1 /* 2 * [The "BSD licence"] 3 * Copyright (c) 2005-2008 Terence Parr 4 * All rights reserved. 5 * 6 * Conversion to C#: 7 * Copyright (c) 2008 Sam Harwell, Pixel Mine, Inc. 8 * All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 namespace Antlr.Runtime.Tree { 34 35 /** <summary> 36 * How to create and navigate trees. Rather than have a separate factory 37 * and adaptor, I've merged them. Makes sense to encapsulate. 38 * </summary> 39 * 40 * <remarks> 41 * This takes the place of the tree construction code generated in the 42 * generated code in 2.x and the ASTFactory. 43 * 44 * I do not need to know the type of a tree at all so they are all 45 * generic Objects. This may increase the amount of typecasting needed. :( 46 * </remarks> 47 */ 48 public interface ITreeAdaptor { 49 #region Construction 50 51 /** <summary> 52 * Create a tree node from Token object; for CommonTree type trees, 53 * then the token just becomes the payload. This is the most 54 * common create call. 55 * </summary> 56 * 57 * <remarks> 58 * Override if you want another kind of node to be built. 59 * </remarks> 60 */ Create(IToken payload)61 object Create(IToken payload); 62 63 /** <summary>Duplicate a single tree node.</summary> 64 * <remarks>Override if you want another kind of node to be built.</remarks> 65 */ DupNode(object treeNode)66 object DupNode(object treeNode); 67 68 /** <summary>Duplicate tree recursively, using dupNode() for each node</summary> */ DupTree(object tree)69 object DupTree(object tree); 70 71 /** <summary> 72 * Return a nil node (an empty but non-null node) that can hold 73 * a list of element as the children. If you want a flat tree (a list) 74 * use "t=adaptor.nil(); t.addChild(x); t.addChild(y);" 75 * </summary> 76 */ Nil()77 object Nil(); 78 79 /** <summary> 80 * Return a tree node representing an error. This node records the 81 * tokens consumed during error recovery. The start token indicates the 82 * input symbol at which the error was detected. The stop token indicates 83 * the last symbol consumed during recovery. 84 * </summary> 85 * 86 * </remarks> 87 * You must specify the input stream so that the erroneous text can 88 * be packaged up in the error node. The exception could be useful 89 * to some applications; default implementation stores ptr to it in 90 * the CommonErrorNode. 91 * 92 * This only makes sense during token parsing, not tree parsing. 93 * Tree parsing should happen only when parsing and tree construction 94 * succeed. 95 * </remarks> 96 */ ErrorNode(ITokenStream input, IToken start, IToken stop, RecognitionException e)97 object ErrorNode(ITokenStream input, IToken start, IToken stop, RecognitionException e); 98 99 /** <summary>Is tree considered a nil node used to make lists of child nodes?</summary> */ IsNil(object tree)100 bool IsNil(object tree); 101 102 /** <summary> 103 * Add a child to the tree t. If child is a flat tree (a list), make all 104 * in list children of t. Warning: if t has no children, but child does 105 * and child isNil then you can decide it is ok to move children to t via 106 * t.children = child.children; i.e., without copying the array. Just 107 * make sure that this is consistent with have the user will build 108 * ASTs. Do nothing if t or child is null. 109 * </summary> 110 */ AddChild(object t, object child)111 void AddChild(object t, object child); 112 113 /** <summary> 114 * If oldRoot is a nil root, just copy or move the children to newRoot. 115 * If not a nil root, make oldRoot a child of newRoot. 116 * </summary> 117 * 118 * <remarks> 119 * old=^(nil a b c), new=r yields ^(r a b c) 120 * old=^(a b c), new=r yields ^(r ^(a b c)) 121 * 122 * If newRoot is a nil-rooted single child tree, use the single 123 * child as the new root node. 124 * 125 * old=^(nil a b c), new=^(nil r) yields ^(r a b c) 126 * old=^(a b c), new=^(nil r) yields ^(r ^(a b c)) 127 * 128 * If oldRoot was null, it's ok, just return newRoot (even if isNil). 129 * 130 * old=null, new=r yields r 131 * old=null, new=^(nil r) yields ^(nil r) 132 * 133 * Return newRoot. Throw an exception if newRoot is not a 134 * simple node or nil root with a single child node--it must be a root 135 * node. If newRoot is ^(nil x) return x as newRoot. 136 * 137 * Be advised that it's ok for newRoot to point at oldRoot's 138 * children; i.e., you don't have to copy the list. We are 139 * constructing these nodes so we should have this control for 140 * efficiency. 141 * </remarks> 142 */ BecomeRoot(object newRoot, object oldRoot)143 object BecomeRoot(object newRoot, object oldRoot); 144 145 /** <summary> 146 * Given the root of the subtree created for this rule, post process 147 * it to do any simplifications or whatever you want. A required 148 * behavior is to convert ^(nil singleSubtree) to singleSubtree 149 * as the setting of start/stop indexes relies on a single non-nil root 150 * for non-flat trees. 151 * </summary> 152 * 153 * <remarks> 154 * Flat trees such as for lists like "idlist : ID+ ;" are left alone 155 * unless there is only one ID. For a list, the start/stop indexes 156 * are set in the nil node. 157 * 158 * This method is executed after all rule tree construction and right 159 * before setTokenBoundaries(). 160 * </remarks> 161 */ RulePostProcessing(object root)162 object RulePostProcessing(object root); 163 164 /** <summary>For identifying trees.</summary> 165 * 166 * <remarks> 167 * How to identify nodes so we can say "add node to a prior node"? 168 * Even becomeRoot is an issue. Use System.identityHashCode(node) 169 * usually. 170 * </remarks> 171 */ GetUniqueID(object node)172 int GetUniqueID(object node); 173 174 175 // R e w r i t e R u l e s 176 177 /** <summary> 178 * Create a node for newRoot make it the root of oldRoot. 179 * If oldRoot is a nil root, just copy or move the children to newRoot. 180 * If not a nil root, make oldRoot a child of newRoot. 181 * </summary> 182 * 183 * <returns> 184 * Return node created for newRoot. 185 * </returns> 186 * 187 * <remarks> 188 * Be advised: when debugging ASTs, the DebugTreeAdaptor manually 189 * calls create(Token child) and then plain becomeRoot(node, node) 190 * because it needs to trap calls to create, but it can't since it delegates 191 * to not inherits from the TreeAdaptor. 192 * </remarks> 193 */ BecomeRoot(IToken newRoot, object oldRoot)194 object BecomeRoot(IToken newRoot, object oldRoot); 195 196 /** <summary> 197 * Create a new node derived from a token, with a new token type. 198 * This is invoked from an imaginary node ref on right side of a 199 * rewrite rule as IMAG[$tokenLabel]. 200 * </summary> 201 * 202 * <remarks> 203 * This should invoke createToken(Token). 204 * </remarks> 205 */ Create(int tokenType, IToken fromToken)206 object Create(int tokenType, IToken fromToken); 207 208 /** <summary> 209 * Same as create(tokenType,fromToken) except set the text too. 210 * This is invoked from an imaginary node ref on right side of a 211 * rewrite rule as IMAG[$tokenLabel, "IMAG"]. 212 * </summary> 213 * 214 * <remarks> 215 * This should invoke createToken(Token). 216 * </remarks> 217 */ Create(int tokenType, IToken fromToken, string text)218 object Create(int tokenType, IToken fromToken, string text); 219 220 /** <summary> 221 * Create a new node derived from a token, with a new token type. 222 * This is invoked from an imaginary node ref on right side of a 223 * rewrite rule as IMAG["IMAG"]. 224 * </summary> 225 * 226 * <remarks> 227 * This should invoke createToken(int,String). 228 * </remarks> 229 */ Create(int tokenType, string text)230 object Create(int tokenType, string text); 231 232 #endregion 233 234 235 #region Content 236 237 /** <summary>For tree parsing, I need to know the token type of a node</summary> */ GetType(object t)238 int GetType(object t); 239 240 /** <summary>Node constructors can set the type of a node</summary> */ SetType(object t, int type)241 void SetType(object t, int type); 242 GetText(object t)243 string GetText(object t); 244 245 /** <summary>Node constructors can set the text of a node</summary> */ SetText(object t, string text)246 void SetText(object t, string text); 247 248 /** <summary> 249 * Return the token object from which this node was created. 250 * Currently used only for printing an error message. 251 * The error display routine in BaseRecognizer needs to 252 * display where the input the error occurred. If your 253 * tree of limitation does not store information that can 254 * lead you to the token, you can create a token filled with 255 * the appropriate information and pass that back. See 256 * BaseRecognizer.getErrorMessage(). 257 * </summary> 258 */ GetToken(object t)259 IToken GetToken(object t); 260 261 /** <summary> 262 * Where are the bounds in the input token stream for this node and 263 * all children? Each rule that creates AST nodes will call this 264 * method right before returning. Flat trees (i.e., lists) will 265 * still usually have a nil root node just to hold the children list. 266 * That node would contain the start/stop indexes then. 267 * </summary> 268 */ SetTokenBoundaries(object t, IToken startToken, IToken stopToken)269 void SetTokenBoundaries(object t, IToken startToken, IToken stopToken); 270 271 /** <summary>Get the token start index for this subtree; return -1 if no such index</summary> */ GetTokenStartIndex(object t)272 int GetTokenStartIndex(object t); 273 274 /** <summary>Get the token stop index for this subtree; return -1 if no such index</summary> */ GetTokenStopIndex(object t)275 int GetTokenStopIndex(object t); 276 277 #endregion 278 279 280 #region Navigation / Tree Parsing 281 282 /** <summary>Get a child 0..n-1 node</summary> */ GetChild(object t, int i)283 object GetChild(object t, int i); 284 285 /** <summary>Set ith child (0..n-1) to t; t must be non-null and non-nil node</summary> */ SetChild(object t, int i, object child)286 void SetChild(object t, int i, object child); 287 288 /** <summary>Remove ith child and shift children down from right.</summary> */ DeleteChild(object t, int i)289 object DeleteChild(object t, int i); 290 291 /** <summary>How many children? If 0, then this is a leaf node</summary> */ GetChildCount(object t)292 int GetChildCount(object t); 293 294 /** <summary> 295 * Who is the parent node of this node; if null, implies node is root. 296 * If your node type doesn't handle this, it's ok but the tree rewrites 297 * in tree parsers need this functionality. 298 * </summary> 299 */ GetParent(object t)300 object GetParent(object t); SetParent(object t, object parent)301 void SetParent(object t, object parent); 302 303 /** <summary> 304 * What index is this node in the child list? Range: 0..n-1 305 * If your node type doesn't handle this, it's ok but the tree rewrites 306 * in tree parsers need this functionality. 307 * </summary> 308 */ GetChildIndex(object t)309 int GetChildIndex(object t); SetChildIndex(object t, int index)310 void SetChildIndex(object t, int index); 311 312 /** <summary> 313 * Replace from start to stop child index of parent with t, which might 314 * be a list. Number of children may be different after this call. 315 * </summary> 316 * 317 * <remarks> 318 * If parent is null, don't do anything; must be at root of overall tree. 319 * Can't replace whatever points to the parent externally. Do nothing. 320 * </remarks> 321 */ ReplaceChildren(object parent, int startChildIndex, int stopChildIndex, object t)322 void ReplaceChildren(object parent, int startChildIndex, int stopChildIndex, object t); 323 324 #endregion 325 } 326 } 327