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