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    }