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