aboutsummaryrefslogtreecommitdiff
path: root/antlr-3.4/runtime/Java/src/main/java/org/antlr/runtime/tree/BaseTreeAdaptor.java
diff options
context:
space:
mode:
Diffstat (limited to 'antlr-3.4/runtime/Java/src/main/java/org/antlr/runtime/tree/BaseTreeAdaptor.java')
-rw-r--r--antlr-3.4/runtime/Java/src/main/java/org/antlr/runtime/tree/BaseTreeAdaptor.java279
1 files changed, 279 insertions, 0 deletions
diff --git a/antlr-3.4/runtime/Java/src/main/java/org/antlr/runtime/tree/BaseTreeAdaptor.java b/antlr-3.4/runtime/Java/src/main/java/org/antlr/runtime/tree/BaseTreeAdaptor.java
new file mode 100644
index 0000000..33140b1
--- /dev/null
+++ b/antlr-3.4/runtime/Java/src/main/java/org/antlr/runtime/tree/BaseTreeAdaptor.java
@@ -0,0 +1,279 @@
+/*
+ [The "BSD license"]
+ Copyright (c) 2005-2009 Terence Parr
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. The name of the author may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.antlr.runtime.tree;
+
+import org.antlr.runtime.Token;
+import org.antlr.runtime.TokenStream;
+import org.antlr.runtime.RecognitionException;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/** A TreeAdaptor that works with any Tree implementation. */
+public abstract class BaseTreeAdaptor implements TreeAdaptor {
+ /** System.identityHashCode() is not always unique; we have to
+ * track ourselves. That's ok, it's only for debugging, though it's
+ * expensive: we have to create a hashtable with all tree nodes in it.
+ */
+ protected Map treeToUniqueIDMap;
+ protected int uniqueNodeID = 1;
+
+ public Object nil() {
+ return create(null);
+ }
+
+ /** create tree node that holds the start and stop tokens associated
+ * with an error.
+ *
+ * If you specify your own kind of tree nodes, you will likely have to
+ * override this method. CommonTree returns Token.INVALID_TOKEN_TYPE
+ * if no token payload but you might have to set token type for diff
+ * node type.
+ *
+ * You don't have to subclass CommonErrorNode; you will likely need to
+ * subclass your own tree node class to avoid class cast exception.
+ */
+ public Object errorNode(TokenStream input, Token start, Token stop,
+ RecognitionException e)
+ {
+ CommonErrorNode t = new CommonErrorNode(input, start, stop, e);
+ //System.out.println("returning error node '"+t+"' @index="+input.index());
+ return t;
+ }
+
+ public boolean isNil(Object tree) {
+ return ((Tree)tree).isNil();
+ }
+
+ public Object dupTree(Object tree) {
+ return dupTree(tree, null);
+ }
+
+ /** This is generic in the sense that it will work with any kind of
+ * tree (not just Tree interface). It invokes the adaptor routines
+ * not the tree node routines to do the construction.
+ */
+ public Object dupTree(Object t, Object parent) {
+ if ( t==null ) {
+ return null;
+ }
+ Object newTree = dupNode(t);
+ // ensure new subtree root has parent/child index set
+ setChildIndex(newTree, getChildIndex(t)); // same index in new tree
+ setParent(newTree, parent);
+ int n = getChildCount(t);
+ for (int i = 0; i < n; i++) {
+ Object child = getChild(t, i);
+ Object newSubTree = dupTree(child, t);
+ addChild(newTree, newSubTree);
+ }
+ return newTree;
+ }
+
+ /** Add a child to the tree t. If child is a flat tree (a list), make all
+ * in list children of t. Warning: if t has no children, but child does
+ * and child isNil then you can decide it is ok to move children to t via
+ * t.children = child.children; i.e., without copying the array. Just
+ * make sure that this is consistent with have the user will build
+ * ASTs.
+ */
+ public void addChild(Object t, Object child) {
+ if ( t!=null && child!=null ) {
+ ((Tree)t).addChild((Tree)child);
+ }
+ }
+
+ /** If oldRoot is a nil root, just copy or move the children to newRoot.
+ * If not a nil root, make oldRoot a child of newRoot.
+ *
+ * old=^(nil a b c), new=r yields ^(r a b c)
+ * old=^(a b c), new=r yields ^(r ^(a b c))
+ *
+ * If newRoot is a nil-rooted single child tree, use the single
+ * child as the new root node.
+ *
+ * old=^(nil a b c), new=^(nil r) yields ^(r a b c)
+ * old=^(a b c), new=^(nil r) yields ^(r ^(a b c))
+ *
+ * If oldRoot was null, it's ok, just return newRoot (even if isNil).
+ *
+ * old=null, new=r yields r
+ * old=null, new=^(nil r) yields ^(nil r)
+ *
+ * Return newRoot. Throw an exception if newRoot is not a
+ * simple node or nil root with a single child node--it must be a root
+ * node. If newRoot is ^(nil x) return x as newRoot.
+ *
+ * Be advised that it's ok for newRoot to point at oldRoot's
+ * children; i.e., you don't have to copy the list. We are
+ * constructing these nodes so we should have this control for
+ * efficiency.
+ */
+ public Object becomeRoot(Object newRoot, Object oldRoot) {
+ //System.out.println("becomeroot new "+newRoot.toString()+" old "+oldRoot);
+ Tree newRootTree = (Tree)newRoot;
+ Tree oldRootTree = (Tree)oldRoot;
+ if ( oldRoot==null ) {
+ return newRoot;
+ }
+ // handle ^(nil real-node)
+ if ( newRootTree.isNil() ) {
+ int nc = newRootTree.getChildCount();
+ if ( nc==1 ) newRootTree = (Tree)newRootTree.getChild(0);
+ else if ( nc >1 ) {
+ // TODO: make tree run time exceptions hierarchy
+ throw new RuntimeException("more than one node as root (TODO: make exception hierarchy)");
+ }
+ }
+ // add oldRoot to newRoot; addChild takes care of case where oldRoot
+ // is a flat list (i.e., nil-rooted tree). All children of oldRoot
+ // are added to newRoot.
+ newRootTree.addChild(oldRootTree);
+ return newRootTree;
+ }
+
+ /** Transform ^(nil x) to x and nil to null */
+ public Object rulePostProcessing(Object root) {
+ //System.out.println("rulePostProcessing: "+((Tree)root).toStringTree());
+ Tree r = (Tree)root;
+ if ( r!=null && r.isNil() ) {
+ if ( r.getChildCount()==0 ) {
+ r = null;
+ }
+ else if ( r.getChildCount()==1 ) {
+ r = (Tree)r.getChild(0);
+ // whoever invokes rule will set parent and child index
+ r.setParent(null);
+ r.setChildIndex(-1);
+ }
+ }
+ return r;
+ }
+
+ public Object becomeRoot(Token newRoot, Object oldRoot) {
+ return becomeRoot(create(newRoot), oldRoot);
+ }
+
+ public Object create(int tokenType, Token fromToken) {
+ fromToken = createToken(fromToken);
+ //((ClassicToken)fromToken).setType(tokenType);
+ fromToken.setType(tokenType);
+ Tree t = (Tree)create(fromToken);
+ return t;
+ }
+
+ public Object create(int tokenType, Token fromToken, String text) {
+ if (fromToken == null) return create(tokenType, text);
+ fromToken = createToken(fromToken);
+ fromToken.setType(tokenType);
+ fromToken.setText(text);
+ Tree t = (Tree)create(fromToken);
+ return t;
+ }
+
+ public Object create(int tokenType, String text) {
+ Token fromToken = createToken(tokenType, text);
+ Tree t = (Tree)create(fromToken);
+ return t;
+ }
+
+ public int getType(Object t) {
+ return ((Tree)t).getType();
+ }
+
+ public void setType(Object t, int type) {
+ throw new NoSuchMethodError("don't know enough about Tree node");
+ }
+
+ public String getText(Object t) {
+ return ((Tree)t).getText();
+ }
+
+ public void setText(Object t, String text) {
+ throw new NoSuchMethodError("don't know enough about Tree node");
+ }
+
+ public Object getChild(Object t, int i) {
+ return ((Tree)t).getChild(i);
+ }
+
+ public void setChild(Object t, int i, Object child) {
+ ((Tree)t).setChild(i, (Tree)child);
+ }
+
+ public Object deleteChild(Object t, int i) {
+ return ((Tree)t).deleteChild(i);
+ }
+
+ public int getChildCount(Object t) {
+ return ((Tree)t).getChildCount();
+ }
+
+ public int getUniqueID(Object node) {
+ if ( treeToUniqueIDMap==null ) {
+ treeToUniqueIDMap = new HashMap();
+ }
+ Integer prevID = (Integer)treeToUniqueIDMap.get(node);
+ if ( prevID!=null ) {
+ return prevID.intValue();
+ }
+ int ID = uniqueNodeID;
+ treeToUniqueIDMap.put(node, new Integer(ID));
+ uniqueNodeID++;
+ return ID;
+ // GC makes these nonunique:
+ // return System.identityHashCode(node);
+ }
+
+ /** Tell me how to create a token for use with imaginary token nodes.
+ * For example, there is probably no input symbol associated with imaginary
+ * token DECL, but you need to create it as a payload or whatever for
+ * the DECL node as in ^(DECL type ID).
+ *
+ * If you care what the token payload objects' type is, you should
+ * override this method and any other createToken variant.
+ */
+ public abstract Token createToken(int tokenType, String text);
+
+ /** Tell me how to create a token for use with imaginary token nodes.
+ * For example, there is probably no input symbol associated with imaginary
+ * token DECL, but you need to create it as a payload or whatever for
+ * the DECL node as in ^(DECL type ID).
+ *
+ * This is a variant of createToken where the new token is derived from
+ * an actual real input token. Typically this is for converting '{'
+ * tokens to BLOCK etc... You'll see
+ *
+ * r : lc='{' ID+ '}' -> ^(BLOCK[$lc] ID+) ;
+ *
+ * If you care what the token payload objects' type is, you should
+ * override this method and any other createToken variant.
+ */
+ public abstract Token createToken(Token fromToken);
+}
+