1
package com.jogamp.gluegen.cgram;
3
import antlr.collections.AST;
4
import antlr.CommonAST;
6
import java.lang.reflect.*;
7
import java.util.Hashtable;
8
import java.util.Enumeration;
11
Class TNode is an implementation of the AST interface
12
and adds many useful features:
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
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.
22
It stores line numbers for nodes.
24
Searches for parents and children of a tree can be done
27
The tree can be printed to System.out using a lisp-style syntax.
32
public class TNode extends CommonAST {
34
protected String text;
35
protected int lineNum = 0;
36
protected TNode defNode;
39
protected boolean marker = false;
40
protected Hashtable attributes = null;
41
static String tokenVocabulary;
46
/** Set the token vocabulary to a tokentypes class
49
public static void setTokenVocabulary(String s) {
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()));
62
public void initialize(AST tr) {
66
setLineNum(t.getLineNum());
67
setDefNode(t.getDefNode());
68
this.attributes = t.getAttributesTable();
72
/** Get the token type for this node */
73
public int getType() { return ttype; }
75
/** Set the token type for this node */
76
public void setType(int ttype_) {
80
/** Get the marker value for this node.
81
This member is a general-use marker.
83
public boolean getMarker() { return marker; }
85
/** Set the marker value for this node.
86
This property is a general-use boolean marker.
88
public void setMarker(boolean marker_) {
92
/** get the hashtable that holds attribute values.
94
public Hashtable getAttributesTable() {
95
if(attributes == null)
96
attributes = new Hashtable(7);
100
/** set an attribute in the attribute table.
102
public void setAttribute(String attrName, Object value) {
103
if(attributes == null)
104
attributes = new Hashtable(7);
105
attributes.put(attrName,value);
108
/** lookup the attribute name in the attribute table.
109
If the value does not exist, it returns null.
111
public Object getAttribute(String attrName) {
112
if(attributes == null)
115
return attributes.get(attrName);
118
/** Get the line number for this node.
119
If the line number is 0, search for a non-zero line num among children */
120
public int getLineNum() {
127
return ((TNode)down).getLocalLineNum();
130
public int getLocalLineNum() {
138
return ((TNode)right).getLocalLineNum();
140
return ((TNode)down).getLocalLineNum();
143
/** Set the line number for this node */
144
public void setLineNum(int lineNum_) {
148
/** Get the token text for this node */
149
public String getText() { return text; }
151
/** Set the token text for this node */
152
public void setText(String text_) {
156
/** Returns the text for this node and all children */
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());
163
return buf.toString();
166
/** return the last child of this node, or null if there is none */
167
public TNode getLastChild() {
168
TNode down = (TNode)getFirstChild();
170
return down.getLastSibling();
175
/** return the last sibling of this node, which is
176
this if the next sibling is null */
177
public TNode getLastSibling() {
178
TNode next = (TNode)getNextSibling();
180
return next.getLastSibling();
185
/** return the first sibling of this node, which is
186
this if the prev sibling is null */
187
public TNode getFirstSibling() {
188
TNode prev = (TNode)left;
190
return prev.getFirstSibling();
196
/** return the parent node of this node */
197
public TNode getParent() {
198
return (TNode)getFirstSibling().up;
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.
207
public void addSibling(AST node) {
208
if(node == null) return;
209
TNode next = (TNode)right;
211
((TNode)node).left = this;
212
TNode nodeLastSib = ((TNode)node).getLastSibling();
213
nodeLastSib.right = next;
215
next.left = nodeLastSib;
219
/** return the number of children of this node */
220
public int numberOfChildren() {
222
AST child = getFirstChild();
223
while(child != null) {
225
child = child.getNextSibling();
231
/** remove this node from the tree, resetting sibling and parent
232
pointers as necessary. This method maintains double-linking */
233
public void removeSelf() {
234
TNode parent = (TNode)up;
235
TNode prev = (TNode)left;
236
TNode next = (TNode)right;
242
next.left = prev; // which should be null
254
/** return the def node for this node */
255
public TNode getDefNode() {
259
/** set the def node for this node */
260
public void setDefNode(TNode n) {
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!
269
public TNode deepCopy() {
270
TNode copy = new TNode();
273
copy.lineNum = lineNum;
274
copy.defNode = defNode;
275
if(attributes != null)
276
copy.attributes = (Hashtable)attributes.clone();
278
copy.down = ((TNode)down).deepCopyWithRightSiblings();
284
/** return a deep copy of this node, all sub nodes,
286
New tree is doubleLinked, with no parent or left siblings.
287
defNode is not copied */
288
public TNode deepCopyWithRightSiblings() {
289
TNode copy = new TNode();
292
copy.lineNum = lineNum;
293
copy.defNode = defNode;
294
if(attributes != null)
295
copy.attributes = (Hashtable)attributes.clone();
297
copy.down = ((TNode)down).deepCopyWithRightSiblings();
299
copy.right = ((TNode)right).deepCopyWithRightSiblings();
305
/** return a short string representation of the node */
306
public String toString() {
307
StringBuffer str = new StringBuffer( getNameForType(getType()) +
308
"[" + getText() + ", " + "]");
310
if(this.getLineNum() != 0)
311
str.append(" line:" + (this.getLineNum() ) );
313
Enumeration keys = (this.getAttributesTable().keys());
314
while (keys.hasMoreElements()) {
315
String key = (String) keys.nextElement();
316
str.append(" " + key + ":" + (this.getAttribute(key)));
319
return str.toString();
323
/** print given tree to System.out */
324
public static void printTree(AST t) {
325
if (t == null) return;
327
System.out.print("\n");
331
/** protected method that does the work of printing */
332
protected static void printASTNode(AST t, int indent) {
334
child1 = t.getFirstChild();
336
System.out.print("\n");
337
for(int i = 0; i < indent; i++)
338
System.out.print(" ");
341
System.out.print("(");
343
String s = t.getText();
344
if(s != null && s.length() > 0) {
345
System.out.print(getNameForType(t.getType()));
346
System.out.print(": \"" + s + "\"");
349
System.out.print(getNameForType(t.getType()));
350
if(((TNode)t).getLineNum() != 0)
351
System.out.print(" line:" + ((TNode)t).getLineNum() );
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));
358
TNode def = ((TNode)t).getDefNode();
360
System.out.print("[" + getNameForType(def.getType()) + "]");
364
printASTNode(child1,indent + 1);
366
System.out.print("\n");
367
for(int i = 0; i < indent; i++)
368
System.out.print(" ");
369
System.out.print(")");
372
next = t.getNextSibling();
374
printASTNode(next,indent);
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. */
381
public static String getNameForType(int t) {
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;
392
/** set up reverse links between this node and its first
393
child and its first sibling, and link those as well */
394
public void doubleLink() {
395
TNode right = (TNode)getNextSibling();
400
TNode down = (TNode)getFirstChild();
407
/** find first parent of the given type,
408
return null on failure */
409
public TNode parentOfType(int type) {
414
return left.parentOfType(type);
416
if(up.getType() == type)
418
return up.parentOfType(type);
421
/** find the first child of the node
422
of the given type, return null on failure */
423
public TNode firstChildOfType(int type) {
424
TNode down = (TNode)getFirstChild();
427
if(down.getType() == type)
429
return down.firstSiblingOfType(type);
432
/** find the first sibling of the node
433
of the given type, return null on failure */
434
public TNode firstSiblingOfType(int type) {
435
TNode right = (TNode)getNextSibling();
438
if(right.getType() == type)
440
return right.firstSiblingOfType(type);