001 /*
002 @license.text@
003 */
004 package biz.hammurapi.antlr;
005
006 import java.awt.event.WindowAdapter;
007 import java.awt.event.WindowEvent;
008 import java.io.PrintStream;
009
010 import antlr.CommonAST;
011 import biz.hammurapi.legacy.review.SourceMarker;
012 import biz.hammurapi.util.PoliteVisitor;
013 import biz.hammurapi.util.Visitable;
014 import biz.hammurapi.util.Visitor;
015
016
017 /**
018 * Holds line and column numbers
019 * @author Pavel Vlasov
020 * @version $Revision: 1.8 $
021 */
022 public class AST extends CommonAST implements SourceMarker, Visitable {
023 /**
024 * Comment for <code>serialVersionUID</code>
025 */
026 private static final long serialVersionUID = -3283377943637002016L;
027 private int line;
028 private int column;
029 private boolean childrenQueried=false;
030 private AST parent;
031 private String id;
032 private Token token;
033 private boolean loaded=false;
034 // private LanguageElement owner;
035
036 private Token firstToken;
037 private Token lastToken;
038
039 public void initialize(antlr.Token tok) {
040 super.initialize(tok);
041 line=tok.getLine();
042 column=tok.getColumn();
043 this.token=(Token) tok;
044 this.firstToken=this.token;
045 this.lastToken=this.token;
046 }
047
048 public void initialize(antlr.collections.AST node) {
049 super.initialize(node);
050 if (node instanceof AST) {
051 line=((AST) node).getLine();
052 column=((AST) node).getColumn();
053 }
054 }
055
056 public int getLine() {
057 queryChildren();
058 return line;
059 }
060
061 public int getColumn() {
062 queryChildren();
063 return column;
064 }
065
066 public Token getToken() {
067 return token;
068 }
069
070 /**
071 * Returns leftmost non-zero column among itself and all children
072 */
073 public int getLeftColumn() {
074 int ret=getColumn();
075 for (AST child=(AST) getFirstChild(); child!=null; child=(AST) child.getNextSibling()) {
076 int c=child.getLeftColumn();
077 if (c!=0 && c<ret) ret=c;
078 }
079 return ret;
080 }
081
082 public AST getParent() {
083 return parent;
084 }
085
086 protected void setParent(AST parent) {
087 this.parent=parent;
088 }
089
090 /**************************************************************************
091 * Parent calculation
092 *************************************************************************/
093 public void addChild(antlr.collections.AST node) {
094 super.addChild(node);
095 if (node instanceof AST) {
096 ((AST) node).parent=this;
097 }
098 }
099
100 public void setFirstChild(antlr.collections.AST c) {
101 super.setFirstChild(c);
102 if (c instanceof AST) {
103 ((AST) c).parent=this;
104 }
105 }
106
107 public void setNextSibling(antlr.collections.AST n) {
108 antlr.collections.AST currentNextSibling=getNextSibling();
109 if (currentNextSibling instanceof AST) {
110 ((AST) currentNextSibling).setPrevSibling(null);
111 }
112
113 super.setNextSibling(n);
114
115
116 if (n instanceof AST) {
117 ((AST) n).setParent(parent);
118 ((AST) n).setPrevSibling(this);
119 }
120 }
121
122 private AST prevSibling;
123
124 public AST getPrevSibling() {
125 return prevSibling;
126 }
127
128 protected void setPrevSibling(AST prevSibling) {
129 this.prevSibling=prevSibling;
130 }
131
132 /**
133 * Removes AST from tree
134 */
135 public void remove() {
136 if (parent!=null && parent.getFirstChild()==this) {
137 parent.setFirstChild(getNextSibling());
138 }
139
140 parent=null;
141
142 if (prevSibling==null) {
143 if (getNextSibling() instanceof AST) {
144 ((AST) getNextSibling()).setPrevSibling(null);
145 }
146 } else {
147 prevSibling.setNextSibling(getNextSibling());
148 }
149
150 setPrevSibling(null);
151 }
152
153 /**
154 * Reads column and line from children if its own are 0
155 */
156 private void queryChildren() {
157 if (!childrenQueried) {
158 childrenQueried=true;
159 for (AST child = (AST) getFirstChild(); child != null ; child = (AST) child.getNextSibling()) {
160 if (line==0 && column==0 && child.getLine()!=0) {
161 line=child.getLine();
162 column=child.getColumn();
163 }
164
165 Token cft=child.getFirstToken();
166 if (cft!=null && (firstToken==null || cft.compareTo(firstToken)<0)) {
167 firstToken=cft;
168 }
169
170 Token clt=child.getLastToken();
171 if (clt!=null && (lastToken==null || clt.compareTo(lastToken)>0)) {
172 lastToken=clt;
173 }
174 }
175 }
176 }
177
178 private String sourceURL;
179
180 public String getSourceURL() {
181 return sourceURL;
182 }
183
184 public void setSourceURL(String sourceURL) {
185 this.sourceURL=sourceURL;
186 }
187
188 /**
189 * Indicates that the node has been processed by superclass and can be ignored
190 * @return Returns the loaded.
191 */
192 boolean isLoaded() {
193 return loaded;
194 }
195
196 /**
197 * @param loaded The loaded to set.
198 */
199 void setLoaded(boolean loaded) {
200 this.loaded = loaded;
201 }
202
203 public boolean equals(Object obj) {
204 if (obj==null) {
205 return false;
206 }
207
208 if (obj==this) {
209 return true;
210 }
211
212 if (getClass().equals(obj.getClass())) {
213 return false;
214 }
215
216 AST ast=(AST) obj;
217
218 if (super.equals(ast)) {
219
220 if (ast.getNumberOfChildren()!=getNumberOfChildren()) {
221 return false;
222 }
223
224 for (AST child=(AST) getFirstChild(), otherChild=(AST) ast.getFirstChild(); child!=null && otherChild!=null; child=(AST) child.getNextSibling(), otherChild=(AST) otherChild.getNextSibling()) {
225 if (!child.equals(ast.getFirstChild())) {
226 return false;
227 }
228 }
229 return true;
230 }
231
232 return false;
233 }
234
235 public int hashCode() {
236 int ret=getType();
237 ret^=getClass().getName().hashCode();
238
239 if (getText()!=null) {
240 ret^=getText().hashCode();
241 }
242 for (AST child=(AST) getFirstChild(); child!=null; child=(AST) child.getNextSibling()) {
243 ret^=child.hashCode();
244 }
245 return ret;
246 }
247
248 public int getSize() {
249 int ret=1;
250 for (AST child=(AST) getFirstChild(); child!=null; child=(AST) child.getNextSibling()) {
251 ret+=child.getSize();
252 }
253
254 return ret;
255 }
256
257 public Token getFirstToken() {
258 queryChildren();
259 return firstToken;
260 }
261
262 public Token getLastToken() {
263 queryChildren();
264 return lastToken;
265 }
266
267 // protected LanguageElement getOwner() {
268 // return owner;
269 // }
270
271 // protected void setOwner(LanguageElement owner) {
272 // this.owner = owner;
273 // }
274
275 public String getId() {
276 return id;
277 }
278
279 private void enumerateChildren() {
280 int i=0;
281 for (AST node=(AST) getFirstChild(); node!=null; node=(AST) node.getNextSibling(), i++) {
282 node.id = id==null ? String.valueOf(i) : id+'.'+i;
283 node.enumerateChildren();
284 }
285 }
286
287 public void enumerate() {
288 int i=0;
289 for (AST node=this; node!=null; node=(AST) node.getNextSibling(), i++) {
290 node.id=String.valueOf(i);
291 node.enumerateChildren();
292 }
293 }
294
295 public boolean accept(Visitor visitor) {
296 if (visitor.visit(this)) {
297 if (getFirstChild()!=null) {
298 ((Visitable) getFirstChild()).accept(visitor);
299 }
300
301 if (visitor instanceof PoliteVisitor) {
302 ((PoliteVisitor) visitor).leave(this);
303 }
304
305 if (getNextSibling()!=null) {
306 return ((Visitable) getNextSibling()).accept(visitor);
307 }
308
309 return true;
310 }
311
312 return false;
313 }
314
315 public Integer getSourceId() {
316 return null;
317 }
318
319 public void print(String[] tokenNames, boolean withSiblings) {
320 print(tokenNames, System.out, 0, withSiblings);
321 }
322
323 public void print(String[] tokenNames, PrintStream out, int level, boolean withSiblings) {
324 if (withSiblings) {
325 visitAll(tokenNames, this, level, out);
326 } else {
327 visit(tokenNames, this, level, out);
328 }
329 }
330
331 protected void tabs(PrintStream out, int level) {
332 for (int i = 0; i < level; i++) {
333 out.print(" ");
334 }
335 }
336
337 protected void visit(String[] tokenNames, AST node, int level, PrintStream out) {
338 tabs(out, level);
339 out.print(tokenNames[node.getType()]+" ");
340 out.print(node.getText()==null ? "nil" : node.getText());
341 out.println(" "+node.getLine()+(node.getColumn()==node.getLeftColumn() ? ":"+node.getColumn() : ":"+node.getColumn()+"("+node.getLeftColumn()+") "));
342 visitAll(tokenNames, (AST) node.getFirstChild(), level+1, out);
343 }
344
345 protected void visitAll(String[] tokenNames, AST node, int level, PrintStream out) {
346 while (node!=null) {
347 visit(tokenNames, node, level, out);
348 node = (AST) node.getNextSibling();
349 }
350 }
351
352 public void show(String[] tokenNames) {
353 final ASTFrame frame = new ASTFrame("AST: "+getText(), this, tokenNames);
354 frame.setVisible(true);
355 frame.addWindowListener(new WindowAdapter() {
356 public void windowClosing(WindowEvent e) {
357 frame.setVisible(false); // hide the Frame
358 frame.dispose();
359 }
360 });
361 }
362
363 public void showWithSiblings(String title, String[] tokenNames) {
364 AST root=new AST();
365 root.setText(title);
366 root.setFirstChild(this);
367 final ASTFrame frame = new ASTFrame(title, root, tokenNames);
368 frame.setVisible(true);
369 frame.addWindowListener(new WindowAdapter() {
370 public void windowClosing(WindowEvent e) {
371 frame.setVisible(false); // hide the Frame
372 frame.dispose();
373 }
374 });
375 }
376 }