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     public interface ITreeAdaptor<T>
36     {
37         #region Construction
38 
39         /** <summary>
40          *  Create a tree node from Token object; for CommonTree type trees,
41          *  then the token just becomes the payload.  This is the most
42          *  common create call.
43          *  </summary>
44          *
45          *  <remarks>
46          *  Override if you want another kind of node to be built.
47          *  </remarks>
48          */
Create(IToken payload)49         T Create(IToken payload);
50 
51         /** <summary>Duplicate a single tree node.</summary>
52          *  <remarks>Override if you want another kind of node to be built.</remarks>
53          */
DupNode(T treeNode)54         T DupNode(T treeNode);
55 
56         /** <summary>Duplicate tree recursively, using dupNode() for each node</summary> */
DupTree(T tree)57         T DupTree(T tree);
58 
59         /** <summary>
60          *  Return a nil node (an empty but non-null node) that can hold
61          *  a list of element as the children.  If you want a flat tree (a list)
62          *  use "t=adaptor.nil(); t.addChild(x); t.addChild(y);"
63          *  </summary>
64          */
Nil()65         T Nil();
66 
67         /** <summary>
68          *  Return a tree node representing an error.  This node records the
69          *  tokens consumed during error recovery.  The start token indicates the
70          *  input symbol at which the error was detected.  The stop token indicates
71          *  the last symbol consumed during recovery.
72          *  </summary>
73          *
74          *  </remarks>
75          *  You must specify the input stream so that the erroneous text can
76          *  be packaged up in the error node.  The exception could be useful
77          *  to some applications; default implementation stores ptr to it in
78          *  the CommonErrorNode.
79          *
80          *  This only makes sense during token parsing, not tree parsing.
81          *  Tree parsing should happen only when parsing and tree construction
82          *  succeed.
83          *  </remarks>
84          */
ErrorNode(ITokenStream input, IToken start, IToken stop, RecognitionException e)85         T ErrorNode(ITokenStream input, IToken start, IToken stop, RecognitionException e);
86 
87         /** <summary>Is tree considered a nil node used to make lists of child nodes?</summary> */
IsNil(T tree)88         bool IsNil(T tree);
89 
90         /** <summary>
91          *  Add a child to the tree t.  If child is a flat tree (a list), make all
92          *  in list children of t.  Warning: if t has no children, but child does
93          *  and child isNil then you can decide it is ok to move children to t via
94          *  t.children = child.children; i.e., without copying the array.  Just
95          *  make sure that this is consistent with have the user will build
96          *  ASTs.  Do nothing if t or child is null.
97          *  </summary>
98          */
AddChild(T t, T child)99         void AddChild(T t, T child);
100 
101         /** <summary>
102          *  If oldRoot is a nil root, just copy or move the children to newRoot.
103          *  If not a nil root, make oldRoot a child of newRoot.
104          *  </summary>
105          *
106          *  <remarks>
107          *    old=^(nil a b c), new=r yields ^(r a b c)
108          *    old=^(a b c), new=r yields ^(r ^(a b c))
109          *
110          *  If newRoot is a nil-rooted single child tree, use the single
111          *  child as the new root node.
112          *
113          *    old=^(nil a b c), new=^(nil r) yields ^(r a b c)
114          *    old=^(a b c), new=^(nil r) yields ^(r ^(a b c))
115          *
116          *  If oldRoot was null, it's ok, just return newRoot (even if isNil).
117          *
118          *    old=null, new=r yields r
119          *    old=null, new=^(nil r) yields ^(nil r)
120          *
121          *  Return newRoot.  Throw an exception if newRoot is not a
122          *  simple node or nil root with a single child node--it must be a root
123          *  node.  If newRoot is ^(nil x) return x as newRoot.
124          *
125          *  Be advised that it's ok for newRoot to point at oldRoot's
126          *  children; i.e., you don't have to copy the list.  We are
127          *  constructing these nodes so we should have this control for
128          *  efficiency.
129          *  </remarks>
130          */
BecomeRoot(T newRoot, T oldRoot)131         T BecomeRoot(T newRoot, T oldRoot);
132 
133         /** <summary>
134          *  Given the root of the subtree created for this rule, post process
135          *  it to do any simplifications or whatever you want.  A required
136          *  behavior is to convert ^(nil singleSubtree) to singleSubtree
137          *  as the setting of start/stop indexes relies on a single non-nil root
138          *  for non-flat trees.
139          *  </summary>
140          *
141          *  <remarks>
142          *  Flat trees such as for lists like "idlist : ID+ ;" are left alone
143          *  unless there is only one ID.  For a list, the start/stop indexes
144          *  are set in the nil node.
145          *
146          *  This method is executed after all rule tree construction and right
147          *  before setTokenBoundaries().
148          *  </remarks>
149          */
RulePostProcessing(T root)150         T RulePostProcessing(T root);
151 
152         /** <summary>For identifying trees.</summary>
153          *
154          *  <remarks>
155          *  How to identify nodes so we can say "add node to a prior node"?
156          *  Even becomeRoot is an issue.  Use System.identityHashCode(node)
157          *  usually.
158          *  </remarks>
159          */
GetUniqueID(T node)160         int GetUniqueID(T node);
161 
162 
163         // R e w r i t e  R u l e s
164 
165         /** <summary>
166          *  Create a node for newRoot make it the root of oldRoot.
167          *  If oldRoot is a nil root, just copy or move the children to newRoot.
168          *  If not a nil root, make oldRoot a child of newRoot.
169          *  </summary>
170          *
171          *  <returns>
172          *  Return node created for newRoot.
173          *  </returns>
174          *
175          *  <remarks>
176          *  Be advised: when debugging ASTs, the DebugTreeAdaptor manually
177          *  calls create(Token child) and then plain becomeRoot(node, node)
178          *  because it needs to trap calls to create, but it can't since it delegates
179          *  to not inherits from the TreeAdaptor.
180          *  </remarks>
181          */
BecomeRoot(IToken newRoot, T oldRoot)182         T BecomeRoot(IToken newRoot, T oldRoot);
183 
184         /** <summary>
185          *  Create a new node derived from a token, with a new token type.
186          *  This is invoked from an imaginary node ref on right side of a
187          *  rewrite rule as IMAG[$tokenLabel].
188          *  </summary>
189          *
190          *  <remarks>
191          *  This should invoke createToken(Token).
192          *  </remarks>
193          */
Create(int tokenType, IToken fromToken)194         T Create(int tokenType, IToken fromToken);
195 
196         /** <summary>
197          *  Same as create(tokenType,fromToken) except set the text too.
198          *  This is invoked from an imaginary node ref on right side of a
199          *  rewrite rule as IMAG[$tokenLabel, "IMAG"].
200          *  </summary>
201          *
202          *  <remarks>
203          *  This should invoke createToken(Token).
204          *  </remarks>
205          */
Create(int tokenType, IToken fromToken, string text)206         T Create(int tokenType, IToken fromToken, string text);
207 
208         /** <summary>
209          *  Create a new node derived from a token, with a new token type.
210          *  This is invoked from an imaginary node ref on right side of a
211          *  rewrite rule as IMAG["IMAG"].
212          *  </summary>
213          *
214          *  <remarks>
215          *  This should invoke createToken(int,String).
216          *  </remarks>
217          */
Create(int tokenType, string text)218         T Create(int tokenType, string text);
219 
220         #endregion
221 
222 
223         #region Content
224 
225         /** <summary>For tree parsing, I need to know the token type of a node</summary> */
GetType(T t)226         int GetType(T t);
227 
228         /** <summary>Node constructors can set the type of a node</summary> */
SetType(T t, int type)229         void SetType(T t, int type);
230 
GetText(T t)231         string GetText(T t);
232 
233         /** <summary>Node constructors can set the text of a node</summary> */
SetText(T t, string text)234         void SetText(T t, string text);
235 
236         /** <summary>
237          *  Return the token object from which this node was created.
238          *  Currently used only for printing an error message.
239          *  The error display routine in BaseRecognizer needs to
240          *  display where the input the error occurred. If your
241          *  tree of limitation does not store information that can
242          *  lead you to the token, you can create a token filled with
243          *  the appropriate information and pass that back.  See
244          *  BaseRecognizer.getErrorMessage().
245          *  </summary>
246          */
GetToken(T t)247         IToken GetToken(T t);
248 
249         /** <summary>
250          *  Where are the bounds in the input token stream for this node and
251          *  all children?  Each rule that creates AST nodes will call this
252          *  method right before returning.  Flat trees (i.e., lists) will
253          *  still usually have a nil root node just to hold the children list.
254          *  That node would contain the start/stop indexes then.
255          *  </summary>
256          */
SetTokenBoundaries(T t, IToken startToken, IToken stopToken)257         void SetTokenBoundaries(T t, IToken startToken, IToken stopToken);
258 
259         /** <summary>Get the token start index for this subtree; return -1 if no such index</summary> */
GetTokenStartIndex(T t)260         int GetTokenStartIndex(T t);
261 
262         /** <summary>Get the token stop index for this subtree; return -1 if no such index</summary> */
GetTokenStopIndex(T t)263         int GetTokenStopIndex(T t);
264 
265         #endregion
266 
267 
268         #region Navigation / Tree Parsing
269 
270         /** <summary>Get a child 0..n-1 node</summary> */
GetChild(T t, int i)271         T GetChild(T t, int i);
272 
273         /** <summary>Set ith child (0..n-1) to t; t must be non-null and non-nil node</summary> */
SetChild(T t, int i, T child)274         void SetChild(T t, int i, T child);
275 
276         /** <summary>Remove ith child and shift children down from right.</summary> */
DeleteChild(T t, int i)277         T DeleteChild(T t, int i);
278 
279         /** <summary>How many children?  If 0, then this is a leaf node</summary> */
GetChildCount(T t)280         int GetChildCount(T t);
281 
282         /** <summary>
283          *  Who is the parent node of this node; if null, implies node is root.
284          *  If your node type doesn't handle this, it's ok but the tree rewrites
285          *  in tree parsers need this functionality.
286          *  </summary>
287          */
GetParent(T t)288         T GetParent(T t);
SetParent(T t, T parent)289         void SetParent(T t, T parent);
290 
291         /** <summary>
292          *  What index is this node in the child list? Range: 0..n-1
293          *  If your node type doesn't handle this, it's ok but the tree rewrites
294          *  in tree parsers need this functionality.
295          *  </summary>
296          */
GetChildIndex(T t)297         int GetChildIndex(T t);
SetChildIndex(T t, int index)298         void SetChildIndex(T t, int index);
299 
300         /** <summary>
301          *  Replace from start to stop child index of parent with t, which might
302          *  be a list.  Number of children may be different after this call.
303          *  </summary>
304          *
305          *  <remarks>
306          *  If parent is null, don't do anything; must be at root of overall tree.
307          *  Can't replace whatever points to the parent externally.  Do nothing.
308          *  </remarks>
309          */
ReplaceChildren(T parent, int startChildIndex, int stopChildIndex, T t)310         void ReplaceChildren(T parent, int startChildIndex, int stopChildIndex, T t);
311 
312         #endregion
313     }
314 }
315