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