summaryrefslogtreecommitdiffstats
path: root/src/java/com/jogamp/gluegen/cgram/TNode.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/java/com/jogamp/gluegen/cgram/TNode.java')
-rw-r--r--src/java/com/jogamp/gluegen/cgram/TNode.java443
1 files changed, 443 insertions, 0 deletions
diff --git a/src/java/com/jogamp/gluegen/cgram/TNode.java b/src/java/com/jogamp/gluegen/cgram/TNode.java
new file mode 100644
index 0000000..e9185f9
--- /dev/null
+++ b/src/java/com/jogamp/gluegen/cgram/TNode.java
@@ -0,0 +1,443 @@
+package com.jogamp.gluegen.cgram;
+
+import antlr.collections.AST;
+import antlr.CommonAST;
+import antlr.Token;
+import java.lang.reflect.*;
+import java.util.Hashtable;
+import java.util.Enumeration;
+
+/**
+ Class TNode is an implementation of the AST interface
+ and adds many useful features:
+
+ It is double-linked for reverse searching.
+ (this is currently incomplete, in that method doubleLink() must
+ be called after any changes to the tree to maintain the
+ reverse links).
+
+ It can store a definition node (defNode), so that nodes such
+ as scoped names can refer to the node that defines the name.
+
+ It stores line numbers for nodes.
+
+ Searches for parents and children of a tree can be done
+ based on their type.
+
+ The tree can be printed to System.out using a lisp-style syntax.
+
+
+
+ */
+public class TNode extends CommonAST {
+ protected int ttype;
+ protected String text;
+ protected int lineNum = 0;
+ protected TNode defNode;
+ protected TNode up;
+ protected TNode left;
+ protected boolean marker = false;
+ protected Hashtable attributes = null;
+ static String tokenVocabulary;
+
+
+
+
+ /** Set the token vocabulary to a tokentypes class
+ generated by antlr.
+ */
+ public static void setTokenVocabulary(String s) {
+ tokenVocabulary = s;
+ }
+
+
+public void initialize(Token token) {
+ CToken tok = (CToken) token;
+ setText(tok.getText());
+ setType(tok.getType());
+ setLineNum(tok.getLine());
+ setAttribute("source", tok.getSource());
+ setAttribute("tokenNumber", new Integer(tok.getTokenNumber()));
+}
+public void initialize(AST tr) {
+ TNode t = (TNode) tr;
+ setText(t.getText());
+ setType(t.getType());
+ setLineNum(t.getLineNum());
+ setDefNode(t.getDefNode());
+ this.attributes = t.getAttributesTable();
+}
+
+
+ /** Get the token type for this node */
+ public int getType() { return ttype; }
+
+ /** Set the token type for this node */
+ public void setType(int ttype_) {
+ ttype = ttype_;
+ }
+
+ /** Get the marker value for this node.
+ This member is a general-use marker.
+ */
+ public boolean getMarker() { return marker; }
+
+ /** Set the marker value for this node.
+ This property is a general-use boolean marker.
+ */
+ public void setMarker(boolean marker_) {
+ marker = marker_;
+ }
+
+ /** get the hashtable that holds attribute values.
+ */
+ public Hashtable getAttributesTable() {
+ if(attributes == null)
+ attributes = new Hashtable(7);
+ return attributes;
+ }
+
+ /** set an attribute in the attribute table.
+ */
+ public void setAttribute(String attrName, Object value) {
+ if(attributes == null)
+ attributes = new Hashtable(7);
+ attributes.put(attrName,value);
+ }
+
+ /** lookup the attribute name in the attribute table.
+ If the value does not exist, it returns null.
+ */
+ public Object getAttribute(String attrName) {
+ if(attributes == null)
+ return null;
+ else
+ return attributes.get(attrName);
+ }
+
+ /** Get the line number for this node.
+ If the line number is 0, search for a non-zero line num among children */
+ public int getLineNum() {
+ if(lineNum != 0)
+ return lineNum;
+ else
+ if(down == null)
+ return lineNum;
+ else
+ return ((TNode)down).getLocalLineNum();
+ }
+
+ public int getLocalLineNum() {
+ if(lineNum != 0)
+ return lineNum;
+ else
+ if(down == null)
+ if(right == null)
+ return lineNum;
+ else
+ return ((TNode)right).getLocalLineNum();
+ else
+ return ((TNode)down).getLocalLineNum();
+ }
+
+ /** Set the line number for this node */
+ public void setLineNum(int lineNum_) {
+ lineNum = lineNum_;
+ }
+
+ /** Get the token text for this node */
+ public String getText() { return text; }
+
+ /** Set the token text for this node */
+ public void setText(String text_) {
+ text = text_;
+ }
+
+ /** Returns the text for this node and all children */
+ public String getAllChildrenText() {
+ StringBuffer buf = new StringBuffer();
+ buf.append(getText());
+ for (TNode node = (TNode) getFirstChild(); node != null; node = (TNode) node.getNextSibling()) {
+ buf.append(node.getText());
+ }
+ return buf.toString();
+ }
+
+ /** return the last child of this node, or null if there is none */
+ public TNode getLastChild() {
+ TNode down = (TNode)getFirstChild();
+ if(down != null)
+ return down.getLastSibling();
+ else
+ return null;
+ }
+
+ /** return the last sibling of this node, which is
+ this if the next sibling is null */
+ public TNode getLastSibling() {
+ TNode next = (TNode)getNextSibling();
+ if(next != null)
+ return next.getLastSibling();
+ else
+ return this;
+ }
+
+ /** return the first sibling of this node, which is
+ this if the prev sibling is null */
+ public TNode getFirstSibling() {
+ TNode prev = (TNode)left;
+ if(prev != null)
+ return prev.getFirstSibling();
+ else
+ return this;
+ }
+
+
+ /** return the parent node of this node */
+ public TNode getParent() {
+ return (TNode)getFirstSibling().up;
+ }
+
+
+ /** add the new node as a new sibling, inserting it ahead of any
+ existing next sibling. This method maintains double-linking.
+ if node is null, nothing happens. If the node has siblings,
+ then they are added in as well.
+ */
+ public void addSibling(AST node) {
+ if(node == null) return;
+ TNode next = (TNode)right;
+ right = (TNode)node;
+ ((TNode)node).left = this;
+ TNode nodeLastSib = ((TNode)node).getLastSibling();
+ nodeLastSib.right = next;
+ if(next != null)
+ next.left = nodeLastSib;
+ }
+
+
+ /** return the number of children of this node */
+ public int numberOfChildren() {
+ int count = 0;
+ AST child = getFirstChild();
+ while(child != null) {
+ count++;
+ child = child.getNextSibling();
+ }
+ return count;
+ }
+
+
+ /** remove this node from the tree, resetting sibling and parent
+ pointers as necessary. This method maintains double-linking */
+ public void removeSelf() {
+ TNode parent = (TNode)up;
+ TNode prev = (TNode)left;
+ TNode next = (TNode)right;
+
+ if(parent != null) {
+ parent.down = next;
+ if(next != null) {
+ next.up = parent;
+ next.left = prev; // which should be null
+ }
+ }
+ else {
+ if(prev != null)
+ prev.right = next;
+ if(next != null)
+ next.left = prev;
+ }
+ }
+
+
+ /** return the def node for this node */
+ public TNode getDefNode() {
+ return defNode;
+ }
+
+ /** set the def node for this node */
+ public void setDefNode(TNode n) {
+ defNode = n;
+ }
+
+
+ /** return a deep copy of this node, and all sub nodes.
+ New tree is doubleLinked, with no parent or siblings.
+ Marker value is not copied!
+ */
+ public TNode deepCopy() {
+ TNode copy = new TNode();
+ copy.ttype = ttype;
+ copy.text = text;
+ copy.lineNum = lineNum;
+ copy.defNode = defNode;
+ if(attributes != null)
+ copy.attributes = (Hashtable)attributes.clone();
+ if(down != null)
+ copy.down = ((TNode)down).deepCopyWithRightSiblings();
+ copy.doubleLink();
+ return copy;
+ }
+
+
+ /** return a deep copy of this node, all sub nodes,
+ and right siblings.
+ New tree is doubleLinked, with no parent or left siblings.
+ defNode is not copied */
+ public TNode deepCopyWithRightSiblings() {
+ TNode copy = new TNode();
+ copy.ttype = ttype;
+ copy.text = text;
+ copy.lineNum = lineNum;
+ copy.defNode = defNode;
+ if(attributes != null)
+ copy.attributes = (Hashtable)attributes.clone();
+ if(down != null)
+ copy.down = ((TNode)down).deepCopyWithRightSiblings();
+ if(right != null)
+ copy.right = ((TNode)right).deepCopyWithRightSiblings();
+ copy.doubleLink();
+ return copy;
+ }
+
+
+ /** return a short string representation of the node */
+ public String toString() {
+ StringBuffer str = new StringBuffer( getNameForType(getType()) +
+ "[" + getText() + ", " + "]");
+
+ if(this.getLineNum() != 0)
+ str.append(" line:" + (this.getLineNum() ) );
+
+ Enumeration keys = (this.getAttributesTable().keys());
+ while (keys.hasMoreElements()) {
+ String key = (String) keys.nextElement();
+ str.append(" " + key + ":" + (this.getAttribute(key)));
+ }
+
+ return str.toString();
+ }
+
+
+ /** print given tree to System.out */
+ public static void printTree(AST t) {
+ if (t == null) return;
+ printASTNode(t,0);
+ System.out.print("\n");
+ }
+
+
+ /** protected method that does the work of printing */
+ protected static void printASTNode(AST t, int indent) {
+ AST child1, next;
+ child1 = t.getFirstChild();
+
+ System.out.print("\n");
+ for(int i = 0; i < indent; i++)
+ System.out.print(" ");
+
+ if(child1 != null)
+ System.out.print("(");
+
+ String s = t.getText();
+ if(s != null && s.length() > 0) {
+ System.out.print(getNameForType(t.getType()));
+ System.out.print(": \"" + s + "\"");
+ }
+ else
+ System.out.print(getNameForType(t.getType()));
+ if(((TNode)t).getLineNum() != 0)
+ System.out.print(" line:" + ((TNode)t).getLineNum() );
+
+ Enumeration keys = ((TNode)t).getAttributesTable().keys();
+ while (keys.hasMoreElements()) {
+ String key = (String) keys.nextElement();
+ System.out.print(" " + key + ":" + ((TNode)t).getAttribute(key));
+ }
+ TNode def = ((TNode)t).getDefNode();
+ if(def != null)
+ System.out.print("[" + getNameForType(def.getType()) + "]");
+
+
+ if(child1 != null) {
+ printASTNode(child1,indent + 1);
+
+ System.out.print("\n");
+ for(int i = 0; i < indent; i++)
+ System.out.print(" ");
+ System.out.print(")");
+ }
+
+ next = t.getNextSibling();
+ if(next != null) {
+ printASTNode(next,indent);
+ }
+ }
+
+ /** converts an int tree token type to a name.
+ Does this by reflecting on nsdidl.IDLTreeTokenTypes,
+ and is dependent on how ANTLR 2.00 outputs that class. */
+ public static String getNameForType(int t) {
+ try{
+ Class c = Class.forName(tokenVocabulary);
+ Field[] fields = c.getDeclaredFields();
+ if(t-2 < fields.length)
+ return fields[t-2].getName();
+ } catch (Exception e) { System.out.println(e); }
+ return "unfoundtype: " + t;
+ }
+
+
+ /** set up reverse links between this node and its first
+ child and its first sibling, and link those as well */
+ public void doubleLink() {
+ TNode right = (TNode)getNextSibling();
+ if(right != null) {
+ right.left = this;
+ right.doubleLink();
+ }
+ TNode down = (TNode)getFirstChild();
+ if(down != null) {
+ down.up = this;
+ down.doubleLink();
+ }
+ }
+
+ /** find first parent of the given type,
+ return null on failure */
+ public TNode parentOfType(int type) {
+ if(up == null) {
+ if(left == null)
+ return null;
+ else
+ return left.parentOfType(type);
+ }
+ if(up.getType() == type)
+ return up;
+ return up.parentOfType(type);
+ }
+
+ /** find the first child of the node
+ of the given type, return null on failure */
+ public TNode firstChildOfType(int type) {
+ TNode down = (TNode)getFirstChild();
+ if(down == null)
+ return null;
+ if(down.getType() == type)
+ return down;
+ return down.firstSiblingOfType(type);
+ }
+
+ /** find the first sibling of the node
+ of the given type, return null on failure */
+ public TNode firstSiblingOfType(int type) {
+ TNode right = (TNode)getNextSibling();
+ if(right == null)
+ return null;
+ if(right.getType() == type)
+ return right;
+ return right.firstSiblingOfType(type);
+ }
+
+}