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