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 }