1 /* 2 [The "BSD license"] 3 Copyright (c) 2005-2009 Terence Parr 4 All rights reserved. 5 6 Redistribution and use in source and binary forms, with or without 7 modification, are permitted provided that the following conditions 8 are met: 9 1. Redistributions of source code must retain the above copyright 10 notice, this list of conditions and the following disclaimer. 11 2. Redistributions in binary form must reproduce the above copyright 12 notice, this list of conditions and the following disclaimer in the 13 documentation and/or other materials provided with the distribution. 14 3. The name of the author may not be used to endorse or promote products 15 derived from this software without specific prior written permission. 16 17 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 package org.antlr.runtime.tree; 29 30 import org.antlr.runtime.CommonToken; 31 import org.antlr.runtime.Token; 32 33 /** A TreeAdaptor that works with any Tree implementation. It provides 34 * really just factory methods; all the work is done by BaseTreeAdaptor. 35 * If you would like to have different tokens created than ClassicToken 36 * objects, you need to override this and then set the parser tree adaptor to 37 * use your subclass. 38 * 39 * To get your parser to build nodes of a different type, override 40 * create(Token), errorNode(), and to be safe, YourTreeClass.dupNode(). 41 * dupNode is called to duplicate nodes during rewrite operations. 42 */ 43 public class CommonTreeAdaptor extends BaseTreeAdaptor { 44 /** Duplicate a node. This is part of the factory; 45 * override if you want another kind of node to be built. 46 * 47 * I could use reflection to prevent having to override this 48 * but reflection is slow. 49 */ 50 public Object dupNode(Object t) { 51 if ( t==null ) return null; 52 return ((Tree)t).dupNode(); 53 } 54 55 public Object create(Token payload) { 56 return new CommonTree(payload); 57 } 58 59 /** Tell me how to create a token for use with imaginary token nodes. 60 * For example, there is probably no input symbol associated with imaginary 61 * token DECL, but you need to create it as a payload or whatever for 62 * the DECL node as in ^(DECL type ID). 63 * 64 * If you care what the token payload objects' type is, you should 65 * override this method and any other createToken variant. 66 */ 67 public Token createToken(int tokenType, String text) { 68 return new CommonToken(tokenType, text); 69 } 70 71 /** Tell me how to create a token for use with imaginary token nodes. 72 * For example, there is probably no input symbol associated with imaginary 73 * token DECL, but you need to create it as a payload or whatever for 74 * the DECL node as in ^(DECL type ID). 75 * 76 * This is a variant of createToken where the new token is derived from 77 * an actual real input token. Typically this is for converting '{' 78 * tokens to BLOCK etc... You'll see 79 * 80 * r : lc='{' ID+ '}' -> ^(BLOCK[$lc] ID+) ; 81 * 82 * If you care what the token payload objects' type is, you should 83 * override this method and any other createToken variant. 84 */ 85 public Token createToken(Token fromToken) { 86 return new CommonToken(fromToken); 87 } 88 89 /** Track start/stop token for subtree root created for a rule. 90 * Only works with Tree nodes. For rules that match nothing, 91 * seems like this will yield start=i and stop=i-1 in a nil node. 92 * Might be useful info so I'll not force to be i..i. 93 */ 94 public void setTokenBoundaries(Object t, Token startToken, Token stopToken) { 95 if ( t==null ) return; 96 int start = 0; 97 int stop = 0; 98 if ( startToken!=null ) start = startToken.getTokenIndex(); 99 if ( stopToken!=null ) stop = stopToken.getTokenIndex(); 100 ((Tree)t).setTokenStartIndex(start); 101 ((Tree)t).setTokenStopIndex(stop); 102 } 103 104 public int getTokenStartIndex(Object t) { 105 if ( t==null ) return -1; 106 return ((Tree)t).getTokenStartIndex(); 107 } 108 109 public int getTokenStopIndex(Object t) { 110 if ( t==null ) return -1; 111 return ((Tree)t).getTokenStopIndex(); 112 } 113 114 public String getText(Object t) { 115 if ( t==null ) return null; 116 return ((Tree)t).getText(); 117 } 118 119 public int getType(Object t) { 120 if ( t==null ) return Token.INVALID_TOKEN_TYPE; 121 return ((Tree)t).getType(); 122 } 123 124 /** What is the Token associated with this node? If 125 * you are not using CommonTree, then you must 126 * override this in your own adaptor. 127 */ 128 public Token getToken(Object t) { 129 if ( t instanceof CommonTree ) { 130 return ((CommonTree)t).getToken(); 131 } 132 return null; // no idea what to do 133 } 134 135 public Object getChild(Object t, int i) { 136 if ( t==null ) return null; 137 return ((Tree)t).getChild(i); 138 } 139 140 public int getChildCount(Object t) { 141 if ( t==null ) return 0; 142 return ((Tree)t).getChildCount(); 143 } 144 145 public Object getParent(Object t) { 146 if ( t==null ) return null; 147 return ((Tree)t).getParent(); 148 } 149 150 public void setParent(Object t, Object parent) { 151 if ( t!=null ) ((Tree)t).setParent((Tree)parent); 152 } 153 154 public int getChildIndex(Object t) { 155 if ( t==null ) return 0; 156 return ((Tree)t).getChildIndex(); 157 } 158 159 public void setChildIndex(Object t, int index) { 160 if ( t!=null ) ((Tree)t).setChildIndex(index); 161 } 162 163 public void replaceChildren(Object parent, int startChildIndex, int stopChildIndex, Object t) { 164 if ( parent!=null ) { 165 ((Tree)parent).replaceChildren(startChildIndex, stopChildIndex, t); 166 } 167 } 168 } 169