BaseAST.java
上传用户:afrynkmhm
上传日期:2007-01-06
资源大小:1262k
文件大小:11k
源码类别:

编译器/解释器

开发平台:

Others

  1. package antlr;
  2. /* ANTLR Translator Generator
  3.  * Project led by Terence Parr at http://www.jGuru.com
  4.  * Software rights: http://www.antlr.org/RIGHTS.html
  5.  *
  6.  * $Id: //depot/code/org.antlr/release/antlr-2.7.0/antlr/BaseAST.java#1 $
  7.  */
  8. import antlr.collections.AST;
  9. import antlr.collections.ASTEnumeration;
  10. import antlr.collections.impl.ASTEnumerator;
  11. import antlr.collections.impl.Vector;
  12. import java.io.Serializable;
  13. import java.io.IOException;
  14. import java.io.Writer;
  15. /**
  16.  * A Child-Sibling Tree.
  17.  *
  18.  * A tree with PLUS at the root and with two children 3 and 4 is
  19.  * structured as:
  20.  *
  21.  * PLUS
  22.  *   |
  23.  *   3 -- 4
  24.  *
  25.  * and can be specified easily in LISP notation as
  26.  *
  27.  * (PLUS 3 4)
  28.  *
  29.  * where every '(' starts a new subtree.
  30.  *
  31.  * These trees are particular useful for translators because of
  32.  * the flexibility of the children lists.  They are also very easy
  33.  * to walk automatically, whereas trees with specific children
  34.  * reference fields can't easily be walked automatically.
  35.  *
  36.  * This class contains the basic support for an AST.
  37.  * Most people will create ASTs that are subclasses of
  38.  * BaseAST or of CommonAST.
  39.  */
  40. public abstract class BaseAST implements AST, Serializable {
  41.     protected BaseAST down;
  42.     protected BaseAST right;
  43.     private static boolean verboseStringConversion = false;
  44.     private static String[] tokenNames = null;
  45.     /**Add a node to the end of the child list for this node */
  46.     public void addChild(AST node) {
  47. if ( node==null ) return;
  48. BaseAST t = this.down;
  49. if ( t!=null ) {
  50.     while ( t.right!=null ) {
  51. t = t.right;
  52.     }
  53.     t.right = (BaseAST)node;
  54. }
  55. else {
  56.     this.down = (BaseAST)node;
  57. }
  58.     }
  59.     private void doWorkForFindAll(Vector v, AST target, boolean partialMatch) {
  60. AST sibling;
  61. // Start walking sibling lists, looking for matches.
  62.     siblingWalk:
  63. for (sibling=this;
  64.      sibling!=null;
  65.      sibling=sibling.getNextSibling())
  66.     {
  67. if ( (partialMatch && sibling.equalsTreePartial(target)) ||
  68.      (!partialMatch && sibling.equalsTree(target)) ) {
  69.     v.appendElement(sibling);
  70. }
  71. // regardless of match or not, check any children for matches
  72. if ( sibling.getFirstChild()!=null ) {
  73.     ((BaseAST)sibling.getFirstChild()).doWorkForFindAll(v, target, partialMatch);
  74. }
  75.     }
  76.     }
  77.     /** Is node t equal to this in terms of token type and text? */
  78.     public boolean equals(AST t) {
  79. if ( t==null ) return false;
  80. return this.getText().equals(t.getText()) &&
  81.     this.getType() == t.getType();
  82.     }
  83.     /** Is t an exact structural and equals() match of this tree.  The
  84.  *  'this' reference is considered the start of a sibling list.
  85.  */
  86.     public boolean equalsList(AST t) {
  87. AST sibling;
  88. // the empty tree is not a match of any non-null tree.
  89. if (t == null) {
  90.     return false;
  91. }
  92. // Otherwise, start walking sibling lists.  First mismatch, return false.
  93. for (sibling = this; sibling != null && t != null; sibling = sibling.getNextSibling(), t = t.getNextSibling()) {
  94.     // as a quick optimization, check roots first.
  95.     if (!sibling.equals(t)) {
  96. return false;
  97.     }
  98.     // if roots match, do full list match test on children.
  99.     if (sibling.getFirstChild() != null) {
  100. if (!sibling.getFirstChild().equalsList(t.getFirstChild())) {
  101.     return false;
  102. }
  103.     }
  104.     // sibling has no kids, make sure t doesn't either
  105.     else if (t.getFirstChild() != null) {
  106. return false;
  107.     }
  108. }
  109. if (sibling == null && t == null) {
  110.     return true;
  111. }
  112. // one sibling list has more than the other
  113. return false;
  114.     }
  115.     /** Is 'sub' a subtree of this list?
  116.      *  The siblings of the root are NOT ignored.
  117.      */
  118.     public boolean equalsListPartial(AST sub) {
  119. AST sibling;
  120. // the empty tree is always a subset of any tree.
  121. if ( sub==null ) {
  122.     return true;
  123. }
  124. // Otherwise, start walking sibling lists.  First mismatch, return false.
  125. for (sibling=this;
  126.      sibling!=null&&sub!=null;
  127.      sibling=sibling.getNextSibling(), sub=sub.getNextSibling())
  128.     {
  129. // as a quick optimization, check roots first.
  130. if ( !sibling.equals(sub) ) return false;
  131. // if roots match, do partial list match test on children.
  132. if ( sibling.getFirstChild()!=null ) {
  133.     if ( !sibling.getFirstChild().equalsListPartial(sub.getFirstChild()) ) return false;
  134. }
  135.     }
  136. if ( sibling==null && sub!=null ) {
  137.     // nothing left to match in this tree, but subtree has more
  138.     return false;
  139. }
  140. // either both are null or sibling has more, but subtree doesn't
  141. return true;
  142.     }
  143.     /** Is tree rooted at 'this' equal to 't'?  The siblings
  144.      *  of 'this' are ignored.
  145.      */
  146.     public boolean equalsTree(AST t) {
  147. // check roots first.
  148. if ( !this.equals(t) ) return false;
  149. // if roots match, do full list match test on children.
  150. if ( this.getFirstChild()!=null ) {
  151.     if ( !this.getFirstChild().equalsList(t.getFirstChild()) ) return false;
  152. }
  153. // sibling has no kids, make sure t doesn't either
  154. else if (t.getFirstChild() != null) {
  155.     return false;
  156. }
  157. return true;
  158.     }
  159.     /** Is 't' a subtree of the tree rooted at 'this'?  The siblings
  160.      *  of 'this' are ignored. 
  161.      */
  162.     public boolean equalsTreePartial(AST sub) {
  163. // the empty tree is always a subset of any tree.
  164. if ( sub==null ) {
  165.     return true;
  166. }
  167. // check roots first.
  168. if ( !this.equals(sub) ) return false;
  169. // if roots match, do full list partial match test on children.
  170. if ( this.getFirstChild()!=null ) {
  171.     if ( !this.getFirstChild().equalsListPartial(sub.getFirstChild()) ) return false;
  172. }
  173. return true;
  174.     }
  175.     /** Walk the tree looking for all exact subtree matches.  Return
  176.      *  an ASTEnumerator that lets the caller walk the list
  177.      *  of subtree roots found herein.
  178.      */
  179.     public ASTEnumeration findAll(AST target) {
  180. Vector roots = new Vector(10);
  181. AST sibling;
  182. // the empty tree cannot result in an enumeration
  183. if ( target==null ) {
  184.     return null;
  185. }
  186. doWorkForFindAll(roots, target, false);  // find all matches recursively
  187. return new ASTEnumerator(roots);
  188.     }
  189.     /** Walk the tree looking for all subtrees.  Return
  190.      *  an ASTEnumerator that lets the caller walk the list
  191.      *  of subtree roots found herein.
  192.      */
  193.     public ASTEnumeration findAllPartial(AST sub) {
  194. Vector roots = new Vector(10);
  195. AST sibling;
  196. // the empty tree cannot result in an enumeration
  197. if ( sub==null ) {
  198.     return null;
  199. }
  200. doWorkForFindAll(roots, sub, true);  // find all matches recursively
  201. return new ASTEnumerator(roots);
  202.     }
  203.     /** Get the first child of this node; null if not children */
  204.     public AST getFirstChild() {
  205. return down;
  206.     }
  207.     /** Get the next sibling in line after this one */
  208.     public AST getNextSibling() {
  209. return right;
  210.     }
  211.     /** Get the token text for this node */
  212.     public String getText() { return ""; }
  213.     /** Get the token type for this node */
  214.     public int getType() { return 0; }
  215.     public abstract void initialize(int t, String txt);
  216.     public abstract void initialize(AST t);
  217.     public abstract void initialize(Token t);
  218. /** Remove all children */
  219.     public void removeChildren() {
  220. down = null;
  221.     }
  222.     public void setFirstChild(AST c) {
  223. down = (BaseAST)c;
  224.     }
  225.     public void setNextSibling(AST n) {
  226. right = (BaseAST)n;
  227.     }
  228.     /** Set the token text for this node */
  229.     public void setText(String text) {;}
  230.     /** Set the token type for this node */
  231.     public void setType(int ttype) {;}
  232.     public static void setVerboseStringConversion(boolean verbose, String[] names) {
  233. verboseStringConversion = verbose;
  234. tokenNames = names;
  235.     }
  236.     public String toString() {
  237. StringBuffer b = new StringBuffer();
  238. // if verbose and type name not same as text (keyword probably)
  239. if ( verboseStringConversion &&
  240.      !getText().equalsIgnoreCase(tokenNames[getType()]) &&
  241.      !getText().equalsIgnoreCase(Tool.stripFrontBack(tokenNames[getType()],""",""")) ) {
  242.     b.append('[');
  243.     b.append(getText());
  244.     b.append(",<");
  245.     b.append(tokenNames[getType()]);
  246.     b.append(">]");
  247.     return b.toString();
  248. }
  249. return getText();
  250.     }
  251.     /** Print out a child-sibling tree in LISP notation */
  252.     public String toStringList() {
  253. AST t = this;
  254. String ts="";
  255. if ( t.getFirstChild()!=null ) ts+=" (";
  256. ts += " "+this.toString();
  257. if ( t.getFirstChild()!=null ) {
  258.     ts += ((BaseAST)t.getFirstChild()).toStringList();
  259. }
  260. if ( t.getFirstChild()!=null ) ts+=" )";
  261. if ( t.getNextSibling()!=null ) {
  262.     ts += ((BaseAST)t.getNextSibling()).toStringList();
  263. }
  264. return ts;
  265.     }
  266.     public String toStringTree() {
  267. AST t = this;
  268. String ts="";
  269. if ( t.getFirstChild()!=null ) ts+=" (";
  270. ts += " "+this.toString();
  271. if ( t.getFirstChild()!=null ) {
  272.     ts += ((BaseAST)t.getFirstChild()).toStringList();
  273. }
  274. if ( t.getFirstChild()!=null ) ts+=" )";
  275. return ts;
  276.     }
  277.     public static String decode(String text)
  278.     {
  279. char c, c1, c2, c3, c4, c5;
  280. StringBuffer n = new StringBuffer();
  281. for (int i=0; i < text.length(); i++)
  282.     {
  283. c = text.charAt(i);
  284. if (c == '&') {
  285.     c1 = text.charAt(i+1); c2 = text.charAt(i+2);
  286.     c3 = text.charAt(i+3); c4 = text.charAt(i+4);
  287.     c5 = text.charAt(i+5);
  288.     if ( c1 == 'a' && c2 == 'm' && c3 == 'p' && c4 == ';') {
  289. n.append("&");
  290. i += 5;
  291.     }
  292.     else if ( c1 == 'l' && c2 == 't' && c3 == ';') {
  293. n.append("<");
  294. i += 4;
  295.     }
  296.     else if ( c1 == 'g' && c2 == 't' && c3 == ';') {
  297. n.append(">");
  298. i += 4;
  299.     }
  300.     else if ( c1 == 'q' && c2 == 'u' && c3 == 'o' && 
  301.       c4 == 't' && c5 == ';') {
  302. n.append(""");
  303. i += 6;
  304.     }
  305.     else if ( c1 == 'a' && c2 == 'p' && c3 == 'o' && 
  306.       c4 == 's' && c5 == ';') {
  307. n.append("'");
  308. i += 6;
  309.     }
  310.     else n.append("&");
  311. }
  312. else n.append(c);
  313.     }
  314. return new String(n);
  315.     }
  316.     public static String encode(String text)
  317.     {
  318. char c;
  319. StringBuffer n = new StringBuffer();
  320. for (int i=0; i < text.length(); i++)
  321.     {
  322. c = text.charAt(i);
  323. switch (c) {
  324. case '&' : { n.append("&amp;"); break; }
  325. case '<' : { n.append("&lt;"); break; }
  326. case '>' : { n.append("&gt;"); break; }
  327. case '"' : { n.append("&quot;"); break; }
  328. case ''' : { n.append("&apos;"); break; }
  329. default : { n.append(c); break; }
  330. }
  331.     }
  332. return new String(n);
  333.     }
  334.     public void xmlSerializeNode(Writer out)
  335. throws IOException
  336.     {
  337. StringBuffer buf = new StringBuffer(100);
  338. buf.append("<");
  339. buf.append(getClass().getName()+" ");
  340. buf.append("text=""+encode(getText())+"" type=""+
  341.    getType()+""/>");
  342. out.write(buf.toString());
  343.     }
  344.     public void xmlSerializeRootOpen(Writer out)
  345. throws IOException
  346.     {
  347. StringBuffer buf = new StringBuffer(100);
  348. buf.append("<");
  349. buf.append(getClass().getName()+" ");
  350. buf.append("text=""+encode(getText())+"" type=""+
  351.    getType()+"">n");
  352. out.write(buf.toString());
  353.     }
  354.     public void xmlSerializeRootClose(Writer out)
  355. throws IOException
  356.     {
  357. out.write("</"+getClass().getName()+">n");
  358.     }
  359.     public void xmlSerialize(Writer out) throws IOException
  360.     {
  361. // print out this node and all siblings
  362. for (AST node = this; 
  363.      node != null; 
  364.      node = node.getNextSibling())
  365. {
  366.     if (node.getFirstChild() == null) {
  367. // print guts (class name, attributes)
  368. ((BaseAST)node).xmlSerializeNode(out);
  369.     }
  370.     else {
  371. ((BaseAST)node).xmlSerializeRootOpen(out);
  372. // print children
  373. ((BaseAST)node.getFirstChild()).xmlSerialize(out);
  374. // print end tag
  375. ((BaseAST)node).xmlSerializeRootClose(out);
  376.     }
  377. }
  378.     }
  379. }