1 package com.sun.gluegen.cgram;
2
3 import antlr.collections.AST;
4 import antlr.CommonAST;
5 import antlr.Token;
6 import java.lang.reflect.*;
7 import java.util.Hashtable;
8 import java.util.Enumeration;
9
10 /**
11 Class TNode is an implementation of the AST interface
12 and adds many useful features:
13
14 It is double-linked for reverse searching.
15 (this is currently incomplete, in that method doubleLink() must
16 be called after any changes to the tree to maintain the
17 reverse links).
18
19 It can store a definition node (defNode), so that nodes such
20 as scoped names can refer to the node that defines the name.
21
22 It stores line numbers for nodes.
23
24 Searches for parents and children of a tree can be done
25 based on their type.
26
27 The tree can be printed to System.out using a lisp-style syntax.
28
29
30
31 */
32 public class TNode extends CommonAST {
33 protected int ttype;
34 protected String text;
35 protected int lineNum = 0;
36 protected TNode defNode;
37 protected TNode up;
38 protected TNode left;
39 protected boolean marker = false;
40 protected Hashtable attributes = null;
41 static String tokenVocabulary;
42
43
44
45
46 /** Set the token vocabulary to a tokentypes class
47 generated by antlr.
48 */
setTokenVocabulary(String s)49 public static void setTokenVocabulary(String s) {
50 tokenVocabulary = s;
51 }
52
53
initialize(Token token)54 public void initialize(Token token) {
55 CToken tok = (CToken) token;
56 setText(tok.getText());
57 setType(tok.getType());
58 setLineNum(tok.getLine());
59 setAttribute("source", tok.getSource());
60 setAttribute("tokenNumber", new Integer(tok.getTokenNumber()));
61 }
initialize(AST tr)62 public void initialize(AST tr) {
63 TNode t = (TNode) tr;
64 setText(t.getText());
65 setType(t.getType());
66 setLineNum(t.getLineNum());
67 setDefNode(t.getDefNode());
68 this.attributes = t.getAttributesTable();
69 }
70
71
72 /** Get the token type for this node */
getType()73 public int getType() { return ttype; }
74
75 /** Set the token type for this node */
setType(int ttype_)76 public void setType(int ttype_) {
77 ttype = ttype_;
78 }
79
80 /** Get the marker value for this node.
81 This member is a general-use marker.
82 */
getMarker()83 public boolean getMarker() { return marker; }
84
85 /** Set the marker value for this node.
86 This property is a general-use boolean marker.
87 */
setMarker(boolean marker_)88 public void setMarker(boolean marker_) {
89 marker = marker_;
90 }
91
92 /** get the hashtable that holds attribute values.
93 */
getAttributesTable()94 public Hashtable getAttributesTable() {
95 if(attributes == null)
96 attributes = new Hashtable(7);
97 return attributes;
98 }
99
100 /** set an attribute in the attribute table.
101 */
setAttribute(String attrName, Object value)102 public void setAttribute(String attrName, Object value) {
103 if(attributes == null)
104 attributes = new Hashtable(7);
105 attributes.put(attrName,value);
106 }
107
108 /** lookup the attribute name in the attribute table.
109 If the value does not exist, it returns null.
110 */
getAttribute(String attrName)111 public Object getAttribute(String attrName) {
112 if(attributes == null)
113 return null;
114 else
115 return attributes.get(attrName);
116 }
117
118 /** Get the line number for this node.
119 If the line number is 0, search for a non-zero line num among children */
getLineNum()120 public int getLineNum() {
121 if(lineNum != 0)
122 return lineNum;
123 else
124 if(down == null)
125 return lineNum;
126 else
127 return ((TNode)down).getLocalLineNum();
128 }
129
getLocalLineNum()130 public int getLocalLineNum() {
131 if(lineNum != 0)
132 return lineNum;
133 else
134 if(down == null)
135 if(right == null)
136 return lineNum;
137 else
138 return ((TNode)right).getLocalLineNum();
139 else
140 return ((TNode)down).getLocalLineNum();
141 }
142
143 /** Set the line number for this node */
setLineNum(int lineNum_)144 public void setLineNum(int lineNum_) {
145 lineNum = lineNum_;
146 }
147
148 /** Get the token text for this node */
getText()149 public String getText() { return text; }
150
151 /** Set the token text for this node */
setText(String text_)152 public void setText(String text_) {
153 text = text_;
154 }
155
156 /** Returns the text for this node and all children */
getAllChildrenText()157 public String getAllChildrenText() {
158 StringBuffer buf = new StringBuffer();
159 buf.append(getText());
160 for (TNode node = (TNode) getFirstChild(); node != null; node = (TNode) node.getNextSibling()) {
161 buf.append(node.getText());
162 }
163 return buf.toString();
164 }
165
166 /** return the last child of this node, or null if there is none */
getLastChild()167 public TNode getLastChild() {
168 TNode down = (TNode)getFirstChild();
169 if(down != null)
170 return down.getLastSibling();
171 else
172 return null;
173 }
174
175 /** return the last sibling of this node, which is
176 this if the next sibling is null */
getLastSibling()177 public TNode getLastSibling() {
178 TNode next = (TNode)getNextSibling();
179 if(next != null)
180 return next.getLastSibling();
181 else
182 return this;
183 }
184
185 /** return the first sibling of this node, which is
186 this if the prev sibling is null */
getFirstSibling()187 public TNode getFirstSibling() {
188 TNode prev = (TNode)left;
189 if(prev != null)
190 return prev.getFirstSibling();
191 else
192 return this;
193 }
194
195
196 /** return the parent node of this node */
getParent()197 public TNode getParent() {
198 return (TNode)getFirstSibling().up;
199 }
200
201
202 /** add the new node as a new sibling, inserting it ahead of any
203 existing next sibling. This method maintains double-linking.
204 if node is null, nothing happens. If the node has siblings,
205 then they are added in as well.
206 */
addSibling(AST node)207 public void addSibling(AST node) {
208 if(node == null) return;
209 TNode next = (TNode)right;
210 right = (TNode)node;
211 ((TNode)node).left = this;
212 TNode nodeLastSib = ((TNode)node).getLastSibling();
213 nodeLastSib.right = next;
214 if(next != null)
215 next.left = nodeLastSib;
216 }
217
218
219 /** return the number of children of this node */
numberOfChildren()220 public int numberOfChildren() {
221 int count = 0;
222 AST child = getFirstChild();
223 while(child != null) {
224 count++;
225 child = child.getNextSibling();
226 }
227 return count;
228 }
229
230
231 /** remove this node from the tree, resetting sibling and parent
232 pointers as necessary. This method maintains double-linking */
removeSelf()233 public void removeSelf() {
234 TNode parent = (TNode)up;
235 TNode prev = (TNode)left;
236 TNode next = (TNode)right;
237
238 if(parent != null) {
239 parent.down = next;
240 if(next != null) {
241 next.up = parent;
242 next.left = prev; // which should be null
243 }
244 }
245 else {
246 if(prev != null)
247 prev.right = next;
248 if(next != null)
249 next.left = prev;
250 }
251 }
252
253
254 /** return the def node for this node */
getDefNode()255 public TNode getDefNode() {
256 return defNode;
257 }
258
259 /** set the def node for this node */
setDefNode(TNode n)260 public void setDefNode(TNode n) {
261 defNode = n;
262 }
263
264
265 /** return a deep copy of this node, and all sub nodes.
266 New tree is doubleLinked, with no parent or siblings.
267 Marker value is not copied!
268 */
deepCopy()269 public TNode deepCopy() {
270 TNode copy = new TNode();
271 copy.ttype = ttype;
272 copy.text = text;
273 copy.lineNum = lineNum;
274 copy.defNode = defNode;
275 if(attributes != null)
276 copy.attributes = (Hashtable)attributes.clone();
277 if(down != null)
278 copy.down = ((TNode)down).deepCopyWithRightSiblings();
279 copy.doubleLink();
280 return copy;
281 }
282
283
284 /** return a deep copy of this node, all sub nodes,
285 and right siblings.
286 New tree is doubleLinked, with no parent or left siblings.
287 defNode is not copied */
deepCopyWithRightSiblings()288 public TNode deepCopyWithRightSiblings() {
289 TNode copy = new TNode();
290 copy.ttype = ttype;
291 copy.text = text;
292 copy.lineNum = lineNum;
293 copy.defNode = defNode;
294 if(attributes != null)
295 copy.attributes = (Hashtable)attributes.clone();
296 if(down != null)
297 copy.down = ((TNode)down).deepCopyWithRightSiblings();
298 if(right != null)
299 copy.right = ((TNode)right).deepCopyWithRightSiblings();
300 copy.doubleLink();
301 return copy;
302 }
303
304
305 /** return a short string representation of the node */
toString()306 public String toString() {
307 StringBuffer str = new StringBuffer( getNameForType(getType()) +
308 "[" + getText() + ", " + "]");
309
310 if(this.getLineNum() != 0)
311 str.append(" line:" + (this.getLineNum() ) );
312
313 Enumeration keys = (this.getAttributesTable().keys());
314 while (keys.hasMoreElements()) {
315 String key = (String) keys.nextElement();
316 str.append(" " + key + ":" + (this.getAttribute(key)));
317 }
318
319 return str.toString();
320 }
321
322
323 /** print given tree to System.out */
printTree(AST t)324 public static void printTree(AST t) {
325 if (t == null) return;
326 printASTNode(t,0);
327 System.out.print("\n");
328 }
329
330
331 /** protected method that does the work of printing */
printASTNode(AST t, int indent)332 protected static void printASTNode(AST t, int indent) {
333 AST child1, next;
334 child1 = t.getFirstChild();
335
336 System.out.print("\n");
337 for(int i = 0; i < indent; i++)
338 System.out.print(" ");
339
340 if(child1 != null)
341 System.out.print("(");
342
343 String s = t.getText();
344 if(s != null && s.length() > 0) {
345 System.out.print(getNameForType(t.getType()));
346 System.out.print(": \"" + s + "\"");
347 }
348 else
349 System.out.print(getNameForType(t.getType()));
350 if(((TNode)t).getLineNum() != 0)
351 System.out.print(" line:" + ((TNode)t).getLineNum() );
352
353 Enumeration keys = ((TNode)t).getAttributesTable().keys();
354 while (keys.hasMoreElements()) {
355 String key = (String) keys.nextElement();
356 System.out.print(" " + key + ":" + ((TNode)t).getAttribute(key));
357 }
358 TNode def = ((TNode)t).getDefNode();
359 if(def != null)
360 System.out.print("[" + getNameForType(def.getType()) + "]");
361
362
363 if(child1 != null) {
364 printASTNode(child1,indent + 1);
365
366 System.out.print("\n");
367 for(int i = 0; i < indent; i++)
368 System.out.print(" ");
369 System.out.print(")");
370 }
371
372 next = t.getNextSibling();
373 if(next != null) {
374 printASTNode(next,indent);
375 }
376 }
377
378 /** converts an int tree token type to a name.
379 Does this by reflecting on nsdidl.IDLTreeTokenTypes,
380 and is dependent on how ANTLR 2.00 outputs that class. */
getNameForType(int t)381 public static String getNameForType(int t) {
382 try{
383 Class c = Class.forName(tokenVocabulary);
384 Field[] fields = c.getDeclaredFields();
385 if(t-2 < fields.length)
386 return fields[t-2].getName();
387 } catch (Exception e) { System.out.println(e); }
388 return "unfoundtype: " + t;
389 }
390
391
392 /** set up reverse links between this node and its first
393 child and its first sibling, and link those as well */
doubleLink()394 public void doubleLink() {
395 TNode right = (TNode)getNextSibling();
396 if(right != null) {
397 right.left = this;
398 right.doubleLink();
399 }
400 TNode down = (TNode)getFirstChild();
401 if(down != null) {
402 down.up = this;
403 down.doubleLink();
404 }
405 }
406
407 /** find first parent of the given type,
408 return null on failure */
parentOfType(int type)409 public TNode parentOfType(int type) {
410 if(up == null) {
411 if(left == null)
412 return null;
413 else
414 return left.parentOfType(type);
415 }
416 if(up.getType() == type)
417 return up;
418 return up.parentOfType(type);
419 }
420
421 /** find the first child of the node
422 of the given type, return null on failure */
firstChildOfType(int type)423 public TNode firstChildOfType(int type) {
424 TNode down = (TNode)getFirstChild();
425 if(down == null)
426 return null;
427 if(down.getType() == type)
428 return down;
429 return down.firstSiblingOfType(type);
430 }
431
432 /** find the first sibling of the node
433 of the given type, return null on failure */
firstSiblingOfType(int type)434 public TNode firstSiblingOfType(int type) {
435 TNode right = (TNode)getNextSibling();
436 if(right == null)
437 return null;
438 if(right.getType() == type)
439 return right;
440 return right.firstSiblingOfType(type);
441 }
442
443 }
444