1 package antlr;
2
3 * A Child-Sibling Tree.
5 *
6 * A tree with PLUS at the root and with two children 3 and 4 is
7 * structured as:
8 *
9 * PLUS
10 * |
11 * 3 -- 4
12 *
13 * and can be specified easily in LISP notation as
14 *
15 * (PLUS 3 4)
16 *
17 * where every '(' starts a new subtree.
18 *
19 * These trees are particular useful for translators because of
20 * the flexibility of the children lists. They are also very easy
21 * to walk automatically, whereas trees with specific children
22 * reference fields can't easily be walked automatically.
23 *
24 * This class contains the basic support for an AST.
25 * Most people will create ASTs that are subclasses of
26 * BaseAST or of CommonAST.
27 */
28 import antlr.collections.AST;
29 import antlr.collections.ASTEnumeration;
30 import antlr.collections.impl.ASTEnumerator;
31 import antlr.collections.impl.Vector;
32
33 public abstract class BaseAST implements AST {
34 protected BaseAST down;
35 protected BaseAST right;
36
37 private static boolean verboseStringConversion = false;
38 private static String[] tokenNames = null;
39
40
41 public void addChild(AST node) {
42 if ( node==null ) return;
43 BaseAST t = this.down;
44 if ( t!=null ) {
45 while ( t.right!=null ) {
46 t = t.right;
47 }
48 t.right = (BaseAST)node;
49 }
50 else {
51 this.down = (BaseAST)node;
52 }
53 }
54 private void doWorkForFindAll(Vector v, AST target, boolean partialMatch) {
55 AST sibling;
56
57 siblingWalk:
59 for (sibling=this;
60 sibling!=null;
61 sibling=sibling.getNextSibling())
62 {
63 if ( (partialMatch && sibling.equalsTreePartial(target)) ||
64 (!partialMatch && sibling.equalsTree(target)) ) {
65 v.appendElement(sibling);
66 }
67 if ( partialMatch ) if ( sibling.equalsTreePartial(target) ) {
69 // subtree rooted at 'sibling' exact or partial equals 'target'
70 v.appendElement(sibling);
71 }
72 if ( !partialMatch ) if ( sibling.equalsTree(target) ) {
73 // subtree rooted at 'sibling' exact or partial equals 'target'
74 v.appendElement(sibling);
75 }
76 */
77 if ( sibling.getFirstChild()!=null ) {
79 ((BaseAST)sibling.getFirstChild()).doWorkForFindAll(v, target, partialMatch);
80 }
81 }
82 }
83
84 public boolean equals(AST t) {
85 if ( t==null ) return false;
86 return this.getText().equals(t.getText()) &&
87 this.getType() == t.getType();
88 }
89 * 'this' reference is considered the start of a sibling list.
91 */
92 public boolean equalsList(AST t) {
93 AST sibling;
94
95 if (t == null) {
97 return false;
98 }
99
100 for (sibling = this; sibling != null && t != null; sibling = sibling.getNextSibling(), t = t.getNextSibling()) {
102 if (!sibling.equals(t)) {
104 return false;
105 }
106 if (sibling.getFirstChild() != null) {
108 if (!sibling.getFirstChild().equalsList(t.getFirstChild())) {
109 return false;
110 }
111 }
112 else if (t.getFirstChild() != null) {
114 return false;
115 }
116 }
117 if (sibling == null && t == null) {
118 return true;
119 }
120 return false;
122 }
123 * The siblings of the root are NOT ignored.
125 */
126 public boolean equalsListPartial(AST sub) {
127 AST sibling;
128
129 if ( sub==null ) {
131 return true;
132 }
133
134 for (sibling=this;
136 sibling!=null&&sub!=null;
137 sibling=sibling.getNextSibling(), sub=sub.getNextSibling())
138 {
139 if ( sibling.getType() != sub.getType() ) return false;
141 if ( sibling.getFirstChild()!=null ) {
143 if ( !sibling.getFirstChild().equalsListPartial(sub.getFirstChild()) ) return false;
144 }
145 }
146 if ( sibling==null && sub!=null ) {
147 return false;
149 }
150 return true;
152 }
153 * of 'this' are ignored.
155 */
156 public boolean equalsTree(AST t) {
157 if ( !this.equals(t) ) return false;
159 if ( this.getFirstChild()!=null ) {
161 if ( !this.getFirstChild().equalsList(t.getFirstChild()) ) return false;
162 }
163 else if (t.getFirstChild() != null) {
165 return false;
166 }
167 return true;
168 }
169 * of 'this' are ignored.
171 */
172 public boolean equalsTreePartial(AST sub) {
173 if ( sub==null ) {
175 return true;
176 }
177
178 if ( !this.equals(sub) ) return false;
180 if ( this.getFirstChild()!=null ) {
182 if ( !this.getFirstChild().equalsListPartial(sub.getFirstChild()) ) return false;
183 }
184 return true;
185 }
186 * an ASTEnumerator that lets the caller walk the list
188 * of subtree roots found herein.
189 */
190 public ASTEnumeration findAll(AST target) {
191 Vector roots = new Vector(10);
192 AST sibling;
193
194 if ( target==null ) {
196 return null;
197 }
198
199 doWorkForFindAll(roots, target, false);
201 return new ASTEnumerator(roots);
202 }
203 * an ASTEnumerator that lets the caller walk the list
205 * of subtree roots found herein.
206 */
207 public ASTEnumeration findAllPartial(AST sub) {
208 Vector roots = new Vector(10);
209 AST sibling;
210
211 if ( sub==null ) {
213 return null;
214 }
215
216 doWorkForFindAll(roots, sub, true);
218 return new ASTEnumerator(roots);
219 }
220
221 public AST getFirstChild() {
222 return down;
223 }
224
225 public AST getNextSibling() {
226 return right;
227 }
228
229 public String getText() { return ""; }
230
231 public int getType() { return 0; }
232 public abstract void initialize(int t, String txt);
233 public abstract void initialize(AST t);
234 public abstract void initialize(Token t);
235
236 public void removeChildren() {
237 down = null;
238 }
239 public void setFirstChild(AST c) {
240 down = (BaseAST)c;
241 }
242 public void setNextSibling(AST n) {
243 right = (BaseAST)n;
244 }
245
246 public void setText(String text) {;}
247
248 public void setType(int ttype) {;}
249 public static void setVerboseStringConversion(boolean verbose, String[] names) {
250 verboseStringConversion = verbose;
251 tokenNames = names;
252 }
253 public String toString() {
254 StringBuffer b = new StringBuffer();
255 if ( verboseStringConversion &&
257 !getText().equalsIgnoreCase(tokenNames[getType()]) &&
258 !getText().equalsIgnoreCase(Tool.stripFrontBack(tokenNames[getType()],"\"","\"")) ) {
259 b.append('[');
260 b.append(getText());
261 b.append(",<");
262 b.append(tokenNames[getType()]);
263 b.append(">]");
264 return b.toString();
265 }
266 return getText();
267 }
268
269 public String toStringList() {
270 AST t = this;
271 String ts="";
272 if ( t.getFirstChild()!=null ) ts+=" (";
273 ts += " "+this.toString();
274 if ( t.getFirstChild()!=null ) {
275 ts += ((BaseAST)t.getFirstChild()).toStringList();
276 }
277 if ( t.getFirstChild()!=null ) ts+=" )";
278 if ( t.getNextSibling()!=null ) {
279 ts += ((BaseAST)t.getNextSibling()).toStringList();
280 }
281 return ts;
282 }
283 public String toStringTree() {
284 AST t = this;
285 String ts="";
286 if ( t.getFirstChild()!=null ) ts+=" (";
287 ts += " "+this.toString();
288 if ( t.getFirstChild()!=null ) {
289 ts += ((BaseAST)t.getFirstChild()).toStringList();
290 }
291 if ( t.getFirstChild()!=null ) ts+=" )";
292 return ts;
293 }
294 }
295