xref: /aosp_15_r20/external/antlr/runtime/Delphi/Sources/Antlr3.Runtime/Antlr.Runtime.Tree.pas (revision 16467b971bd3e2009fad32dd79016f2c7e421deb)
1*16467b97STreehugger Robot unit Antlr.Runtime.Tree;
2*16467b97STreehugger Robot (*
3*16467b97STreehugger Robot [The "BSD licence"]
4*16467b97STreehugger Robot Copyright (c) 2008 Erik van Bilsen
5*16467b97STreehugger Robot Copyright (c) 2005-2007 Kunle Odutola
6*16467b97STreehugger Robot All rights reserved.
7*16467b97STreehugger Robot 
8*16467b97STreehugger Robot Redistribution and use in source and binary forms, with or without
9*16467b97STreehugger Robot modification, are permitted provided that the following conditions
10*16467b97STreehugger Robot are met:
11*16467b97STreehugger Robot 1. Redistributions of source code MUST RETAIN the above copyright
12*16467b97STreehugger Robot    notice, this list of conditions and the following disclaimer.
13*16467b97STreehugger Robot 2. Redistributions in binary form MUST REPRODUCE the above copyright
14*16467b97STreehugger Robot    notice, this list of conditions and the following disclaimer in
15*16467b97STreehugger Robot    the documentation and/or other materials provided with the
16*16467b97STreehugger Robot    distribution.
17*16467b97STreehugger Robot 3. The name of the author may not be used to endorse or promote products
18*16467b97STreehugger Robot    derived from this software without specific prior WRITTEN permission.
19*16467b97STreehugger Robot 4. Unless explicitly state otherwise, any contribution intentionally
20*16467b97STreehugger Robot    submitted for inclusion in this work to the copyright owner or licensor
21*16467b97STreehugger Robot    shall be under the terms and conditions of this license, without any
22*16467b97STreehugger Robot    additional terms or conditions.
23*16467b97STreehugger Robot 
24*16467b97STreehugger Robot THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
25*16467b97STreehugger Robot IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
26*16467b97STreehugger Robot OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27*16467b97STreehugger Robot IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
28*16467b97STreehugger Robot INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
29*16467b97STreehugger Robot NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30*16467b97STreehugger Robot DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31*16467b97STreehugger Robot THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32*16467b97STreehugger Robot (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
33*16467b97STreehugger Robot THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34*16467b97STreehugger Robot *)
35*16467b97STreehugger Robot 
36*16467b97STreehugger Robot interface
37*16467b97STreehugger Robot 
38*16467b97STreehugger Robot {$IF CompilerVersion < 20}
39*16467b97STreehugger Robot {$MESSAGE ERROR 'You need Delphi 2009 or higher to use the Antlr runtime'}
40*16467b97STreehugger Robot {$IFEND}
41*16467b97STreehugger Robot 
42*16467b97STreehugger Robot uses
43*16467b97STreehugger Robot   Classes,
44*16467b97STreehugger Robot   SysUtils,
45*16467b97STreehugger Robot   Antlr.Runtime,
46*16467b97STreehugger Robot   Antlr.Runtime.Tools,
47*16467b97STreehugger Robot   Antlr.Runtime.Collections;
48*16467b97STreehugger Robot 
49*16467b97STreehugger Robot type
50*16467b97STreehugger Robot   /// <summary>
51*16467b97STreehugger Robot   /// How to create and navigate trees.  Rather than have a separate factory
52*16467b97STreehugger Robot   /// and adaptor, I've merged them.  Makes sense to encapsulate.
53*16467b97STreehugger Robot   ///
54*16467b97STreehugger Robot   /// This takes the place of the tree construction code generated in the
55*16467b97STreehugger Robot   /// generated code in 2.x and the ASTFactory.
56*16467b97STreehugger Robot   ///
57*16467b97STreehugger Robot   /// I do not need to know the type of a tree at all so they are all
58*16467b97STreehugger Robot   /// generic Objects.  This may increase the amount of typecasting needed. :(
59*16467b97STreehugger Robot   /// </summary>
60*16467b97STreehugger Robot   ITreeAdaptor = interface(IANTLRInterface)
61*16467b97STreehugger Robot   ['{F9DEB286-F555-4CC8-A51A-93F3F649B248}']
62*16467b97STreehugger Robot     { Methods }
63*16467b97STreehugger Robot 
64*16467b97STreehugger Robot     // C o n s t r u c t i o n
65*16467b97STreehugger Robot 
66*16467b97STreehugger Robot     /// <summary>
67*16467b97STreehugger Robot     /// Create a tree node from Token object; for CommonTree type trees,
68*16467b97STreehugger Robot     /// then the token just becomes the payload.
69*16467b97STreehugger Robot     /// </summary>
70*16467b97STreehugger Robot     /// <remarks>
71*16467b97STreehugger Robot     /// This is the most common create call. Override if you want another kind of node to be built.
72*16467b97STreehugger Robot     /// </remarks>
CreateNode(const Payload: IToken)73*16467b97STreehugger Robot     function CreateNode(const Payload: IToken): IANTLRInterface; overload;
74*16467b97STreehugger Robot 
75*16467b97STreehugger Robot     /// <summary>Duplicate a single tree node </summary>
76*16467b97STreehugger Robot     /// <remarks> Override if you want another kind of node to be built.</remarks>
DupNode(const TreeNode: IANTLRInterface)77*16467b97STreehugger Robot     function DupNode(const TreeNode: IANTLRInterface): IANTLRInterface;
78*16467b97STreehugger Robot 
79*16467b97STreehugger Robot     /// <summary>Duplicate tree recursively, using DupNode() for each node </summary>
DupTree(const Tree: IANTLRInterface)80*16467b97STreehugger Robot     function DupTree(const Tree: IANTLRInterface): IANTLRInterface;
81*16467b97STreehugger Robot 
82*16467b97STreehugger Robot     /// <summary>
83*16467b97STreehugger Robot     /// Return a nil node (an empty but non-null node) that can hold
84*16467b97STreehugger Robot     /// a list of element as the children.  If you want a flat tree (a list)
85*16467b97STreehugger Robot     /// use "t=adaptor.nil(); t.AddChild(x); t.AddChild(y);"
86*16467b97STreehugger Robot     /// </summary>
GetNilNode()87*16467b97STreehugger Robot     function GetNilNode: IANTLRInterface;
88*16467b97STreehugger Robot 
89*16467b97STreehugger Robot     /// <summary>
90*16467b97STreehugger Robot     /// Return a tree node representing an error. This node records the
91*16467b97STreehugger Robot     /// tokens consumed during error recovery. The start token indicates the
92*16467b97STreehugger Robot     /// input symbol at which the error was detected. The stop token indicates
93*16467b97STreehugger Robot     /// the last symbol consumed during recovery.
94*16467b97STreehugger Robot     /// </summary>
95*16467b97STreehugger Robot     /// <remarks>
96*16467b97STreehugger Robot     /// <para>You must specify the input stream so that the erroneous text can
97*16467b97STreehugger Robot     /// be packaged up in the error node. The exception could be useful
98*16467b97STreehugger Robot     /// to some applications; default implementation stores ptr to it in
99*16467b97STreehugger Robot     /// the CommonErrorNode.</para>
100*16467b97STreehugger Robot     ///
101*16467b97STreehugger Robot     /// <para>This only makes sense during token parsing, not tree parsing.
102*16467b97STreehugger Robot     /// Tree parsing should happen only when parsing and tree construction
103*16467b97STreehugger Robot     /// succeed.</para>
104*16467b97STreehugger Robot     /// </remarks>
ErrorNode(const Input: ITokenStream; const Start, Stop: IToken;105*16467b97STreehugger Robot     function ErrorNode(const Input: ITokenStream; const Start, Stop: IToken;
106*16467b97STreehugger Robot       const E: ERecognitionException): IANTLRInterface;
107*16467b97STreehugger Robot 
108*16467b97STreehugger Robot     /// <summary>
109*16467b97STreehugger Robot     /// Is tree considered a nil node used to make lists of child nodes?
110*16467b97STreehugger Robot     /// </summary>
IsNil(const Tree: IANTLRInterface)111*16467b97STreehugger Robot     function IsNil(const Tree: IANTLRInterface): Boolean;
112*16467b97STreehugger Robot 
113*16467b97STreehugger Robot     /// <summary>
114*16467b97STreehugger Robot     /// Add a child to the tree t.  If child is a flat tree (a list), make all
115*16467b97STreehugger Robot     /// in list children of t.
116*16467b97STreehugger Robot     /// </summary>
117*16467b97STreehugger Robot     /// <remarks>
118*16467b97STreehugger Robot     /// <para>
119*16467b97STreehugger Robot     /// Warning: if t has no children, but child does and child isNil then you
120*16467b97STreehugger Robot     /// can decide it is ok to move children to t via t.children = child.children;
121*16467b97STreehugger Robot     /// i.e., without copying the array.  Just make sure that this is consistent
122*16467b97STreehugger Robot     /// with have the user will build ASTs. Do nothing if t or child is null.
123*16467b97STreehugger Robot     /// </para>
124*16467b97STreehugger Robot     /// <para>
125*16467b97STreehugger Robot     /// This is for construction and I'm not sure it's completely general for
126*16467b97STreehugger Robot     /// a tree's addChild method to work this way.  Make sure you differentiate
127*16467b97STreehugger Robot     /// between your tree's addChild and this parser tree construction addChild
128*16467b97STreehugger Robot     /// if it's not ok to move children to t with a simple assignment.
129*16467b97STreehugger Robot     /// </para>
130*16467b97STreehugger Robot     /// </remarks>
131*16467b97STreehugger Robot     procedure AddChild(const T, Child: IANTLRInterface);
132*16467b97STreehugger Robot 
133*16467b97STreehugger Robot     /// <summary>
134*16467b97STreehugger Robot     /// If oldRoot is a nil root, just copy or move the children to newRoot.
135*16467b97STreehugger Robot     /// If not a nil root, make oldRoot a child of newRoot.
136*16467b97STreehugger Robot     /// </summary>
137*16467b97STreehugger Robot     /// <remarks>
138*16467b97STreehugger Robot     ///
139*16467b97STreehugger Robot     ///   old=^(nil a b c), new=r yields ^(r a b c)
140*16467b97STreehugger Robot     ///   old=^(a b c), new=r yields ^(r ^(a b c))
141*16467b97STreehugger Robot     ///
142*16467b97STreehugger Robot     /// If newRoot is a nil-rooted single child tree, use the single
143*16467b97STreehugger Robot     /// child as the new root node.
144*16467b97STreehugger Robot     ///
145*16467b97STreehugger Robot     ///   old=^(nil a b c), new=^(nil r) yields ^(r a b c)
146*16467b97STreehugger Robot     ///   old=^(a b c), new=^(nil r) yields ^(r ^(a b c))
147*16467b97STreehugger Robot     ///
148*16467b97STreehugger Robot     /// If oldRoot was null, it's ok, just return newRoot (even if isNil).
149*16467b97STreehugger Robot     ///
150*16467b97STreehugger Robot     ///   old=null, new=r yields r
151*16467b97STreehugger Robot     ///   old=null, new=^(nil r) yields ^(nil r)
152*16467b97STreehugger Robot     ///
153*16467b97STreehugger Robot     /// Return newRoot.  Throw an exception if newRoot is not a
154*16467b97STreehugger Robot     /// simple node or nil root with a single child node--it must be a root
155*16467b97STreehugger Robot     /// node.  If newRoot is ^(nil x) return x as newRoot.
156*16467b97STreehugger Robot     ///
157*16467b97STreehugger Robot     /// Be advised that it's ok for newRoot to point at oldRoot's
158*16467b97STreehugger Robot     /// children; i.e., you don't have to copy the list.  We are
159*16467b97STreehugger Robot     /// constructing these nodes so we should have this control for
160*16467b97STreehugger Robot     /// efficiency.
161*16467b97STreehugger Robot     /// </remarks>
BecomeRoot(const NewRoot, OldRoot: IANTLRInterface)162*16467b97STreehugger Robot     function BecomeRoot(const NewRoot, OldRoot: IANTLRInterface): IANTLRInterface; overload;
163*16467b97STreehugger Robot 
164*16467b97STreehugger Robot     /// <summary>
165*16467b97STreehugger Robot     /// Given the root of the subtree created for this rule, post process
166*16467b97STreehugger Robot     /// it to do any simplifications or whatever you want.  A required
167*16467b97STreehugger Robot     /// behavior is to convert ^(nil singleSubtree) to singleSubtree
168*16467b97STreehugger Robot     /// as the setting of start/stop indexes relies on a single non-nil root
169*16467b97STreehugger Robot     /// for non-flat trees.
170*16467b97STreehugger Robot     ///
171*16467b97STreehugger Robot     /// Flat trees such as for lists like "idlist : ID+ ;" are left alone
172*16467b97STreehugger Robot     /// unless there is only one ID.  For a list, the start/stop indexes
173*16467b97STreehugger Robot     /// are set in the nil node.
174*16467b97STreehugger Robot     ///
175*16467b97STreehugger Robot     /// This method is executed after all rule tree construction and right
176*16467b97STreehugger Robot     /// before SetTokenBoundaries().
177*16467b97STreehugger Robot     /// </summary>
RulePostProcessing(const Root: IANTLRInterface)178*16467b97STreehugger Robot     function RulePostProcessing(const Root: IANTLRInterface): IANTLRInterface;
179*16467b97STreehugger Robot 
180*16467b97STreehugger Robot     /// <summary>
181*16467b97STreehugger Robot     /// For identifying trees. How to identify nodes so we can say "add node
182*16467b97STreehugger Robot     /// to a prior node"?
183*16467b97STreehugger Robot     /// </summary>
184*16467b97STreehugger Robot     /// <remarks>
185*16467b97STreehugger Robot     /// Even BecomeRoot is an issue. Ok, we could:
186*16467b97STreehugger Robot     /// <list type="number">
187*16467b97STreehugger Robot     ///   <item>Number the nodes as they are created?</item>
188*16467b97STreehugger Robot     ///   <item>
189*16467b97STreehugger Robot     ///     Use the original framework assigned hashcode that's unique
190*16467b97STreehugger Robot     ///     across instances of a given type.
191*16467b97STreehugger Robot     ///     WARNING: This is usually implemented either as IL to make a
192*16467b97STreehugger Robot     ///     non-virt call to object.GetHashCode() or by via a call to
193*16467b97STreehugger Robot     ///     System.Runtime.CompilerServices.RuntimeHelpers.GetHashCode().
194*16467b97STreehugger Robot     ///     Both have issues especially on .NET 1.x and Mono.
195*16467b97STreehugger Robot     ///   </item>
196*16467b97STreehugger Robot     /// </list>
197*16467b97STreehugger Robot     /// </remarks>
GetUniqueID(const Node: IANTLRInterface)198*16467b97STreehugger Robot     function GetUniqueID(const Node: IANTLRInterface): Integer;
199*16467b97STreehugger Robot 
200*16467b97STreehugger Robot     // R e w r i t e  R u l e s
201*16467b97STreehugger Robot 
202*16467b97STreehugger Robot     /// <summary>
203*16467b97STreehugger Robot     /// Create a node for newRoot make it the root of oldRoot.
204*16467b97STreehugger Robot     /// If oldRoot is a nil root, just copy or move the children to newRoot.
205*16467b97STreehugger Robot     /// If not a nil root, make oldRoot a child of newRoot.
206*16467b97STreehugger Robot     ///
207*16467b97STreehugger Robot     /// Return node created for newRoot.
208*16467b97STreehugger Robot     /// </summary>
BecomeRoot(const NewRoot: IToken; const OldRoot: IANTLRInterface)209*16467b97STreehugger Robot     function BecomeRoot(const NewRoot: IToken; const OldRoot: IANTLRInterface): IANTLRInterface; overload;
210*16467b97STreehugger Robot 
211*16467b97STreehugger Robot     /// <summary>Create a new node derived from a token, with a new token type.
212*16467b97STreehugger Robot     /// This is invoked from an imaginary node ref on right side of a
213*16467b97STreehugger Robot     /// rewrite rule as IMAG[$tokenLabel].
214*16467b97STreehugger Robot     ///
215*16467b97STreehugger Robot     /// This should invoke createToken(Token).
216*16467b97STreehugger Robot     /// </summary>
CreateNode(const TokenType: Integer; const FromToken: IToken)217*16467b97STreehugger Robot     function CreateNode(const TokenType: Integer; const FromToken: IToken): IANTLRInterface; overload;
218*16467b97STreehugger Robot 
219*16467b97STreehugger Robot     /// <summary>Same as Create(tokenType,fromToken) except set the text too.
220*16467b97STreehugger Robot     /// This is invoked from an imaginary node ref on right side of a
221*16467b97STreehugger Robot     /// rewrite rule as IMAG[$tokenLabel, "IMAG"].
222*16467b97STreehugger Robot     ///
223*16467b97STreehugger Robot     /// This should invoke createToken(Token).
224*16467b97STreehugger Robot     /// </summary>
CreateNode(const TokenType: Integer; const FromToken: IToken;225*16467b97STreehugger Robot     function CreateNode(const TokenType: Integer; const FromToken: IToken;
226*16467b97STreehugger Robot       const Text: String): IANTLRInterface; overload;
227*16467b97STreehugger Robot 
228*16467b97STreehugger Robot     /// <summary>Create a new node derived from a token, with a new token type.
229*16467b97STreehugger Robot     /// This is invoked from an imaginary node ref on right side of a
230*16467b97STreehugger Robot     /// rewrite rule as IMAG["IMAG"].
231*16467b97STreehugger Robot     ///
232*16467b97STreehugger Robot     /// This should invoke createToken(int,String).
233*16467b97STreehugger Robot     /// </summary>
CreateNode(const TokenType: Integer; const Text: String)234*16467b97STreehugger Robot     function CreateNode(const TokenType: Integer; const Text: String): IANTLRInterface; overload;
235*16467b97STreehugger Robot 
236*16467b97STreehugger Robot     // C o n t e n t
237*16467b97STreehugger Robot 
238*16467b97STreehugger Robot     /// <summary>For tree parsing, I need to know the token type of a node </summary>
GetNodeType(const T: IANTLRInterface)239*16467b97STreehugger Robot     function GetNodeType(const T: IANTLRInterface): Integer;
240*16467b97STreehugger Robot 
241*16467b97STreehugger Robot     /// <summary>Node constructors can set the type of a node </summary>
242*16467b97STreehugger Robot     procedure SetNodeType(const T: IANTLRInterface; const NodeType: Integer);
243*16467b97STreehugger Robot 
GetNodeText(const T: IANTLRInterface)244*16467b97STreehugger Robot     function GetNodeText(const T: IANTLRInterface): String;
245*16467b97STreehugger Robot 
246*16467b97STreehugger Robot     /// <summary>Node constructors can set the text of a node </summary>
247*16467b97STreehugger Robot     procedure SetNodeText(const T: IANTLRInterface; const Text: String);
248*16467b97STreehugger Robot 
249*16467b97STreehugger Robot     /// <summary>
250*16467b97STreehugger Robot     /// Return the token object from which this node was created.
251*16467b97STreehugger Robot     /// </summary>
252*16467b97STreehugger Robot     /// <remarks>
253*16467b97STreehugger Robot     /// Currently used only for printing an error message. The error
254*16467b97STreehugger Robot     /// display routine in BaseRecognizer needs to display where the
255*16467b97STreehugger Robot     /// input the error occurred. If your tree of limitation does not
256*16467b97STreehugger Robot     /// store information that can lead you to the token, you can create
257*16467b97STreehugger Robot     /// a token filled with the appropriate information and pass that back.
258*16467b97STreehugger Robot     /// <see cref="BaseRecognizer.GetErrorMessage"/>
259*16467b97STreehugger Robot     /// </remarks>
GetToken(const TreeNode: IANTLRInterface)260*16467b97STreehugger Robot     function GetToken(const TreeNode: IANTLRInterface): IToken;
261*16467b97STreehugger Robot 
262*16467b97STreehugger Robot     /// <summary>
263*16467b97STreehugger Robot     /// Where are the bounds in the input token stream for this node and
264*16467b97STreehugger Robot     /// all children?
265*16467b97STreehugger Robot     /// </summary>
266*16467b97STreehugger Robot     /// <remarks>
267*16467b97STreehugger Robot     /// Each rule that creates AST nodes will call this
268*16467b97STreehugger Robot     /// method right before returning.  Flat trees (i.e., lists) will
269*16467b97STreehugger Robot     /// still usually have a nil root node just to hold the children list.
270*16467b97STreehugger Robot     /// That node would contain the start/stop indexes then.
271*16467b97STreehugger Robot     /// </remarks>
272*16467b97STreehugger Robot     procedure SetTokenBoundaries(const T: IANTLRInterface; const StartToken,
273*16467b97STreehugger Robot       StopToken: IToken);
274*16467b97STreehugger Robot 
275*16467b97STreehugger Robot     /// <summary>
276*16467b97STreehugger Robot     /// Get the token start index for this subtree; return -1 if no such index
277*16467b97STreehugger Robot     /// </summary>
GetTokenStartIndex(const T: IANTLRInterface)278*16467b97STreehugger Robot     function GetTokenStartIndex(const T: IANTLRInterface): Integer;
279*16467b97STreehugger Robot 
280*16467b97STreehugger Robot     /// <summary>
281*16467b97STreehugger Robot     /// Get the token stop index for this subtree; return -1 if no such index
282*16467b97STreehugger Robot     /// </summary>
GetTokenStopIndex(const T: IANTLRInterface)283*16467b97STreehugger Robot     function GetTokenStopIndex(const T: IANTLRInterface): Integer;
284*16467b97STreehugger Robot 
285*16467b97STreehugger Robot     // N a v i g a t i o n  /  T r e e  P a r s i n g
286*16467b97STreehugger Robot 
287*16467b97STreehugger Robot     /// <summary>Get a child 0..n-1 node </summary>
GetChild(const T: IANTLRInterface; const I: Integer)288*16467b97STreehugger Robot     function GetChild(const T: IANTLRInterface; const I: Integer): IANTLRInterface;
289*16467b97STreehugger Robot 
290*16467b97STreehugger Robot     /// <summary>Set ith child (0..n-1) to t; t must be non-null and non-nil node</summary>
291*16467b97STreehugger Robot     procedure SetChild(const T: IANTLRInterface; const I: Integer; const Child: IANTLRInterface);
292*16467b97STreehugger Robot 
293*16467b97STreehugger Robot     /// <summary>Remove ith child and shift children down from right.</summary>
DeleteChild(const T: IANTLRInterface; const I: Integer)294*16467b97STreehugger Robot     function DeleteChild(const T: IANTLRInterface; const I: Integer): IANTLRInterface;
295*16467b97STreehugger Robot 
296*16467b97STreehugger Robot     /// <summary>How many children?  If 0, then this is a leaf node </summary>
GetChildCount(const T: IANTLRInterface)297*16467b97STreehugger Robot     function GetChildCount(const T: IANTLRInterface): Integer;
298*16467b97STreehugger Robot 
299*16467b97STreehugger Robot     /// <summary>
300*16467b97STreehugger Robot     /// Who is the parent node of this node; if null, implies node is root.
301*16467b97STreehugger Robot     /// </summary>
302*16467b97STreehugger Robot     /// <remarks>
303*16467b97STreehugger Robot     /// If your node type doesn't handle this, it's ok but the tree rewrites
304*16467b97STreehugger Robot     /// in tree parsers need this functionality.
305*16467b97STreehugger Robot     /// </remarks>
GetParent(const T: IANTLRInterface)306*16467b97STreehugger Robot     function GetParent(const T: IANTLRInterface): IANTLRInterface;
307*16467b97STreehugger Robot     procedure SetParent(const T, Parent: IANTLRInterface);
308*16467b97STreehugger Robot 
309*16467b97STreehugger Robot     /// <summary>
310*16467b97STreehugger Robot     /// What index is this node in the child list? Range: 0..n-1
311*16467b97STreehugger Robot     /// </summary>
312*16467b97STreehugger Robot     /// <remarks>
313*16467b97STreehugger Robot     /// If your node type doesn't handle this, it's ok but the tree rewrites
314*16467b97STreehugger Robot     /// in tree parsers need this functionality.
315*16467b97STreehugger Robot     /// </remarks>
GetChildIndex(const T: IANTLRInterface)316*16467b97STreehugger Robot     function GetChildIndex(const T: IANTLRInterface): Integer;
317*16467b97STreehugger Robot     procedure SetChildIdex(const T: IANTLRInterface; const Index: Integer);
318*16467b97STreehugger Robot 
319*16467b97STreehugger Robot     /// <summary>
320*16467b97STreehugger Robot     /// Replace from start to stop child index of parent with t, which might
321*16467b97STreehugger Robot     /// be a list.  Number of children may be different after this call.
322*16467b97STreehugger Robot     /// </summary>
323*16467b97STreehugger Robot     /// <remarks>
324*16467b97STreehugger Robot     /// If parent is null, don't do anything; must be at root of overall tree.
325*16467b97STreehugger Robot     /// Can't replace whatever points to the parent externally.  Do nothing.
326*16467b97STreehugger Robot     /// </remarks>
327*16467b97STreehugger Robot     procedure ReplaceChildren(const Parent: IANTLRInterface; const StartChildIndex,
328*16467b97STreehugger Robot       StopChildIndex: Integer; const T: IANTLRInterface);
329*16467b97STreehugger Robot   end;
330*16467b97STreehugger Robot 
331*16467b97STreehugger Robot   /// <summary>A stream of tree nodes, accessing nodes from a tree of some kind </summary>
332*16467b97STreehugger Robot   ITreeNodeStream = interface(IIntStream)
333*16467b97STreehugger Robot   ['{75EA5C06-8145-48F5-9A56-43E481CE86C6}']
334*16467b97STreehugger Robot     { Property accessors }
GetTreeSource()335*16467b97STreehugger Robot     function GetTreeSource: IANTLRInterface;
GetTokenStream()336*16467b97STreehugger Robot     function GetTokenStream: ITokenStream;
GetTreeAdaptor()337*16467b97STreehugger Robot     function GetTreeAdaptor: ITreeAdaptor;
338*16467b97STreehugger Robot     procedure SetHasUniqueNavigationNodes(const Value: Boolean);
339*16467b97STreehugger Robot 
340*16467b97STreehugger Robot     { Methods }
341*16467b97STreehugger Robot 
342*16467b97STreehugger Robot     /// <summary>Get a tree node at an absolute index i; 0..n-1.</summary>
343*16467b97STreehugger Robot     /// <remarks>
344*16467b97STreehugger Robot     /// If you don't want to buffer up nodes, then this method makes no
345*16467b97STreehugger Robot     /// sense for you.
346*16467b97STreehugger Robot     /// </remarks>
Get(const I: Integer)347*16467b97STreehugger Robot     function Get(const I: Integer): IANTLRInterface;
348*16467b97STreehugger Robot 
349*16467b97STreehugger Robot     /// <summary>
350*16467b97STreehugger Robot     /// Get tree node at current input pointer + i ahead where i=1 is next node.
351*16467b97STreehugger Robot     /// i&lt;0 indicates nodes in the past.  So LT(-1) is previous node, but
352*16467b97STreehugger Robot     /// implementations are not required to provide results for k &lt; -1.
353*16467b97STreehugger Robot     /// LT(0) is undefined.  For i&gt;=n, return null.
354*16467b97STreehugger Robot     /// Return null for LT(0) and any index that results in an absolute address
355*16467b97STreehugger Robot     /// that is negative.
356*16467b97STreehugger Robot     ///
357*16467b97STreehugger Robot     /// This is analogus to the LT() method of the TokenStream, but this
358*16467b97STreehugger Robot     /// returns a tree node instead of a token.  Makes code gen identical
359*16467b97STreehugger Robot     /// for both parser and tree grammars. :)
360*16467b97STreehugger Robot     /// </summary>
LT(const K: Integer)361*16467b97STreehugger Robot     function LT(const K: Integer): IANTLRInterface;
362*16467b97STreehugger Robot 
363*16467b97STreehugger Robot     /// <summary>Return the text of all nodes from start to stop, inclusive.
364*16467b97STreehugger Robot     /// If the stream does not buffer all the nodes then it can still
365*16467b97STreehugger Robot     /// walk recursively from start until stop.  You can always return
366*16467b97STreehugger Robot     /// null or "" too, but users should not access $ruleLabel.text in
367*16467b97STreehugger Robot     /// an action of course in that case.
368*16467b97STreehugger Robot     /// </summary>
ToString(const Start, Stop: IANTLRInterface)369*16467b97STreehugger Robot     function ToString(const Start, Stop: IANTLRInterface): String; overload;
ToString()370*16467b97STreehugger Robot     function ToString: String; overload;
371*16467b97STreehugger Robot 
372*16467b97STreehugger Robot     // REWRITING TREES (used by tree parser)
373*16467b97STreehugger Robot 
374*16467b97STreehugger Robot     /// <summary>
375*16467b97STreehugger Robot     /// Replace from start to stop child index of parent with t, which might
376*16467b97STreehugger Robot     /// be a list.  Number of children may be different after this call.
377*16467b97STreehugger Robot     /// </summary>
378*16467b97STreehugger Robot     /// <remarks>
379*16467b97STreehugger Robot     /// The stream is notified because it is walking the tree and might need
380*16467b97STreehugger Robot     /// to know you are monkeying with the underlying tree.  Also, it might be
381*16467b97STreehugger Robot     /// able to modify the node stream to avoid restreaming for future phases.
382*16467b97STreehugger Robot     ///
383*16467b97STreehugger Robot     /// If parent is null, don't do anything; must be at root of overall tree.
384*16467b97STreehugger Robot     /// Can't replace whatever points to the parent externally.  Do nothing.
385*16467b97STreehugger Robot     /// </remarks>
386*16467b97STreehugger Robot     procedure ReplaceChildren(const Parent: IANTLRInterface; const StartChildIndex,
387*16467b97STreehugger Robot       StopChildIndex: Integer; const T: IANTLRInterface);
388*16467b97STreehugger Robot 
389*16467b97STreehugger Robot     { Properties }
390*16467b97STreehugger Robot 
391*16467b97STreehugger Robot     /// <summary>
392*16467b97STreehugger Robot     /// Where is this stream pulling nodes from?  This is not the name, but
393*16467b97STreehugger Robot     /// the object that provides node objects.
394*16467b97STreehugger Robot     ///
395*16467b97STreehugger Robot     /// TODO: do we really need this?
396*16467b97STreehugger Robot     /// </summary>
397*16467b97STreehugger Robot     property TreeSource: IANTLRInterface read GetTreeSource;
398*16467b97STreehugger Robot 
399*16467b97STreehugger Robot     /// <summary>
400*16467b97STreehugger Robot     /// Get the ITokenStream from which this stream's Tree was created
401*16467b97STreehugger Robot     /// (may be null)
402*16467b97STreehugger Robot     /// </summary>
403*16467b97STreehugger Robot     /// <remarks>
404*16467b97STreehugger Robot     /// If the tree associated with this stream was created from a
405*16467b97STreehugger Robot     /// TokenStream, you can specify it here.  Used to do rule $text
406*16467b97STreehugger Robot     /// attribute in tree parser.  Optional unless you use tree parser
407*16467b97STreehugger Robot     /// rule text attribute or output=template and rewrite=true options.
408*16467b97STreehugger Robot     /// </remarks>
409*16467b97STreehugger Robot     property TokenStream: ITokenStream read GetTokenStream;
410*16467b97STreehugger Robot 
411*16467b97STreehugger Robot     /// <summary>
412*16467b97STreehugger Robot     /// What adaptor can tell me how to interpret/navigate nodes and trees.
413*16467b97STreehugger Robot     /// E.g., get text of a node.
414*16467b97STreehugger Robot     /// </summary>
415*16467b97STreehugger Robot     property TreeAdaptor: ITreeAdaptor read GetTreeAdaptor;
416*16467b97STreehugger Robot 
417*16467b97STreehugger Robot     /// <summary>
418*16467b97STreehugger Robot     /// As we flatten the tree, we use UP, DOWN nodes to represent
419*16467b97STreehugger Robot     /// the tree structure.  When debugging we need unique nodes
420*16467b97STreehugger Robot     /// so we have to instantiate new ones.  When doing normal tree
421*16467b97STreehugger Robot     /// parsing, it's slow and a waste of memory to create unique
422*16467b97STreehugger Robot     /// navigation nodes.  Default should be false;
423*16467b97STreehugger Robot     /// </summary>
424*16467b97STreehugger Robot     property HasUniqueNavigationNodes: Boolean write SetHasUniqueNavigationNodes;
425*16467b97STreehugger Robot   end;
426*16467b97STreehugger Robot 
427*16467b97STreehugger Robot   /// <summary>
428*16467b97STreehugger Robot   /// What does a tree look like?  ANTLR has a number of support classes
429*16467b97STreehugger Robot   /// such as CommonTreeNodeStream that work on these kinds of trees.  You
430*16467b97STreehugger Robot   /// don't have to make your trees implement this interface, but if you do,
431*16467b97STreehugger Robot   /// you'll be able to use more support code.
432*16467b97STreehugger Robot   ///
433*16467b97STreehugger Robot   /// NOTE: When constructing trees, ANTLR can build any kind of tree; it can
434*16467b97STreehugger Robot   /// even use Token objects as trees if you add a child list to your tokens.
435*16467b97STreehugger Robot   ///
436*16467b97STreehugger Robot   /// This is a tree node without any payload; just navigation and factory stuff.
437*16467b97STreehugger Robot   /// </summary>
438*16467b97STreehugger Robot   ITree = interface(IANTLRInterface)
439*16467b97STreehugger Robot   ['{4B6EFB53-EBF6-4647-BA4D-48B68134DC2A}']
440*16467b97STreehugger Robot     { Property accessors }
GetChildCount()441*16467b97STreehugger Robot     function GetChildCount: Integer;
GetParent()442*16467b97STreehugger Robot     function GetParent: ITree;
443*16467b97STreehugger Robot     procedure SetParent(const Value: ITree);
GetChildIndex()444*16467b97STreehugger Robot     function GetChildIndex: Integer;
445*16467b97STreehugger Robot     procedure SetChildIndex(const Value: Integer);
GetIsNil()446*16467b97STreehugger Robot     function GetIsNil: Boolean;
GetTokenType()447*16467b97STreehugger Robot     function GetTokenType: Integer;
GetText()448*16467b97STreehugger Robot     function GetText: String;
GetLine()449*16467b97STreehugger Robot     function GetLine: Integer;
GetCharPositionInLine()450*16467b97STreehugger Robot     function GetCharPositionInLine: Integer;
GetTokenStartIndex()451*16467b97STreehugger Robot     function GetTokenStartIndex: Integer;
452*16467b97STreehugger Robot     procedure SetTokenStartIndex(const Value: Integer);
GetTokenStopIndex()453*16467b97STreehugger Robot     function GetTokenStopIndex: Integer;
454*16467b97STreehugger Robot     procedure SetTokenStopIndex(const Value: Integer);
455*16467b97STreehugger Robot 
456*16467b97STreehugger Robot     { Methods }
457*16467b97STreehugger Robot 
458*16467b97STreehugger Robot     /// <summary>Set (or reset) the parent and child index values for all children</summary>
459*16467b97STreehugger Robot     procedure FreshenParentAndChildIndexes;
460*16467b97STreehugger Robot 
GetChild(const I: Integer)461*16467b97STreehugger Robot     function GetChild(const I: Integer): ITree;
462*16467b97STreehugger Robot 
463*16467b97STreehugger Robot     /// <summary>
464*16467b97STreehugger Robot     /// Add t as a child to this node.  If t is null, do nothing.  If t
465*16467b97STreehugger Robot     /// is nil, add all children of t to this' children.
466*16467b97STreehugger Robot     /// </summary>
467*16467b97STreehugger Robot     /// <param name="t">Tree to add</param>
468*16467b97STreehugger Robot     procedure AddChild(const T: ITree);
469*16467b97STreehugger Robot 
470*16467b97STreehugger Robot     /// <summary>Set ith child (0..n-1) to t; t must be non-null and non-nil node</summary>
471*16467b97STreehugger Robot     procedure SetChild(const I: Integer; const T: ITree);
472*16467b97STreehugger Robot 
DeleteChild(const I: Integer)473*16467b97STreehugger Robot     function DeleteChild(const I: Integer): IANTLRInterface;
474*16467b97STreehugger Robot 
475*16467b97STreehugger Robot     /// <summary>
476*16467b97STreehugger Robot     /// Delete children from start to stop and replace with t even if t is
477*16467b97STreehugger Robot     /// a list (nil-root tree).  num of children can increase or decrease.
478*16467b97STreehugger Robot     /// For huge child lists, inserting children can force walking rest of
479*16467b97STreehugger Robot     /// children to set their childindex; could be slow.
480*16467b97STreehugger Robot     /// </summary>
481*16467b97STreehugger Robot     procedure ReplaceChildren(const StartChildIndex, StopChildIndex: Integer;
482*16467b97STreehugger Robot       const T: IANTLRInterface);
483*16467b97STreehugger Robot 
DupNode()484*16467b97STreehugger Robot     function DupNode: ITree;
485*16467b97STreehugger Robot 
ToStringTree()486*16467b97STreehugger Robot     function ToStringTree: String;
487*16467b97STreehugger Robot 
ToString()488*16467b97STreehugger Robot     function ToString: String;
489*16467b97STreehugger Robot 
490*16467b97STreehugger Robot     { Properties }
491*16467b97STreehugger Robot 
492*16467b97STreehugger Robot     property ChildCount: Integer read GetChildCount;
493*16467b97STreehugger Robot 
494*16467b97STreehugger Robot     // Tree tracks parent and child index now > 3.0
495*16467b97STreehugger Robot     property Parent: ITree read GetParent write SetParent;
496*16467b97STreehugger Robot 
497*16467b97STreehugger Robot     /// <summary>This node is what child index? 0..n-1</summary>
498*16467b97STreehugger Robot     property ChildIndex: Integer read GetChildIndex write SetChildIndex;
499*16467b97STreehugger Robot 
500*16467b97STreehugger Robot     /// <summary>
501*16467b97STreehugger Robot     /// Indicates the node is a nil node but may still have children, meaning
502*16467b97STreehugger Robot     /// the tree is a flat list.
503*16467b97STreehugger Robot     /// </summary>
504*16467b97STreehugger Robot     property IsNil: Boolean read GetIsNil;
505*16467b97STreehugger Robot 
506*16467b97STreehugger Robot     /// <summary>Return a token type; needed for tree parsing </summary>
507*16467b97STreehugger Robot     property TokenType: Integer read GetTokenType;
508*16467b97STreehugger Robot 
509*16467b97STreehugger Robot     property Text: String read GetText;
510*16467b97STreehugger Robot 
511*16467b97STreehugger Robot     /// <summary>In case we don't have a token payload, what is the line for errors? </summary>
512*16467b97STreehugger Robot     property Line: Integer read GetLine;
513*16467b97STreehugger Robot     property CharPositionInLine: Integer read GetCharPositionInLine;
514*16467b97STreehugger Robot 
515*16467b97STreehugger Robot     /// <summary>
516*16467b97STreehugger Robot     /// What is the smallest token index (indexing from 0) for this node
517*16467b97STreehugger Robot     /// and its children?
518*16467b97STreehugger Robot     /// </summary>
519*16467b97STreehugger Robot     property TokenStartIndex: Integer read GetTokenStartIndex write SetTokenStartIndex;
520*16467b97STreehugger Robot 
521*16467b97STreehugger Robot     /// <summary>
522*16467b97STreehugger Robot     /// What is the largest token index (indexing from 0) for this node
523*16467b97STreehugger Robot     /// and its children?
524*16467b97STreehugger Robot     /// </summary>
525*16467b97STreehugger Robot     property TokenStopIndex: Integer read GetTokenStopIndex write SetTokenStopIndex;
526*16467b97STreehugger Robot   end;
527*16467b97STreehugger Robot 
528*16467b97STreehugger Robot   /// <summary>
529*16467b97STreehugger Robot   /// A generic tree implementation with no payload.  You must subclass to
530*16467b97STreehugger Robot   /// actually have any user data.  ANTLR v3 uses a list of children approach
531*16467b97STreehugger Robot   /// instead of the child-sibling approach in v2.  A flat tree (a list) is
532*16467b97STreehugger Robot   /// an empty node whose children represent the list.  An empty, but
533*16467b97STreehugger Robot   /// non-null node is called "nil".
534*16467b97STreehugger Robot   /// </summary>
535*16467b97STreehugger Robot   IBaseTree = interface(ITree)
536*16467b97STreehugger Robot   ['{6772F6EA-5FE0-40C6-BE5C-800AB2540E55}']
537*16467b97STreehugger Robot     { Property accessors }
GetChildren()538*16467b97STreehugger Robot     function GetChildren: IList<IBaseTree>;
GetChildIndex()539*16467b97STreehugger Robot     function GetChildIndex: Integer;
540*16467b97STreehugger Robot     procedure SetChildIndex(const Value: Integer);
GetParent()541*16467b97STreehugger Robot     function GetParent: ITree;
542*16467b97STreehugger Robot     procedure SetParent(const Value: ITree);
GetTokenType()543*16467b97STreehugger Robot     function GetTokenType: Integer;
GetTokenStartIndex()544*16467b97STreehugger Robot     function GetTokenStartIndex: Integer;
545*16467b97STreehugger Robot     procedure SetTokenStartIndex(const Value: Integer);
GetTokenStopIndex()546*16467b97STreehugger Robot     function GetTokenStopIndex: Integer;
547*16467b97STreehugger Robot     procedure SetTokenStopIndex(const Value: Integer);
GetText()548*16467b97STreehugger Robot     function GetText: String;
549*16467b97STreehugger Robot 
550*16467b97STreehugger Robot     { Methods }
551*16467b97STreehugger Robot 
552*16467b97STreehugger Robot     /// <summary>
553*16467b97STreehugger Robot     /// Add all elements of kids list as children of this node
554*16467b97STreehugger Robot     /// </summary>
555*16467b97STreehugger Robot     /// <param name="kids"></param>
556*16467b97STreehugger Robot     procedure AddChildren(const Kids: IList<IBaseTree>);
557*16467b97STreehugger Robot 
558*16467b97STreehugger Robot     procedure SetChild(const I: Integer; const T: ITree);
559*16467b97STreehugger Robot     procedure FreshenParentAndChildIndexes(const Offset: Integer);
560*16467b97STreehugger Robot 
561*16467b97STreehugger Robot     procedure SanityCheckParentAndChildIndexes; overload;
562*16467b97STreehugger Robot     procedure SanityCheckParentAndChildIndexes(const Parent: ITree;
563*16467b97STreehugger Robot       const I: Integer); overload;
564*16467b97STreehugger Robot 
565*16467b97STreehugger Robot     /// <summary>
566*16467b97STreehugger Robot     /// Print out a whole tree not just a node
567*16467b97STreehugger Robot     /// </summary>
ToStringTree()568*16467b97STreehugger Robot     function ToStringTree: String;
569*16467b97STreehugger Robot 
DupNode()570*16467b97STreehugger Robot     function DupNode: ITree;
571*16467b97STreehugger Robot 
572*16467b97STreehugger Robot     { Properties }
573*16467b97STreehugger Robot 
574*16467b97STreehugger Robot     /// <summary>
575*16467b97STreehugger Robot     /// Get the children internal list of children. Manipulating the list
576*16467b97STreehugger Robot     /// directly is not a supported operation (i.e. you do so at your own risk)
577*16467b97STreehugger Robot     /// </summary>
578*16467b97STreehugger Robot     property Children: IList<IBaseTree> read GetChildren;
579*16467b97STreehugger Robot 
580*16467b97STreehugger Robot     /// <summary>BaseTree doesn't track child indexes.</summary>
581*16467b97STreehugger Robot     property ChildIndex: Integer read GetChildIndex write SetChildIndex;
582*16467b97STreehugger Robot 
583*16467b97STreehugger Robot     /// <summary>BaseTree doesn't track parent pointers.</summary>
584*16467b97STreehugger Robot     property Parent: ITree read GetParent write SetParent;
585*16467b97STreehugger Robot 
586*16467b97STreehugger Robot     /// <summary>Return a token type; needed for tree parsing </summary>
587*16467b97STreehugger Robot     property TokenType: Integer read GetTokenType;
588*16467b97STreehugger Robot 
589*16467b97STreehugger Robot     /// <summary>
590*16467b97STreehugger Robot     /// What is the smallest token index (indexing from 0) for this node
591*16467b97STreehugger Robot     /// and its children?
592*16467b97STreehugger Robot     /// </summary>
593*16467b97STreehugger Robot     property TokenStartIndex: Integer read GetTokenStartIndex write SetTokenStartIndex;
594*16467b97STreehugger Robot 
595*16467b97STreehugger Robot     /// <summary>
596*16467b97STreehugger Robot     /// What is the largest token index (indexing from 0) for this node
597*16467b97STreehugger Robot     /// and its children?
598*16467b97STreehugger Robot     /// </summary>
599*16467b97STreehugger Robot     property TokenStopIndex: Integer read GetTokenStopIndex write SetTokenStopIndex;
600*16467b97STreehugger Robot 
601*16467b97STreehugger Robot     property Text: String read GetText;
602*16467b97STreehugger Robot   end;
603*16467b97STreehugger Robot 
604*16467b97STreehugger Robot   /// <summary>A tree node that is wrapper for a Token object. </summary>
605*16467b97STreehugger Robot   /// <remarks>
606*16467b97STreehugger Robot   /// After 3.0 release while building tree rewrite stuff, it became clear
607*16467b97STreehugger Robot   /// that computing parent and child index is very difficult and cumbersome.
608*16467b97STreehugger Robot   /// Better to spend the space in every tree node.  If you don't want these
609*16467b97STreehugger Robot   /// extra fields, it's easy to cut them out in your own BaseTree subclass.
610*16467b97STreehugger Robot   /// </remarks>
611*16467b97STreehugger Robot   ICommonTree = interface(IBaseTree)
612*16467b97STreehugger Robot   ['{791C0EA6-1E4D-443E-83E2-CC1EFEAECC8B}']
613*16467b97STreehugger Robot     { Property accessors }
GetToken()614*16467b97STreehugger Robot     function GetToken: IToken;
GetStartIndex()615*16467b97STreehugger Robot     function GetStartIndex: Integer;
616*16467b97STreehugger Robot     procedure SetStartIndex(const Value: Integer);
GetStopIndex()617*16467b97STreehugger Robot     function GetStopIndex: Integer;
618*16467b97STreehugger Robot     procedure SetStopIndex(const Value: Integer);
619*16467b97STreehugger Robot 
620*16467b97STreehugger Robot     { Properties }
621*16467b97STreehugger Robot     property Token: IToken read GetToken;
622*16467b97STreehugger Robot     property StartIndex: Integer read GetStartIndex write SetStartIndex;
623*16467b97STreehugger Robot     property StopIndex: Integer read GetStopIndex write SetStopIndex;
624*16467b97STreehugger Robot   end;
625*16467b97STreehugger Robot 
626*16467b97STreehugger Robot   // A node representing erroneous token range in token stream
627*16467b97STreehugger Robot   ICommonErrorNode = interface(ICommonTree)
628*16467b97STreehugger Robot   ['{20FF30BA-C055-4E8F-B3E7-7FFF6313853E}']
629*16467b97STreehugger Robot   end;
630*16467b97STreehugger Robot 
631*16467b97STreehugger Robot   /// <summary>
632*16467b97STreehugger Robot   /// A TreeAdaptor that works with any Tree implementation
633*16467b97STreehugger Robot   /// </summary>
634*16467b97STreehugger Robot   IBaseTreeAdaptor = interface(ITreeAdaptor)
635*16467b97STreehugger Robot   ['{B9CE670A-E53F-494C-B700-E4A3DF42D482}']
636*16467b97STreehugger Robot     /// <summary>
637*16467b97STreehugger Robot     /// This is generic in the sense that it will work with any kind of
638*16467b97STreehugger Robot     /// tree (not just the ITree interface).  It invokes the adaptor routines
639*16467b97STreehugger Robot     /// not the tree node routines to do the construction.
640*16467b97STreehugger Robot     /// </summary>
DupTree(const Tree: IANTLRInterface)641*16467b97STreehugger Robot     function DupTree(const Tree: IANTLRInterface): IANTLRInterface; overload;
DupTree(const T, Parent: IANTLRInterface)642*16467b97STreehugger Robot     function DupTree(const T, Parent: IANTLRInterface): IANTLRInterface; overload;
643*16467b97STreehugger Robot 
644*16467b97STreehugger Robot     /// <summary>
645*16467b97STreehugger Robot     /// Tell me how to create a token for use with imaginary token nodes.
646*16467b97STreehugger Robot     /// For example, there is probably no input symbol associated with imaginary
647*16467b97STreehugger Robot     /// token DECL, but you need to create it as a payload or whatever for
648*16467b97STreehugger Robot     /// the DECL node as in ^(DECL type ID).
649*16467b97STreehugger Robot     ///
650*16467b97STreehugger Robot     /// If you care what the token payload objects' type is, you should
651*16467b97STreehugger Robot     /// override this method and any other createToken variant.
652*16467b97STreehugger Robot     /// </summary>
CreateToken(const TokenType: Integer; const Text: String)653*16467b97STreehugger Robot     function CreateToken(const TokenType: Integer; const Text: String): IToken; overload;
654*16467b97STreehugger Robot 
655*16467b97STreehugger Robot     /// <summary>
656*16467b97STreehugger Robot     /// Tell me how to create a token for use with imaginary token nodes.
657*16467b97STreehugger Robot     /// For example, there is probably no input symbol associated with imaginary
658*16467b97STreehugger Robot     /// token DECL, but you need to create it as a payload or whatever for
659*16467b97STreehugger Robot     /// the DECL node as in ^(DECL type ID).
660*16467b97STreehugger Robot     ///
661*16467b97STreehugger Robot     /// This is a variant of createToken where the new token is derived from
662*16467b97STreehugger Robot     /// an actual real input token.  Typically this is for converting '{'
663*16467b97STreehugger Robot     /// tokens to BLOCK etc...  You'll see
664*16467b97STreehugger Robot     ///
665*16467b97STreehugger Robot     ///    r : lc='{' ID+ '}' -> ^(BLOCK[$lc] ID+) ;
666*16467b97STreehugger Robot     ///
667*16467b97STreehugger Robot     /// If you care what the token payload objects' type is, you should
668*16467b97STreehugger Robot     /// override this method and any other createToken variant.
669*16467b97STreehugger Robot     /// </summary>
CreateToken(const FromToken: IToken)670*16467b97STreehugger Robot     function CreateToken(const FromToken: IToken): IToken; overload;
671*16467b97STreehugger Robot   end;
672*16467b97STreehugger Robot 
673*16467b97STreehugger Robot   /// <summary>
674*16467b97STreehugger Robot   /// A TreeAdaptor that works with any Tree implementation.  It provides
675*16467b97STreehugger Robot   /// really just factory methods; all the work is done by BaseTreeAdaptor.
676*16467b97STreehugger Robot   /// If you would like to have different tokens created than ClassicToken
677*16467b97STreehugger Robot   /// objects, you need to override this and then set the parser tree adaptor to
678*16467b97STreehugger Robot   /// use your subclass.
679*16467b97STreehugger Robot   ///
680*16467b97STreehugger Robot   /// To get your parser to build nodes of a different type, override
681*16467b97STreehugger Robot   /// Create(Token).
682*16467b97STreehugger Robot   /// </summary>
683*16467b97STreehugger Robot   ICommonTreeAdaptor = interface(IBaseTreeAdaptor)
684*16467b97STreehugger Robot   ['{B067EE7A-38EB-4156-9447-CDD6DDD6D13B}']
685*16467b97STreehugger Robot   end;
686*16467b97STreehugger Robot 
687*16467b97STreehugger Robot   /// <summary>
688*16467b97STreehugger Robot   /// A buffered stream of tree nodes.  Nodes can be from a tree of ANY kind.
689*16467b97STreehugger Robot   /// </summary>
690*16467b97STreehugger Robot   /// <remarks>
691*16467b97STreehugger Robot   /// This node stream sucks all nodes out of the tree specified in the
692*16467b97STreehugger Robot   /// constructor during construction and makes pointers into the tree
693*16467b97STreehugger Robot   /// using an array of Object pointers. The stream necessarily includes
694*16467b97STreehugger Robot   /// pointers to DOWN and UP and EOF nodes.
695*16467b97STreehugger Robot   ///
696*16467b97STreehugger Robot   /// This stream knows how to mark/release for backtracking.
697*16467b97STreehugger Robot   ///
698*16467b97STreehugger Robot   /// This stream is most suitable for tree interpreters that need to
699*16467b97STreehugger Robot   /// jump around a lot or for tree parsers requiring speed (at cost of memory).
700*16467b97STreehugger Robot   /// There is some duplicated functionality here with UnBufferedTreeNodeStream
701*16467b97STreehugger Robot   /// but just in bookkeeping, not tree walking etc...
702*16467b97STreehugger Robot   ///
703*16467b97STreehugger Robot   /// <see cref="UnBufferedTreeNodeStream"/>
704*16467b97STreehugger Robot   ///
705*16467b97STreehugger Robot   /// </remarks>
706*16467b97STreehugger Robot   ICommonTreeNodeStream = interface(ITreeNodeStream)
707*16467b97STreehugger Robot   ['{0112FB31-AA1E-471C-ADC3-D97AC5D77E05}']
708*16467b97STreehugger Robot     { Property accessors }
GetCurrentSymbol()709*16467b97STreehugger Robot     function GetCurrentSymbol: IANTLRInterface;
GetTreeSource()710*16467b97STreehugger Robot     function GetTreeSource: IANTLRInterface;
GetSourceName()711*16467b97STreehugger Robot     function GetSourceName: String;
GetTokenStream()712*16467b97STreehugger Robot     function GetTokenStream: ITokenStream;
713*16467b97STreehugger Robot     procedure SetTokenStream(const Value: ITokenStream);
GetTreeAdaptor()714*16467b97STreehugger Robot     function GetTreeAdaptor: ITreeAdaptor;
715*16467b97STreehugger Robot     procedure SetTreeAdaptor(const Value: ITreeAdaptor);
GetHasUniqueNavigationNodes()716*16467b97STreehugger Robot     function GetHasUniqueNavigationNodes: Boolean;
717*16467b97STreehugger Robot     procedure SetHasUniqueNavigationNodes(const Value: Boolean);
718*16467b97STreehugger Robot 
719*16467b97STreehugger Robot     { Methods }
720*16467b97STreehugger Robot     /// <summary>
721*16467b97STreehugger Robot     /// Walk tree with depth-first-search and fill nodes buffer.
722*16467b97STreehugger Robot     /// Don't do DOWN, UP nodes if its a list (t is isNil).
723*16467b97STreehugger Robot     /// </summary>
724*16467b97STreehugger Robot     procedure FillBuffer(const T: IANTLRInterface);
725*16467b97STreehugger Robot 
Get(const I: Integer)726*16467b97STreehugger Robot     function Get(const I: Integer): IANTLRInterface;
727*16467b97STreehugger Robot 
LT(const K: Integer)728*16467b97STreehugger Robot     function LT(const K: Integer): IANTLRInterface;
729*16467b97STreehugger Robot 
730*16467b97STreehugger Robot     /// <summary>
731*16467b97STreehugger Robot     /// Look backwards k nodes
732*16467b97STreehugger Robot     /// </summary>
LB(const K: Integer)733*16467b97STreehugger Robot     function LB(const K: Integer): IANTLRInterface;
734*16467b97STreehugger Robot 
735*16467b97STreehugger Robot     /// <summary>
736*16467b97STreehugger Robot     /// Make stream jump to a new location, saving old location.
737*16467b97STreehugger Robot     /// Switch back with pop().
738*16467b97STreehugger Robot     /// </summary>
739*16467b97STreehugger Robot     procedure Push(const Index: Integer);
740*16467b97STreehugger Robot 
741*16467b97STreehugger Robot     /// <summary>
742*16467b97STreehugger Robot     /// Seek back to previous index saved during last Push() call.
743*16467b97STreehugger Robot     /// Return top of stack (return index).
744*16467b97STreehugger Robot     /// </summary>
Pop()745*16467b97STreehugger Robot     function Pop: Integer;
746*16467b97STreehugger Robot 
747*16467b97STreehugger Robot     procedure Reset;
748*16467b97STreehugger Robot 
749*16467b97STreehugger Robot     // Debugging
ToTokenString(const Start, Stop: Integer)750*16467b97STreehugger Robot     function ToTokenString(const Start, Stop: Integer): String;
ToString(const Start, Stop: IANTLRInterface)751*16467b97STreehugger Robot     function ToString(const Start, Stop: IANTLRInterface): String; overload;
ToString()752*16467b97STreehugger Robot     function ToString: String; overload;
753*16467b97STreehugger Robot 
754*16467b97STreehugger Robot     { Properties }
755*16467b97STreehugger Robot     property CurrentSymbol: IANTLRInterface read GetCurrentSymbol;
756*16467b97STreehugger Robot 
757*16467b97STreehugger Robot     /// <summary>
758*16467b97STreehugger Robot     /// Where is this stream pulling nodes from?  This is not the name, but
759*16467b97STreehugger Robot     /// the object that provides node objects.
760*16467b97STreehugger Robot     /// </summary>
761*16467b97STreehugger Robot     property TreeSource: IANTLRInterface read GetTreeSource;
762*16467b97STreehugger Robot 
763*16467b97STreehugger Robot     property SourceName: String read GetSourceName;
764*16467b97STreehugger Robot     property TokenStream: ITokenStream read GetTokenStream write SetTokenStream;
765*16467b97STreehugger Robot     property TreeAdaptor: ITreeAdaptor read GetTreeAdaptor write SetTreeAdaptor;
766*16467b97STreehugger Robot     property HasUniqueNavigationNodes: Boolean read GetHasUniqueNavigationNodes write SetHasUniqueNavigationNodes;
767*16467b97STreehugger Robot   end;
768*16467b97STreehugger Robot 
769*16467b97STreehugger Robot   /// <summary>
770*16467b97STreehugger Robot   /// A record of the rules used to Match a token sequence.  The tokens
771*16467b97STreehugger Robot   /// end up as the leaves of this tree and rule nodes are the interior nodes.
772*16467b97STreehugger Robot   /// This really adds no functionality, it is just an alias for CommonTree
773*16467b97STreehugger Robot   /// that is more meaningful (specific) and holds a String to display for a node.
774*16467b97STreehugger Robot   /// </summary>
775*16467b97STreehugger Robot   IParseTree = interface(IANTLRInterface)
776*16467b97STreehugger Robot   ['{1558F260-CAF8-4488-A242-3559BCE4E573}']
777*16467b97STreehugger Robot     { Methods }
778*16467b97STreehugger Robot 
779*16467b97STreehugger Robot     // Emit a token and all hidden nodes before.  EOF node holds all
780*16467b97STreehugger Robot     // hidden tokens after last real token.
ToStringWithHiddenTokens()781*16467b97STreehugger Robot     function ToStringWithHiddenTokens: String;
782*16467b97STreehugger Robot 
783*16467b97STreehugger Robot     // Print out the leaves of this tree, which means printing original
784*16467b97STreehugger Robot     // input back out.
ToInputString()785*16467b97STreehugger Robot     function ToInputString: String;
786*16467b97STreehugger Robot 
787*16467b97STreehugger Robot     procedure _ToStringLeaves(const Buf: TStringBuilder);
788*16467b97STreehugger Robot   end;
789*16467b97STreehugger Robot 
790*16467b97STreehugger Robot   /// <summary>
791*16467b97STreehugger Robot   /// A generic list of elements tracked in an alternative to be used in
792*16467b97STreehugger Robot   /// a -> rewrite rule.  We need to subclass to fill in the next() method,
793*16467b97STreehugger Robot   /// which returns either an AST node wrapped around a token payload or
794*16467b97STreehugger Robot   /// an existing subtree.
795*16467b97STreehugger Robot   ///
796*16467b97STreehugger Robot   /// Once you start next()ing, do not try to add more elements.  It will
797*16467b97STreehugger Robot   /// break the cursor tracking I believe.
798*16467b97STreehugger Robot   ///
799*16467b97STreehugger Robot   /// <see cref="RewriteRuleSubtreeStream"/>
800*16467b97STreehugger Robot   /// <see cref="RewriteRuleTokenStream"/>
801*16467b97STreehugger Robot   ///
802*16467b97STreehugger Robot   /// TODO: add mechanism to detect/puke on modification after reading from stream
803*16467b97STreehugger Robot   /// </summary>
804*16467b97STreehugger Robot   IRewriteRuleElementStream = interface(IANTLRInterface)
805*16467b97STreehugger Robot   ['{3CB6C521-F583-40DC-A1E3-4D7D57B98C74}']
806*16467b97STreehugger Robot     { Property accessors }
GetDescription()807*16467b97STreehugger Robot     function GetDescription: String;
808*16467b97STreehugger Robot 
809*16467b97STreehugger Robot     { Methods }
810*16467b97STreehugger Robot     procedure Add(const El: IANTLRInterface);
811*16467b97STreehugger Robot 
812*16467b97STreehugger Robot     /// <summary>
813*16467b97STreehugger Robot     /// Reset the condition of this stream so that it appears we have
814*16467b97STreehugger Robot     /// not consumed any of its elements.  Elements themselves are untouched.
815*16467b97STreehugger Robot     /// </summary>
816*16467b97STreehugger Robot     /// <remarks>
817*16467b97STreehugger Robot     /// Once we reset the stream, any future use will need duplicates.  Set
818*16467b97STreehugger Robot     /// the dirty bit.
819*16467b97STreehugger Robot     /// </remarks>
820*16467b97STreehugger Robot     procedure Reset;
821*16467b97STreehugger Robot 
HasNext()822*16467b97STreehugger Robot     function HasNext: Boolean;
823*16467b97STreehugger Robot 
824*16467b97STreehugger Robot     /// <summary>
825*16467b97STreehugger Robot     /// Return the next element in the stream.
826*16467b97STreehugger Robot     /// </summary>
NextTree()827*16467b97STreehugger Robot     function NextTree: IANTLRInterface;
NextNode()828*16467b97STreehugger Robot     function NextNode: IANTLRInterface;
829*16467b97STreehugger Robot 
Size()830*16467b97STreehugger Robot     function Size: Integer;
831*16467b97STreehugger Robot 
832*16467b97STreehugger Robot     { Properties }
833*16467b97STreehugger Robot     property Description: String read GetDescription;
834*16467b97STreehugger Robot   end;
835*16467b97STreehugger Robot 
836*16467b97STreehugger Robot   /// <summary>
837*16467b97STreehugger Robot   /// Queues up nodes matched on left side of -> in a tree parser. This is
838*16467b97STreehugger Robot   /// the analog of RewriteRuleTokenStream for normal parsers.
839*16467b97STreehugger Robot   /// </summary>
840*16467b97STreehugger Robot   IRewriteRuleNodeStream = interface(IRewriteRuleElementStream)
841*16467b97STreehugger Robot   ['{F60D1D36-FE13-4312-99DA-11E5F4BEBB66}']
842*16467b97STreehugger Robot     { Methods }
NextNode()843*16467b97STreehugger Robot     function NextNode: IANTLRInterface;
844*16467b97STreehugger Robot   end;
845*16467b97STreehugger Robot 
846*16467b97STreehugger Robot   IRewriteRuleSubtreeStream = interface(IRewriteRuleElementStream)
847*16467b97STreehugger Robot   ['{C6BDA145-D926-45BC-B293-67490D72829B}']
848*16467b97STreehugger Robot     { Methods }
849*16467b97STreehugger Robot 
850*16467b97STreehugger Robot     /// <summary>
851*16467b97STreehugger Robot     /// Treat next element as a single node even if it's a subtree.
852*16467b97STreehugger Robot     /// </summary>
853*16467b97STreehugger Robot     /// <remarks>
854*16467b97STreehugger Robot     /// This is used instead of next() when the result has to be a
855*16467b97STreehugger Robot     /// tree root node.  Also prevents us from duplicating recently-added
856*16467b97STreehugger Robot     /// children; e.g., ^(type ID)+ adds ID to type and then 2nd iteration
857*16467b97STreehugger Robot     /// must dup the type node, but ID has been added.
858*16467b97STreehugger Robot     ///
859*16467b97STreehugger Robot     /// Referencing a rule result twice is ok; dup entire tree as
860*16467b97STreehugger Robot     /// we can't be adding trees as root; e.g., expr expr.
861*16467b97STreehugger Robot     /// </remarks>
NextNode()862*16467b97STreehugger Robot     function NextNode: IANTLRInterface;
863*16467b97STreehugger Robot   end;
864*16467b97STreehugger Robot 
865*16467b97STreehugger Robot   IRewriteRuleTokenStream = interface(IRewriteRuleElementStream)
866*16467b97STreehugger Robot   ['{4D46AB00-7A19-4F69-B159-1EF09DB8C09C}']
867*16467b97STreehugger Robot     /// <summary>
868*16467b97STreehugger Robot     /// Get next token from stream and make a node for it.
869*16467b97STreehugger Robot     /// </summary>
870*16467b97STreehugger Robot     /// <remarks>
871*16467b97STreehugger Robot     /// ITreeAdaptor.Create() returns an object, so no further restrictions possible.
872*16467b97STreehugger Robot     /// </remarks>
NextNode()873*16467b97STreehugger Robot     function NextNode: IANTLRInterface;
874*16467b97STreehugger Robot 
NextToken()875*16467b97STreehugger Robot     function NextToken: IToken;
876*16467b97STreehugger Robot   end;
877*16467b97STreehugger Robot 
878*16467b97STreehugger Robot   /// <summary>
879*16467b97STreehugger Robot   /// A parser for a stream of tree nodes.  "tree grammars" result in a subclass
880*16467b97STreehugger Robot   /// of this.  All the error reporting and recovery is shared with Parser via
881*16467b97STreehugger Robot   /// the BaseRecognizer superclass.
882*16467b97STreehugger Robot   /// </summary>
883*16467b97STreehugger Robot   ITreeParser = interface(IBaseRecognizer)
884*16467b97STreehugger Robot   ['{20611FB3-9830-444D-B385-E8C2D094484B}']
885*16467b97STreehugger Robot     { Property accessors }
GetTreeNodeStream()886*16467b97STreehugger Robot     function GetTreeNodeStream: ITreeNodeStream;
887*16467b97STreehugger Robot     procedure SetTreeNodeStream(const Value: ITreeNodeStream);
888*16467b97STreehugger Robot 
889*16467b97STreehugger Robot     { Methods }
890*16467b97STreehugger Robot     procedure TraceIn(const RuleName: String; const RuleIndex: Integer);
891*16467b97STreehugger Robot     procedure TraceOut(const RuleName: String; const RuleIndex: Integer);
892*16467b97STreehugger Robot 
893*16467b97STreehugger Robot     { Properties }
894*16467b97STreehugger Robot     property TreeNodeStream: ITreeNodeStream read GetTreeNodeStream write SetTreeNodeStream;
895*16467b97STreehugger Robot   end;
896*16467b97STreehugger Robot 
897*16467b97STreehugger Robot   ITreePatternLexer = interface(IANTLRInterface)
898*16467b97STreehugger Robot   ['{C3FEC614-9E6F-48D2-ABAB-59FC83D8BC2F}']
899*16467b97STreehugger Robot     { Methods }
NextToken()900*16467b97STreehugger Robot     function NextToken: Integer;
SVal()901*16467b97STreehugger Robot     function SVal: String;
902*16467b97STreehugger Robot   end;
903*16467b97STreehugger Robot 
904*16467b97STreehugger Robot   IContextVisitor = interface(IANTLRInterface)
905*16467b97STreehugger Robot   ['{92B80D23-C63E-48B4-A9CD-EC2639317E43}']
906*16467b97STreehugger Robot     { Methods }
907*16467b97STreehugger Robot     procedure Visit(const T, Parent: IANTLRInterface; const ChildIndex: Integer;
908*16467b97STreehugger Robot       const Labels: IDictionary<String, IANTLRInterface>);
909*16467b97STreehugger Robot   end;
910*16467b97STreehugger Robot 
911*16467b97STreehugger Robot   /// <summary>
912*16467b97STreehugger Robot   /// Build and navigate trees with this object.  Must know about the names
913*16467b97STreehugger Robot   /// of tokens so you have to pass in a map or array of token names (from which
914*16467b97STreehugger Robot   /// this class can build the map).  I.e., Token DECL means nothing unless the
915*16467b97STreehugger Robot   /// class can translate it to a token type.
916*16467b97STreehugger Robot   /// </summary>
917*16467b97STreehugger Robot   /// <remarks>
918*16467b97STreehugger Robot   /// In order to create nodes and navigate, this class needs a TreeAdaptor.
919*16467b97STreehugger Robot   ///
920*16467b97STreehugger Robot   /// This class can build a token type -> node index for repeated use or for
921*16467b97STreehugger Robot   /// iterating over the various nodes with a particular type.
922*16467b97STreehugger Robot   ///
923*16467b97STreehugger Robot   /// This class works in conjunction with the TreeAdaptor rather than moving
924*16467b97STreehugger Robot   /// all this functionality into the adaptor.  An adaptor helps build and
925*16467b97STreehugger Robot   /// navigate trees using methods.  This class helps you do it with string
926*16467b97STreehugger Robot   /// patterns like "(A B C)".  You can create a tree from that pattern or
927*16467b97STreehugger Robot   /// match subtrees against it.
928*16467b97STreehugger Robot   /// </remarks>
929*16467b97STreehugger Robot   ITreeWizard = interface(IANTLRInterface)
930*16467b97STreehugger Robot   ['{4F440E19-893A-4E52-A979-E5377EAFA3B8}']
931*16467b97STreehugger Robot     { Methods }
932*16467b97STreehugger Robot     /// <summary>
933*16467b97STreehugger Robot     /// Compute a Map&lt;String, Integer&gt; that is an inverted index of
934*16467b97STreehugger Robot     /// tokenNames (which maps int token types to names).
935*16467b97STreehugger Robot     /// </summary>
ComputeTokenTypes(const TokenNames: TStringArray)936*16467b97STreehugger Robot     function ComputeTokenTypes(const TokenNames: TStringArray): IDictionary<String, Integer>;
937*16467b97STreehugger Robot 
938*16467b97STreehugger Robot     /// <summary>
939*16467b97STreehugger Robot     /// Using the map of token names to token types, return the type.
940*16467b97STreehugger Robot     /// </summary>
GetTokenType(const TokenName: String)941*16467b97STreehugger Robot     function GetTokenType(const TokenName: String): Integer;
942*16467b97STreehugger Robot 
943*16467b97STreehugger Robot     /// <summary>
944*16467b97STreehugger Robot     /// Walk the entire tree and make a node name to nodes mapping.
945*16467b97STreehugger Robot     /// </summary>
946*16467b97STreehugger Robot     /// <remarks>
947*16467b97STreehugger Robot     /// For now, use recursion but later nonrecursive version may be
948*16467b97STreehugger Robot     /// more efficient.  Returns Map&lt;Integer, List&gt; where the List is
949*16467b97STreehugger Robot     /// of your AST node type.  The Integer is the token type of the node.
950*16467b97STreehugger Robot     ///
951*16467b97STreehugger Robot     /// TODO: save this index so that find and visit are faster
952*16467b97STreehugger Robot     /// </remarks>
Index(const T: IANTLRInterface)953*16467b97STreehugger Robot     function Index(const T: IANTLRInterface): IDictionary<Integer, IList<IANTLRInterface>>;
954*16467b97STreehugger Robot 
955*16467b97STreehugger Robot     /// <summary>Return a List of tree nodes with token type ttype</summary>
Find(const T: IANTLRInterface; const TokenType: Integer)956*16467b97STreehugger Robot     function Find(const T: IANTLRInterface; const TokenType: Integer): IList<IANTLRInterface>; overload;
957*16467b97STreehugger Robot 
958*16467b97STreehugger Robot     /// <summary>Return a List of subtrees matching pattern</summary>
Find(const T: IANTLRInterface; const Pattern: String)959*16467b97STreehugger Robot     function Find(const T: IANTLRInterface; const Pattern: String): IList<IANTLRInterface>; overload;
960*16467b97STreehugger Robot 
FindFirst(const T: IANTLRInterface; const TokenType: Integer)961*16467b97STreehugger Robot     function FindFirst(const T: IANTLRInterface; const TokenType: Integer): IANTLRInterface; overload;
FindFirst(const T: IANTLRInterface; const Pattern: String)962*16467b97STreehugger Robot     function FindFirst(const T: IANTLRInterface; const Pattern: String): IANTLRInterface; overload;
963*16467b97STreehugger Robot 
964*16467b97STreehugger Robot     /// <summary>
965*16467b97STreehugger Robot     /// Visit every ttype node in t, invoking the visitor.
966*16467b97STreehugger Robot     /// </summary>
967*16467b97STreehugger Robot     /// <remarks>
968*16467b97STreehugger Robot     /// This is a quicker
969*16467b97STreehugger Robot     /// version of the general visit(t, pattern) method.  The labels arg
970*16467b97STreehugger Robot     /// of the visitor action method is never set (it's null) since using
971*16467b97STreehugger Robot     /// a token type rather than a pattern doesn't let us set a label.
972*16467b97STreehugger Robot     /// </remarks>
973*16467b97STreehugger Robot     procedure Visit(const T: IANTLRInterface; const TokenType: Integer;
974*16467b97STreehugger Robot       const Visitor: IContextVisitor); overload;
975*16467b97STreehugger Robot 
976*16467b97STreehugger Robot     /// <summary>
977*16467b97STreehugger Robot     /// For all subtrees that match the pattern, execute the visit action.
978*16467b97STreehugger Robot     /// </summary>
979*16467b97STreehugger Robot     /// <remarks>
980*16467b97STreehugger Robot     /// The implementation uses the root node of the pattern in combination
981*16467b97STreehugger Robot     /// with visit(t, ttype, visitor) so nil-rooted patterns are not allowed.
982*16467b97STreehugger Robot     /// Patterns with wildcard roots are also not allowed.
983*16467b97STreehugger Robot     /// </remarks>
984*16467b97STreehugger Robot     procedure Visit(const T: IANTLRInterface; const Pattern: String;
985*16467b97STreehugger Robot       const Visitor: IContextVisitor); overload;
986*16467b97STreehugger Robot 
987*16467b97STreehugger Robot     /// <summary>
988*16467b97STreehugger Robot     /// Given a pattern like (ASSIGN %lhs:ID %rhs:.) with optional labels
989*16467b97STreehugger Robot     /// on the various nodes and '.' (dot) as the node/subtree wildcard,
990*16467b97STreehugger Robot     /// return true if the pattern matches and fill the labels Map with
991*16467b97STreehugger Robot     /// the labels pointing at the appropriate nodes.  Return false if
992*16467b97STreehugger Robot     /// the pattern is malformed or the tree does not match.
993*16467b97STreehugger Robot     /// </summary>
994*16467b97STreehugger Robot     /// <remarks>
995*16467b97STreehugger Robot     /// If a node specifies a text arg in pattern, then that must match
996*16467b97STreehugger Robot     /// for that node in t.
997*16467b97STreehugger Robot     ///
998*16467b97STreehugger Robot     /// TODO: what's a better way to indicate bad pattern? Exceptions are a hassle
999*16467b97STreehugger Robot     /// </remarks>
Parse(const T: IANTLRInterface; const Pattern: String;1000*16467b97STreehugger Robot     function Parse(const T: IANTLRInterface; const Pattern: String;
1001*16467b97STreehugger Robot       const Labels: IDictionary<String, IANTLRInterface>): Boolean; overload;
Parse(const T: IANTLRInterface; const Pattern: String)1002*16467b97STreehugger Robot     function Parse(const T: IANTLRInterface; const Pattern: String): Boolean; overload;
1003*16467b97STreehugger Robot 
1004*16467b97STreehugger Robot     /// <summary>
1005*16467b97STreehugger Robot     /// Create a tree or node from the indicated tree pattern that closely
1006*16467b97STreehugger Robot     /// follows ANTLR tree grammar tree element syntax:
1007*16467b97STreehugger Robot     ///
1008*16467b97STreehugger Robot     ///   (root child1 ... child2).
1009*16467b97STreehugger Robot     ///
1010*16467b97STreehugger Robot     /// </summary>
1011*16467b97STreehugger Robot     /// <remarks>
1012*16467b97STreehugger Robot     /// You can also just pass in a node: ID
1013*16467b97STreehugger Robot     ///
1014*16467b97STreehugger Robot     /// Any node can have a text argument: ID[foo]
1015*16467b97STreehugger Robot     /// (notice there are no quotes around foo--it's clear it's a string).
1016*16467b97STreehugger Robot     ///
1017*16467b97STreehugger Robot     /// nil is a special name meaning "give me a nil node".  Useful for
1018*16467b97STreehugger Robot     /// making lists: (nil A B C) is a list of A B C.
1019*16467b97STreehugger Robot     /// </remarks>
CreateTreeOrNode(const Pattern: String)1020*16467b97STreehugger Robot     function CreateTreeOrNode(const Pattern: String): IANTLRInterface;
1021*16467b97STreehugger Robot 
1022*16467b97STreehugger Robot     /// <summary>
1023*16467b97STreehugger Robot     /// Compare type, structure, and text of two trees, assuming adaptor in
1024*16467b97STreehugger Robot     /// this instance of a TreeWizard.
1025*16467b97STreehugger Robot     /// </summary>
Equals(const T1, T2: IANTLRInterface)1026*16467b97STreehugger Robot     function Equals(const T1, T2: IANTLRInterface): Boolean; overload;
1027*16467b97STreehugger Robot 
1028*16467b97STreehugger Robot     /// <summary>
1029*16467b97STreehugger Robot     /// Compare t1 and t2; return true if token types/text, structure match exactly.
1030*16467b97STreehugger Robot     /// The trees are examined in their entirety so that (A B) does not match
1031*16467b97STreehugger Robot     /// (A B C) nor (A (B C)).
1032*16467b97STreehugger Robot     /// </summary>
1033*16467b97STreehugger Robot     /// <remarks>
1034*16467b97STreehugger Robot     /// TODO: allow them to pass in a comparator
1035*16467b97STreehugger Robot     /// TODO: have a version that is nonstatic so it can use instance adaptor
1036*16467b97STreehugger Robot     ///
1037*16467b97STreehugger Robot     /// I cannot rely on the tree node's equals() implementation as I make
1038*16467b97STreehugger Robot     /// no constraints at all on the node types nor interface etc...
1039*16467b97STreehugger Robot     /// </remarks>
Equals(const T1, T2: IANTLRInterface; const Adaptor: ITreeAdaptor)1040*16467b97STreehugger Robot     function Equals(const T1, T2: IANTLRInterface; const Adaptor: ITreeAdaptor): Boolean; overload;
1041*16467b97STreehugger Robot   end;
1042*16467b97STreehugger Robot 
1043*16467b97STreehugger Robot   ITreePatternParser = interface(IANTLRInterface)
1044*16467b97STreehugger Robot   ['{0CE3DF2A-7E4C-4A7C-8FE8-F1D7AFF97CAE}']
1045*16467b97STreehugger Robot     { Methods }
Pattern()1046*16467b97STreehugger Robot     function Pattern: IANTLRInterface;
ParseTree()1047*16467b97STreehugger Robot     function ParseTree: IANTLRInterface;
ParseNode()1048*16467b97STreehugger Robot     function ParseNode: IANTLRInterface;
1049*16467b97STreehugger Robot   end;
1050*16467b97STreehugger Robot 
1051*16467b97STreehugger Robot   /// <summary>
1052*16467b97STreehugger Robot   /// This is identical to the ParserRuleReturnScope except that
1053*16467b97STreehugger Robot   /// the start property is a tree node and not a Token object
1054*16467b97STreehugger Robot   /// when you are parsing trees.  To be generic the tree node types
1055*16467b97STreehugger Robot   /// have to be Object :(
1056*16467b97STreehugger Robot   /// </summary>
1057*16467b97STreehugger Robot   ITreeRuleReturnScope = interface(IRuleReturnScope)
1058*16467b97STreehugger Robot   ['{FA2B1766-34E5-4D92-8996-371D5CFED999}']
1059*16467b97STreehugger Robot   end;
1060*16467b97STreehugger Robot 
1061*16467b97STreehugger Robot   /// <summary>
1062*16467b97STreehugger Robot   /// A stream of tree nodes, accessing nodes from a tree of ANY kind.
1063*16467b97STreehugger Robot   /// </summary>
1064*16467b97STreehugger Robot   /// <remarks>
1065*16467b97STreehugger Robot   /// No new nodes should be created in tree during the walk.  A small buffer
1066*16467b97STreehugger Robot   /// of tokens is kept to efficiently and easily handle LT(i) calls, though
1067*16467b97STreehugger Robot   /// the lookahead mechanism is fairly complicated.
1068*16467b97STreehugger Robot   ///
1069*16467b97STreehugger Robot   /// For tree rewriting during tree parsing, this must also be able
1070*16467b97STreehugger Robot   /// to replace a set of children without "losing its place".
1071*16467b97STreehugger Robot   /// That part is not yet implemented.  Will permit a rule to return
1072*16467b97STreehugger Robot   /// a different tree and have it stitched into the output tree probably.
1073*16467b97STreehugger Robot   ///
1074*16467b97STreehugger Robot   /// <see cref="CommonTreeNodeStream"/>
1075*16467b97STreehugger Robot   ///
1076*16467b97STreehugger Robot   /// </remarks>
1077*16467b97STreehugger Robot   IUnBufferedTreeNodeStream = interface(ITreeNodeStream)
1078*16467b97STreehugger Robot   ['{E46367AD-ED41-4D97-824E-575A48F7435D}']
1079*16467b97STreehugger Robot     { Property accessors }
GetHasUniqueNavigationNodes()1080*16467b97STreehugger Robot     function GetHasUniqueNavigationNodes: Boolean;
1081*16467b97STreehugger Robot     procedure SetHasUniqueNavigationNodes(const Value: Boolean);
GetCurrent()1082*16467b97STreehugger Robot     function GetCurrent: IANTLRInterface;
GetTokenStream()1083*16467b97STreehugger Robot     function GetTokenStream: ITokenStream;
1084*16467b97STreehugger Robot     procedure SetTokenStream(const Value: ITokenStream);
1085*16467b97STreehugger Robot 
1086*16467b97STreehugger Robot     { Methods }
1087*16467b97STreehugger Robot     procedure Reset;
MoveNext()1088*16467b97STreehugger Robot     function MoveNext: Boolean;
1089*16467b97STreehugger Robot 
1090*16467b97STreehugger Robot     { Properties }
1091*16467b97STreehugger Robot     property HasUniqueNavigationNodes: Boolean read GetHasUniqueNavigationNodes write SetHasUniqueNavigationNodes;
1092*16467b97STreehugger Robot     property Current: IANTLRInterface read GetCurrent;
1093*16467b97STreehugger Robot     property TokenStream: ITokenStream read GetTokenStream write SetTokenStream;
1094*16467b97STreehugger Robot   end;
1095*16467b97STreehugger Robot 
1096*16467b97STreehugger Robot   /// <summary>Base class for all exceptions thrown during AST rewrite construction.</summary>
1097*16467b97STreehugger Robot   /// <remarks>
1098*16467b97STreehugger Robot   /// This signifies a case where the cardinality of two or more elements
1099*16467b97STreehugger Robot   /// in a subrule are different: (ID INT)+ where |ID|!=|INT|
1100*16467b97STreehugger Robot   /// </remarks>
1101*16467b97STreehugger Robot   ERewriteCardinalityException = class(Exception)
1102*16467b97STreehugger Robot   strict private
1103*16467b97STreehugger Robot     FElementDescription: String;
1104*16467b97STreehugger Robot   public
1105*16467b97STreehugger Robot     constructor Create(const AElementDescription: String);
1106*16467b97STreehugger Robot 
1107*16467b97STreehugger Robot     property ElementDescription: String read FElementDescription write FElementDescription;
1108*16467b97STreehugger Robot   end;
1109*16467b97STreehugger Robot 
1110*16467b97STreehugger Robot   /// <summary>
1111*16467b97STreehugger Robot   /// No elements within a (...)+ in a rewrite rule
1112*16467b97STreehugger Robot   /// </summary>
1113*16467b97STreehugger Robot   ERewriteEarlyExitException = class(ERewriteCardinalityException)
1114*16467b97STreehugger Robot     // No new declarations
1115*16467b97STreehugger Robot   end;
1116*16467b97STreehugger Robot 
1117*16467b97STreehugger Robot   /// <summary>
1118*16467b97STreehugger Robot   /// Ref to ID or expr but no tokens in ID stream or subtrees in expr stream
1119*16467b97STreehugger Robot   /// </summary>
1120*16467b97STreehugger Robot   ERewriteEmptyStreamException = class(ERewriteCardinalityException)
1121*16467b97STreehugger Robot     // No new declarations
1122*16467b97STreehugger Robot   end;
1123*16467b97STreehugger Robot 
1124*16467b97STreehugger Robot type
1125*16467b97STreehugger Robot   TTree = class sealed
1126*16467b97STreehugger Robot   strict private
1127*16467b97STreehugger Robot     class var
1128*16467b97STreehugger Robot       FINVALID_NODE: ITree;
1129*16467b97STreehugger Robot   private
1130*16467b97STreehugger Robot     class procedure Initialize; static;
1131*16467b97STreehugger Robot   public
1132*16467b97STreehugger Robot     class property INVALID_NODE: ITree read FINVALID_NODE;
1133*16467b97STreehugger Robot   end;
1134*16467b97STreehugger Robot 
1135*16467b97STreehugger Robot   TBaseTree = class abstract(TANTLRObject, IBaseTree, ITree)
1136*16467b97STreehugger Robot   protected
1137*16467b97STreehugger Robot     { ITree / IBaseTree }
GetParent()1138*16467b97STreehugger Robot     function GetParent: ITree; virtual;
1139*16467b97STreehugger Robot     procedure SetParent(const Value: ITree); virtual;
GetChildIndex()1140*16467b97STreehugger Robot     function GetChildIndex: Integer; virtual;
1141*16467b97STreehugger Robot     procedure SetChildIndex(const Value: Integer); virtual;
GetTokenType()1142*16467b97STreehugger Robot     function GetTokenType: Integer; virtual; abstract;
GetText()1143*16467b97STreehugger Robot     function GetText: String; virtual; abstract;
GetTokenStartIndex()1144*16467b97STreehugger Robot     function GetTokenStartIndex: Integer; virtual; abstract;
1145*16467b97STreehugger Robot     procedure SetTokenStartIndex(const Value: Integer); virtual; abstract;
GetTokenStopIndex()1146*16467b97STreehugger Robot     function GetTokenStopIndex: Integer; virtual; abstract;
1147*16467b97STreehugger Robot     procedure SetTokenStopIndex(const Value: Integer); virtual; abstract;
DupNode()1148*16467b97STreehugger Robot     function DupNode: ITree; virtual; abstract;
ToStringTree()1149*16467b97STreehugger Robot     function ToStringTree: String; virtual;
GetChildCount()1150*16467b97STreehugger Robot     function GetChildCount: Integer; virtual;
GetIsNil()1151*16467b97STreehugger Robot     function GetIsNil: Boolean; virtual;
GetLine()1152*16467b97STreehugger Robot     function GetLine: Integer; virtual;
GetCharPositionInLine()1153*16467b97STreehugger Robot     function GetCharPositionInLine: Integer; virtual;
GetChild(const I: Integer)1154*16467b97STreehugger Robot     function GetChild(const I: Integer): ITree; virtual;
1155*16467b97STreehugger Robot     procedure AddChild(const T: ITree);
DeleteChild(const I: Integer)1156*16467b97STreehugger Robot     function DeleteChild(const I: Integer): IANTLRInterface;
1157*16467b97STreehugger Robot     procedure FreshenParentAndChildIndexes; overload;
1158*16467b97STreehugger Robot     procedure ReplaceChildren(const StartChildIndex, StopChildIndex: Integer;
1159*16467b97STreehugger Robot       const T: IANTLRInterface);
1160*16467b97STreehugger Robot   protected
1161*16467b97STreehugger Robot     { IBaseTree }
GetChildren()1162*16467b97STreehugger Robot     function GetChildren: IList<IBaseTree>;
1163*16467b97STreehugger Robot     procedure AddChildren(const Kids: IList<IBaseTree>);
1164*16467b97STreehugger Robot     procedure SetChild(const I: Integer; const T: ITree); virtual;
1165*16467b97STreehugger Robot     procedure FreshenParentAndChildIndexes(const Offset: Integer); overload;
1166*16467b97STreehugger Robot     procedure SanityCheckParentAndChildIndexes; overload; virtual;
1167*16467b97STreehugger Robot     procedure SanityCheckParentAndChildIndexes(const Parent: ITree;
1168*16467b97STreehugger Robot       const I: Integer); overload; virtual;
1169*16467b97STreehugger Robot   strict protected
1170*16467b97STreehugger Robot     FChildren: IList<IBaseTree>;
1171*16467b97STreehugger Robot 
1172*16467b97STreehugger Robot     /// <summary>Override in a subclass to change the impl of children list </summary>
CreateChildrenList()1173*16467b97STreehugger Robot     function CreateChildrenList: IList<IBaseTree>; virtual;
1174*16467b97STreehugger Robot 
1175*16467b97STreehugger Robot   public
1176*16467b97STreehugger Robot     constructor Create; overload;
1177*16467b97STreehugger Robot 
1178*16467b97STreehugger Robot     /// <summary>Create a new node from an existing node does nothing for BaseTree
1179*16467b97STreehugger Robot     /// as there are no fields other than the children list, which cannot
1180*16467b97STreehugger Robot     /// be copied as the children are not considered part of this node.
1181*16467b97STreehugger Robot     /// </summary>
1182*16467b97STreehugger Robot     constructor Create(const ANode: ITree); overload;
1183*16467b97STreehugger Robot 
ToString()1184*16467b97STreehugger Robot     function ToString: String; override; abstract;
1185*16467b97STreehugger Robot   end;
1186*16467b97STreehugger Robot 
1187*16467b97STreehugger Robot   TCommonTree = class(TBaseTree, ICommonTree)
1188*16467b97STreehugger Robot   strict protected
1189*16467b97STreehugger Robot     /// <summary>A single token is the payload </summary>
1190*16467b97STreehugger Robot     FToken: IToken;
1191*16467b97STreehugger Robot 
1192*16467b97STreehugger Robot     /// <summary>
1193*16467b97STreehugger Robot     /// What token indexes bracket all tokens associated with this node
1194*16467b97STreehugger Robot     /// and below?
1195*16467b97STreehugger Robot     /// </summary>
1196*16467b97STreehugger Robot     FStartIndex: Integer;
1197*16467b97STreehugger Robot     FStopIndex: Integer;
1198*16467b97STreehugger Robot 
1199*16467b97STreehugger Robot     /// <summary>Who is the parent node of this node; if null, implies node is root</summary>
1200*16467b97STreehugger Robot     /// <remarks>
1201*16467b97STreehugger Robot     /// FParent should be of type ICommonTree, but that would introduce a
1202*16467b97STreehugger Robot     /// circular reference because the tree also maintains links to it's
1203*16467b97STreehugger Robot     /// children. This circular reference would cause a memory leak because
1204*16467b97STreehugger Robot     /// the reference count will never reach 0. This is avoided by making
1205*16467b97STreehugger Robot     /// FParent a regular pointer and letting the GetParent and SetParent
1206*16467b97STreehugger Robot     /// property accessors do the conversion to/from ICommonTree.
1207*16467b97STreehugger Robot     /// </remarks>
1208*16467b97STreehugger Robot     FParent: Pointer; { ICommonTree ; }
1209*16467b97STreehugger Robot 
1210*16467b97STreehugger Robot     /// <summary>What index is this node in the child list? Range: 0..n-1</summary>
1211*16467b97STreehugger Robot     FChildIndex: Integer;
1212*16467b97STreehugger Robot   protected
1213*16467b97STreehugger Robot     { ITree / IBaseTree }
GetIsNil()1214*16467b97STreehugger Robot     function GetIsNil: Boolean; override;
GetTokenType()1215*16467b97STreehugger Robot     function GetTokenType: Integer; override;
GetText()1216*16467b97STreehugger Robot     function GetText: String; override;
GetLine()1217*16467b97STreehugger Robot     function GetLine: Integer; override;
GetCharPositionInLine()1218*16467b97STreehugger Robot     function GetCharPositionInLine: Integer; override;
GetTokenStartIndex()1219*16467b97STreehugger Robot     function GetTokenStartIndex: Integer; override;
1220*16467b97STreehugger Robot     procedure SetTokenStartIndex(const Value: Integer); override;
GetTokenStopIndex()1221*16467b97STreehugger Robot     function GetTokenStopIndex: Integer; override;
1222*16467b97STreehugger Robot     procedure SetTokenStopIndex(const Value: Integer); override;
GetChildIndex()1223*16467b97STreehugger Robot     function GetChildIndex: Integer; override;
1224*16467b97STreehugger Robot     procedure SetChildIndex(const Value: Integer); override;
GetParent()1225*16467b97STreehugger Robot     function GetParent: ITree; override;
1226*16467b97STreehugger Robot     procedure SetParent(const Value: ITree); override;
DupNode()1227*16467b97STreehugger Robot     function DupNode: ITree; override;
1228*16467b97STreehugger Robot   protected
1229*16467b97STreehugger Robot     { ICommonTree }
GetToken()1230*16467b97STreehugger Robot     function GetToken: IToken;
GetStartIndex()1231*16467b97STreehugger Robot     function GetStartIndex: Integer;
1232*16467b97STreehugger Robot     procedure SetStartIndex(const Value: Integer);
GetStopIndex()1233*16467b97STreehugger Robot     function GetStopIndex: Integer;
1234*16467b97STreehugger Robot     procedure SetStopIndex(const Value: Integer);
1235*16467b97STreehugger Robot   public
1236*16467b97STreehugger Robot     constructor Create; overload;
1237*16467b97STreehugger Robot     constructor Create(const ANode: ICommonTree); overload;
1238*16467b97STreehugger Robot     constructor Create(const AToken: IToken); overload;
1239*16467b97STreehugger Robot 
ToString()1240*16467b97STreehugger Robot     function ToString: String; override;
1241*16467b97STreehugger Robot   end;
1242*16467b97STreehugger Robot 
1243*16467b97STreehugger Robot   TCommonErrorNode = class(TCommonTree, ICommonErrorNode)
1244*16467b97STreehugger Robot   strict private
1245*16467b97STreehugger Robot     FInput: IIntStream;
1246*16467b97STreehugger Robot     FStart: IToken;
1247*16467b97STreehugger Robot     FStop: IToken;
1248*16467b97STreehugger Robot     FTrappedException: ERecognitionException;
1249*16467b97STreehugger Robot   protected
1250*16467b97STreehugger Robot     { ITree / IBaseTree }
GetIsNil()1251*16467b97STreehugger Robot     function GetIsNil: Boolean; override;
GetTokenType()1252*16467b97STreehugger Robot     function GetTokenType: Integer; override;
GetText()1253*16467b97STreehugger Robot     function GetText: String; override;
1254*16467b97STreehugger Robot   public
1255*16467b97STreehugger Robot     constructor Create(const AInput: ITokenStream; const AStart, AStop: IToken;
1256*16467b97STreehugger Robot       const AException: ERecognitionException);
1257*16467b97STreehugger Robot 
ToString()1258*16467b97STreehugger Robot     function ToString: String; override;
1259*16467b97STreehugger Robot   end;
1260*16467b97STreehugger Robot 
1261*16467b97STreehugger Robot   TBaseTreeAdaptor = class abstract(TANTLRObject, IBaseTreeAdaptor, ITreeAdaptor)
1262*16467b97STreehugger Robot   strict private
1263*16467b97STreehugger Robot     /// <summary>A map of tree node to unique IDs.</summary>
1264*16467b97STreehugger Robot     FTreeToUniqueIDMap: IDictionary<IANTLRInterface, Integer>;
1265*16467b97STreehugger Robot 
1266*16467b97STreehugger Robot     /// <summary>Next available unique ID.</summary>
1267*16467b97STreehugger Robot     FUniqueNodeID: Integer;
1268*16467b97STreehugger Robot   protected
1269*16467b97STreehugger Robot     { ITreeAdaptor }
CreateNode(const Payload: IToken)1270*16467b97STreehugger Robot     function CreateNode(const Payload: IToken): IANTLRInterface; overload; virtual; abstract;
DupNode(const TreeNode: IANTLRInterface)1271*16467b97STreehugger Robot     function DupNode(const TreeNode: IANTLRInterface): IANTLRInterface; virtual; abstract;
DupTree(const Tree: IANTLRInterface)1272*16467b97STreehugger Robot     function DupTree(const Tree: IANTLRInterface): IANTLRInterface; overload; virtual;
GetNilNode()1273*16467b97STreehugger Robot     function GetNilNode: IANTLRInterface; virtual;
ErrorNode(const Input: ITokenStream; const Start, Stop: IToken;1274*16467b97STreehugger Robot     function ErrorNode(const Input: ITokenStream; const Start, Stop: IToken;
1275*16467b97STreehugger Robot       const E: ERecognitionException): IANTLRInterface; virtual;
IsNil(const Tree: IANTLRInterface)1276*16467b97STreehugger Robot     function IsNil(const Tree: IANTLRInterface): Boolean; virtual;
1277*16467b97STreehugger Robot     procedure AddChild(const T, Child: IANTLRInterface); virtual;
BecomeRoot(const NewRoot, OldRoot: IANTLRInterface)1278*16467b97STreehugger Robot     function BecomeRoot(const NewRoot, OldRoot: IANTLRInterface): IANTLRInterface; overload; virtual;
RulePostProcessing(const Root: IANTLRInterface)1279*16467b97STreehugger Robot     function RulePostProcessing(const Root: IANTLRInterface): IANTLRInterface; virtual;
GetUniqueID(const Node: IANTLRInterface)1280*16467b97STreehugger Robot     function GetUniqueID(const Node: IANTLRInterface): Integer;
BecomeRoot(const NewRoot: IToken; const OldRoot: IANTLRInterface)1281*16467b97STreehugger Robot     function BecomeRoot(const NewRoot: IToken; const OldRoot: IANTLRInterface): IANTLRInterface; overload; virtual;
CreateNode(const TokenType: Integer; const FromToken: IToken)1282*16467b97STreehugger Robot     function CreateNode(const TokenType: Integer; const FromToken: IToken): IANTLRInterface; overload; virtual;
CreateNode(const TokenType: Integer; const FromToken: IToken;1283*16467b97STreehugger Robot     function CreateNode(const TokenType: Integer; const FromToken: IToken;
1284*16467b97STreehugger Robot       const Text: String): IANTLRInterface; overload; virtual;
CreateNode(const TokenType: Integer; const Text: String)1285*16467b97STreehugger Robot     function CreateNode(const TokenType: Integer; const Text: String): IANTLRInterface; overload; virtual;
GetNodeType(const T: IANTLRInterface)1286*16467b97STreehugger Robot     function GetNodeType(const T: IANTLRInterface): Integer; virtual;
1287*16467b97STreehugger Robot     procedure SetNodeType(const T: IANTLRInterface; const NodeType: Integer); virtual;
GetNodeText(const T: IANTLRInterface)1288*16467b97STreehugger Robot     function GetNodeText(const T: IANTLRInterface): String; virtual;
1289*16467b97STreehugger Robot     procedure SetNodeText(const T: IANTLRInterface; const Text: String); virtual;
GetToken(const TreeNode: IANTLRInterface)1290*16467b97STreehugger Robot     function GetToken(const TreeNode: IANTLRInterface): IToken; virtual; abstract;
1291*16467b97STreehugger Robot     procedure SetTokenBoundaries(const T: IANTLRInterface; const StartToken,
1292*16467b97STreehugger Robot       StopToken: IToken); virtual; abstract;
GetTokenStartIndex(const T: IANTLRInterface)1293*16467b97STreehugger Robot     function GetTokenStartIndex(const T: IANTLRInterface): Integer; virtual; abstract;
GetTokenStopIndex(const T: IANTLRInterface)1294*16467b97STreehugger Robot     function GetTokenStopIndex(const T: IANTLRInterface): Integer; virtual; abstract;
GetChild(const T: IANTLRInterface; const I: Integer)1295*16467b97STreehugger Robot     function GetChild(const T: IANTLRInterface; const I: Integer): IANTLRInterface; virtual;
1296*16467b97STreehugger Robot     procedure SetChild(const T: IANTLRInterface; const I: Integer; const Child: IANTLRInterface); virtual;
DeleteChild(const T: IANTLRInterface; const I: Integer)1297*16467b97STreehugger Robot     function DeleteChild(const T: IANTLRInterface; const I: Integer): IANTLRInterface; virtual;
GetChildCount(const T: IANTLRInterface)1298*16467b97STreehugger Robot     function GetChildCount(const T: IANTLRInterface): Integer; virtual;
GetParent(const T: IANTLRInterface)1299*16467b97STreehugger Robot     function GetParent(const T: IANTLRInterface): IANTLRInterface; virtual; abstract;
1300*16467b97STreehugger Robot     procedure SetParent(const T, Parent: IANTLRInterface); virtual; abstract;
GetChildIndex(const T: IANTLRInterface)1301*16467b97STreehugger Robot     function GetChildIndex(const T: IANTLRInterface): Integer; virtual; abstract;
1302*16467b97STreehugger Robot     procedure SetChildIdex(const T: IANTLRInterface; const Index: Integer); virtual; abstract;
1303*16467b97STreehugger Robot     procedure ReplaceChildren(const Parent: IANTLRInterface; const StartChildIndex,
1304*16467b97STreehugger Robot       StopChildIndex: Integer; const T: IANTLRInterface); virtual; abstract;
1305*16467b97STreehugger Robot   protected
1306*16467b97STreehugger Robot     { IBaseTreeAdaptor }
DupTree(const T, Parent: IANTLRInterface)1307*16467b97STreehugger Robot     function DupTree(const T, Parent: IANTLRInterface): IANTLRInterface; overload; virtual;
CreateToken(const TokenType: Integer; const Text: String)1308*16467b97STreehugger Robot     function CreateToken(const TokenType: Integer; const Text: String): IToken; overload; virtual; abstract;
CreateToken(const FromToken: IToken)1309*16467b97STreehugger Robot     function CreateToken(const FromToken: IToken): IToken; overload; virtual; abstract;
1310*16467b97STreehugger Robot   public
1311*16467b97STreehugger Robot     constructor Create;
1312*16467b97STreehugger Robot   end;
1313*16467b97STreehugger Robot 
1314*16467b97STreehugger Robot   TCommonTreeAdaptor = class(TBaseTreeAdaptor, ICommonTreeAdaptor)
1315*16467b97STreehugger Robot   protected
1316*16467b97STreehugger Robot     { ITreeAdaptor }
DupNode(const TreeNode: IANTLRInterface)1317*16467b97STreehugger Robot     function DupNode(const TreeNode: IANTLRInterface): IANTLRInterface; override;
CreateNode(const Payload: IToken)1318*16467b97STreehugger Robot     function CreateNode(const Payload: IToken): IANTLRInterface; overload; override;
1319*16467b97STreehugger Robot     procedure SetTokenBoundaries(const T: IANTLRInterface; const StartToken,
1320*16467b97STreehugger Robot       StopToken: IToken); override;
GetTokenStartIndex(const T: IANTLRInterface)1321*16467b97STreehugger Robot     function GetTokenStartIndex(const T: IANTLRInterface): Integer; override;
GetTokenStopIndex(const T: IANTLRInterface)1322*16467b97STreehugger Robot     function GetTokenStopIndex(const T: IANTLRInterface): Integer; override;
GetNodeText(const T: IANTLRInterface)1323*16467b97STreehugger Robot     function GetNodeText(const T: IANTLRInterface): String; override;
GetToken(const TreeNode: IANTLRInterface)1324*16467b97STreehugger Robot     function GetToken(const TreeNode: IANTLRInterface): IToken; override;
GetNodeType(const T: IANTLRInterface)1325*16467b97STreehugger Robot     function GetNodeType(const T: IANTLRInterface): Integer; override;
GetChild(const T: IANTLRInterface; const I: Integer)1326*16467b97STreehugger Robot     function GetChild(const T: IANTLRInterface; const I: Integer): IANTLRInterface; override;
GetChildCount(const T: IANTLRInterface)1327*16467b97STreehugger Robot     function GetChildCount(const T: IANTLRInterface): Integer; override;
GetParent(const T: IANTLRInterface)1328*16467b97STreehugger Robot     function GetParent(const T: IANTLRInterface): IANTLRInterface; override;
1329*16467b97STreehugger Robot     procedure SetParent(const T, Parent: IANTLRInterface); override;
GetChildIndex(const T: IANTLRInterface)1330*16467b97STreehugger Robot     function GetChildIndex(const T: IANTLRInterface): Integer; override;
1331*16467b97STreehugger Robot     procedure SetChildIdex(const T: IANTLRInterface; const Index: Integer); override;
1332*16467b97STreehugger Robot     procedure ReplaceChildren(const Parent: IANTLRInterface; const StartChildIndex,
1333*16467b97STreehugger Robot       StopChildIndex: Integer; const T: IANTLRInterface); override;
1334*16467b97STreehugger Robot   protected
1335*16467b97STreehugger Robot     { IBaseTreeAdaptor }
CreateToken(const TokenType: Integer; const Text: String)1336*16467b97STreehugger Robot     function CreateToken(const TokenType: Integer; const Text: String): IToken; overload; override;
CreateToken(const FromToken: IToken)1337*16467b97STreehugger Robot     function CreateToken(const FromToken: IToken): IToken; overload; override;
1338*16467b97STreehugger Robot   end;
1339*16467b97STreehugger Robot 
1340*16467b97STreehugger Robot   TCommonTreeNodeStream = class(TANTLRObject, ICommonTreeNodeStream, ITreeNodeStream)
1341*16467b97STreehugger Robot   public
1342*16467b97STreehugger Robot     const
1343*16467b97STreehugger Robot       DEFAULT_INITIAL_BUFFER_SIZE = 100;
1344*16467b97STreehugger Robot       INITIAL_CALL_STACK_SIZE = 10;
1345*16467b97STreehugger Robot   strict private
1346*16467b97STreehugger Robot     // all these navigation nodes are shared and hence they
1347*16467b97STreehugger Robot     // cannot contain any line/column info
1348*16467b97STreehugger Robot     FDown: IANTLRInterface;
1349*16467b97STreehugger Robot     FUp: IANTLRInterface;
1350*16467b97STreehugger Robot     FEof: IANTLRInterface;
1351*16467b97STreehugger Robot 
1352*16467b97STreehugger Robot     /// <summary>
1353*16467b97STreehugger Robot     /// The complete mapping from stream index to tree node. This buffer
1354*16467b97STreehugger Robot     /// includes pointers to DOWN, UP, and EOF nodes.
1355*16467b97STreehugger Robot     ///
1356*16467b97STreehugger Robot     /// It is built upon ctor invocation.  The elements are type Object
1357*16467b97STreehugger Robot     /// as we don't what the trees look like. Load upon first need of
1358*16467b97STreehugger Robot     /// the buffer so we can set token types of interest for reverseIndexing.
1359*16467b97STreehugger Robot     /// Slows us down a wee bit  to do all of the if p==-1 testing everywhere though.
1360*16467b97STreehugger Robot     /// </summary>
1361*16467b97STreehugger Robot     FNodes: IList<IANTLRInterface>;
1362*16467b97STreehugger Robot 
1363*16467b97STreehugger Robot     /// <summary>Pull nodes from which tree? </summary>
1364*16467b97STreehugger Robot     FRoot: IANTLRInterface;
1365*16467b97STreehugger Robot 
1366*16467b97STreehugger Robot     /// <summary>IF this tree (root) was created from a token stream, track it</summary>
1367*16467b97STreehugger Robot     FTokens: ITokenStream;
1368*16467b97STreehugger Robot 
1369*16467b97STreehugger Robot     /// <summary>What tree adaptor was used to build these trees</summary>
1370*16467b97STreehugger Robot     FAdaptor: ITreeAdaptor;
1371*16467b97STreehugger Robot 
1372*16467b97STreehugger Robot     /// <summary>
1373*16467b97STreehugger Robot     /// Reuse same DOWN, UP navigation nodes unless this is true
1374*16467b97STreehugger Robot     /// </summary>
1375*16467b97STreehugger Robot     FUniqueNavigationNodes: Boolean;
1376*16467b97STreehugger Robot 
1377*16467b97STreehugger Robot     /// <summary>
1378*16467b97STreehugger Robot     /// The index into the nodes list of the current node (next node
1379*16467b97STreehugger Robot     /// to consume).  If -1, nodes array not filled yet.
1380*16467b97STreehugger Robot     /// </summary>
1381*16467b97STreehugger Robot     FP: Integer;
1382*16467b97STreehugger Robot 
1383*16467b97STreehugger Robot     /// <summary>
1384*16467b97STreehugger Robot     /// Track the last mark() call result value for use in rewind().
1385*16467b97STreehugger Robot     /// </summary>
1386*16467b97STreehugger Robot     FLastMarker: Integer;
1387*16467b97STreehugger Robot 
1388*16467b97STreehugger Robot     /// <summary>
1389*16467b97STreehugger Robot     /// Stack of indexes used for push/pop calls
1390*16467b97STreehugger Robot     /// </summary>
1391*16467b97STreehugger Robot     FCalls: IStackList<Integer>;
1392*16467b97STreehugger Robot   protected
1393*16467b97STreehugger Robot     { IIntStream }
GetSourceName()1394*16467b97STreehugger Robot     function GetSourceName: String; virtual;
1395*16467b97STreehugger Robot 
1396*16467b97STreehugger Robot     procedure Consume; virtual;
LA(I: Integer)1397*16467b97STreehugger Robot     function LA(I: Integer): Integer; virtual;
LAChar(I: Integer)1398*16467b97STreehugger Robot     function LAChar(I: Integer): Char;
Mark()1399*16467b97STreehugger Robot     function Mark: Integer; virtual;
Index()1400*16467b97STreehugger Robot     function Index: Integer; virtual;
1401*16467b97STreehugger Robot     procedure Rewind(const Marker: Integer); overload; virtual;
1402*16467b97STreehugger Robot     procedure Rewind; overload;
1403*16467b97STreehugger Robot     procedure Release(const Marker: Integer); virtual;
1404*16467b97STreehugger Robot     procedure Seek(const Index: Integer); virtual;
Size()1405*16467b97STreehugger Robot     function Size: Integer; virtual;
1406*16467b97STreehugger Robot   protected
1407*16467b97STreehugger Robot     { ITreeNodeStream }
GetTreeSource()1408*16467b97STreehugger Robot     function GetTreeSource: IANTLRInterface; virtual;
GetTokenStream()1409*16467b97STreehugger Robot     function GetTokenStream: ITokenStream; virtual;
GetTreeAdaptor()1410*16467b97STreehugger Robot     function GetTreeAdaptor: ITreeAdaptor;
1411*16467b97STreehugger Robot     procedure SetHasUniqueNavigationNodes(const Value: Boolean);
1412*16467b97STreehugger Robot 
Get(const I: Integer)1413*16467b97STreehugger Robot     function Get(const I: Integer): IANTLRInterface;
LT(const K: Integer)1414*16467b97STreehugger Robot     function LT(const K: Integer): IANTLRInterface;
ToString(const Start, Stop: IANTLRInterface)1415*16467b97STreehugger Robot     function ToString(const Start, Stop: IANTLRInterface): String; reintroduce; overload;
1416*16467b97STreehugger Robot     procedure ReplaceChildren(const Parent: IANTLRInterface; const StartChildIndex,
1417*16467b97STreehugger Robot       StopChildIndex: Integer; const T: IANTLRInterface);
1418*16467b97STreehugger Robot   protected
1419*16467b97STreehugger Robot     { ICommonTreeNodeStream }
GetCurrentSymbol()1420*16467b97STreehugger Robot     function GetCurrentSymbol: IANTLRInterface; virtual;
1421*16467b97STreehugger Robot     procedure SetTokenStream(const Value: ITokenStream); virtual;
1422*16467b97STreehugger Robot     procedure SetTreeAdaptor(const Value: ITreeAdaptor);
GetHasUniqueNavigationNodes()1423*16467b97STreehugger Robot     function GetHasUniqueNavigationNodes: Boolean;
1424*16467b97STreehugger Robot 
1425*16467b97STreehugger Robot     procedure FillBuffer(const T: IANTLRInterface); overload;
LB(const K: Integer)1426*16467b97STreehugger Robot     function LB(const K: Integer): IANTLRInterface;
1427*16467b97STreehugger Robot     procedure Push(const Index: Integer);
Pop()1428*16467b97STreehugger Robot     function Pop: Integer;
1429*16467b97STreehugger Robot     procedure Reset;
ToTokenString(const Start, Stop: Integer)1430*16467b97STreehugger Robot     function ToTokenString(const Start, Stop: Integer): String;
1431*16467b97STreehugger Robot   strict protected
1432*16467b97STreehugger Robot     /// <summary>
1433*16467b97STreehugger Robot     /// Walk tree with depth-first-search and fill nodes buffer.
1434*16467b97STreehugger Robot     /// Don't do DOWN, UP nodes if its a list (t is isNil).
1435*16467b97STreehugger Robot     /// </summary>
1436*16467b97STreehugger Robot     procedure FillBuffer; overload;
1437*16467b97STreehugger Robot 
1438*16467b97STreehugger Robot     /// <summary>
1439*16467b97STreehugger Robot     /// As we flatten the tree, we use UP, DOWN nodes to represent
1440*16467b97STreehugger Robot     /// the tree structure.  When debugging we need unique nodes
1441*16467b97STreehugger Robot     /// so instantiate new ones when uniqueNavigationNodes is true.
1442*16467b97STreehugger Robot     /// </summary>
1443*16467b97STreehugger Robot     procedure AddNavigationNode(const TokenType: Integer);
1444*16467b97STreehugger Robot 
1445*16467b97STreehugger Robot     /// <summary>
1446*16467b97STreehugger Robot     /// Returns the stream index for the spcified node in the range 0..n-1 or,
1447*16467b97STreehugger Robot     /// -1 if node not found.
1448*16467b97STreehugger Robot     /// </summary>
GetNodeIndex(const Node: IANTLRInterface)1449*16467b97STreehugger Robot     function GetNodeIndex(const Node: IANTLRInterface): Integer;
1450*16467b97STreehugger Robot   public
1451*16467b97STreehugger Robot     constructor Create; overload;
1452*16467b97STreehugger Robot     constructor Create(const ATree: IANTLRInterface); overload;
1453*16467b97STreehugger Robot     constructor Create(const AAdaptor: ITreeAdaptor;
1454*16467b97STreehugger Robot       const ATree: IANTLRInterface); overload;
1455*16467b97STreehugger Robot     constructor Create(const AAdaptor: ITreeAdaptor;
1456*16467b97STreehugger Robot       const ATree: IANTLRInterface; const AInitialBufferSize: Integer); overload;
1457*16467b97STreehugger Robot 
ToString()1458*16467b97STreehugger Robot     function ToString: String; overload; override;
1459*16467b97STreehugger Robot   end;
1460*16467b97STreehugger Robot 
1461*16467b97STreehugger Robot   TParseTree = class(TBaseTree, IParseTree)
1462*16467b97STreehugger Robot   strict private
1463*16467b97STreehugger Robot     FPayload: IANTLRInterface;
1464*16467b97STreehugger Robot     FHiddenTokens: IList<IToken>;
1465*16467b97STreehugger Robot   protected
1466*16467b97STreehugger Robot     { ITree / IBaseTree }
GetTokenType()1467*16467b97STreehugger Robot     function GetTokenType: Integer; override;
GetText()1468*16467b97STreehugger Robot     function GetText: String; override;
GetTokenStartIndex()1469*16467b97STreehugger Robot     function GetTokenStartIndex: Integer; override;
1470*16467b97STreehugger Robot     procedure SetTokenStartIndex(const Value: Integer); override;
GetTokenStopIndex()1471*16467b97STreehugger Robot     function GetTokenStopIndex: Integer; override;
1472*16467b97STreehugger Robot     procedure SetTokenStopIndex(const Value: Integer); override;
DupNode()1473*16467b97STreehugger Robot     function DupNode: ITree; override;
1474*16467b97STreehugger Robot   protected
1475*16467b97STreehugger Robot     { IParseTree }
ToStringWithHiddenTokens()1476*16467b97STreehugger Robot     function ToStringWithHiddenTokens: String;
ToInputString()1477*16467b97STreehugger Robot     function ToInputString: String;
1478*16467b97STreehugger Robot     procedure _ToStringLeaves(const Buf: TStringBuilder);
1479*16467b97STreehugger Robot   public
1480*16467b97STreehugger Robot     constructor Create(const ALabel: IANTLRInterface);
1481*16467b97STreehugger Robot 
ToString()1482*16467b97STreehugger Robot     function ToString: String; override;
1483*16467b97STreehugger Robot   end;
1484*16467b97STreehugger Robot 
1485*16467b97STreehugger Robot   TRewriteRuleElementStream = class abstract(TANTLRObject, IRewriteRuleElementStream)
1486*16467b97STreehugger Robot   private
1487*16467b97STreehugger Robot     /// <summary>
1488*16467b97STreehugger Robot     /// Cursor 0..n-1.  If singleElement!=null, cursor is 0 until you next(),
1489*16467b97STreehugger Robot     /// which bumps it to 1 meaning no more elements.
1490*16467b97STreehugger Robot     /// </summary>
1491*16467b97STreehugger Robot     FCursor: Integer;
1492*16467b97STreehugger Robot 
1493*16467b97STreehugger Robot     /// <summary>
1494*16467b97STreehugger Robot     /// Track single elements w/o creating a list.  Upon 2nd add, alloc list
1495*16467b97STreehugger Robot     /// </summary>
1496*16467b97STreehugger Robot     FSingleElement: IANTLRInterface;
1497*16467b97STreehugger Robot 
1498*16467b97STreehugger Robot     /// <summary>
1499*16467b97STreehugger Robot     /// The list of tokens or subtrees we are tracking
1500*16467b97STreehugger Robot     /// </summary>
1501*16467b97STreehugger Robot     FElements: IList<IANTLRInterface>;
1502*16467b97STreehugger Robot 
1503*16467b97STreehugger Robot     /// <summary>
1504*16467b97STreehugger Robot     /// Tracks whether a node or subtree has been used in a stream
1505*16467b97STreehugger Robot     /// </summary>
1506*16467b97STreehugger Robot     /// <remarks>
1507*16467b97STreehugger Robot     /// Once a node or subtree has been used in a stream, it must be dup'd
1508*16467b97STreehugger Robot     /// from then on.  Streams are reset after subrules so that the streams
1509*16467b97STreehugger Robot     /// can be reused in future subrules.  So, reset must set a dirty bit.
1510*16467b97STreehugger Robot     /// If dirty, then next() always returns a dup.
1511*16467b97STreehugger Robot     /// </remarks>
1512*16467b97STreehugger Robot     FDirty: Boolean;
1513*16467b97STreehugger Robot 
1514*16467b97STreehugger Robot     /// <summary>
1515*16467b97STreehugger Robot     /// The element or stream description; usually has name of the token or
1516*16467b97STreehugger Robot     /// rule reference that this list tracks.  Can include rulename too, but
1517*16467b97STreehugger Robot     /// the exception would track that info.
1518*16467b97STreehugger Robot     /// </summary>
1519*16467b97STreehugger Robot     FElementDescription: String;
1520*16467b97STreehugger Robot     FAdaptor: ITreeAdaptor;
1521*16467b97STreehugger Robot   protected
1522*16467b97STreehugger Robot     { IRewriteRuleElementStream }
GetDescription()1523*16467b97STreehugger Robot     function GetDescription: String;
1524*16467b97STreehugger Robot 
1525*16467b97STreehugger Robot     procedure Add(const El: IANTLRInterface);
1526*16467b97STreehugger Robot     procedure Reset; virtual;
HasNext()1527*16467b97STreehugger Robot     function HasNext: Boolean;
NextTree()1528*16467b97STreehugger Robot     function NextTree: IANTLRInterface; virtual;
NextNode()1529*16467b97STreehugger Robot     function NextNode: IANTLRInterface; virtual; abstract;
Size()1530*16467b97STreehugger Robot     function Size: Integer;
1531*16467b97STreehugger Robot   strict protected
1532*16467b97STreehugger Robot     /// <summary>
1533*16467b97STreehugger Robot     /// Do the work of getting the next element, making sure that
1534*16467b97STreehugger Robot     /// it's a tree node or subtree.
1535*16467b97STreehugger Robot     /// </summary>
1536*16467b97STreehugger Robot     /// <remarks>
1537*16467b97STreehugger Robot     /// Deal with the optimization of single-element list versus
1538*16467b97STreehugger Robot     /// list of size > 1.  Throw an exception if the stream is
1539*16467b97STreehugger Robot     /// empty or we're out of elements and size>1.
1540*16467b97STreehugger Robot     /// </remarks>
_Next()1541*16467b97STreehugger Robot     function _Next: IANTLRInterface;
1542*16467b97STreehugger Robot 
1543*16467b97STreehugger Robot     /// <summary>
1544*16467b97STreehugger Robot     /// Ensure stream emits trees; tokens must be converted to AST nodes.
1545*16467b97STreehugger Robot     /// AST nodes can be passed through unmolested.
1546*16467b97STreehugger Robot     /// </summary>
ToTree(const El: IANTLRInterface)1547*16467b97STreehugger Robot     function ToTree(const El: IANTLRInterface): IANTLRInterface; virtual;
1548*16467b97STreehugger Robot   public
1549*16467b97STreehugger Robot     constructor Create(const AAdaptor: ITreeAdaptor;
1550*16467b97STreehugger Robot       const AElementDescription: String); overload;
1551*16467b97STreehugger Robot 
1552*16467b97STreehugger Robot     /// <summary>
1553*16467b97STreehugger Robot     /// Create a stream with one element
1554*16467b97STreehugger Robot     /// </summary>
1555*16467b97STreehugger Robot     constructor Create(const AAdaptor: ITreeAdaptor;
1556*16467b97STreehugger Robot       const AElementDescription: String; const AOneElement: IANTLRInterface); overload;
1557*16467b97STreehugger Robot 
1558*16467b97STreehugger Robot     /// <summary>
1559*16467b97STreehugger Robot     /// Create a stream, but feed off an existing list
1560*16467b97STreehugger Robot     /// </summary>
1561*16467b97STreehugger Robot     constructor Create(const AAdaptor: ITreeAdaptor;
1562*16467b97STreehugger Robot       const AElementDescription: String; const AElements: IList<IANTLRInterface>); overload;
1563*16467b97STreehugger Robot   end;
1564*16467b97STreehugger Robot 
1565*16467b97STreehugger Robot   TRewriteRuleNodeStream = class(TRewriteRuleElementStream, IRewriteRuleNodeStream)
1566*16467b97STreehugger Robot   protected
1567*16467b97STreehugger Robot     { IRewriteRuleElementStream }
NextNode()1568*16467b97STreehugger Robot     function NextNode: IANTLRInterface; override;
ToTree(const El: IANTLRInterface)1569*16467b97STreehugger Robot     function ToTree(const El: IANTLRInterface): IANTLRInterface; override;
1570*16467b97STreehugger Robot   end;
1571*16467b97STreehugger Robot 
1572*16467b97STreehugger Robot   TRewriteRuleSubtreeStream = class(TRewriteRuleElementStream, IRewriteRuleSubtreeStream)
1573*16467b97STreehugger Robot   public
1574*16467b97STreehugger Robot     type
1575*16467b97STreehugger Robot       /// <summary>
1576*16467b97STreehugger Robot       /// This delegate is used to allow the outfactoring of some common code.
1577*16467b97STreehugger Robot       /// </summary>
1578*16467b97STreehugger Robot       /// <param name="o">The to be processed object</param>
onst()1579*16467b97STreehugger Robot       TProcessHandler = function(const O: IANTLRInterface): IANTLRInterface of Object;
1580*16467b97STreehugger Robot   strict private
1581*16467b97STreehugger Robot     /// <summary>
1582*16467b97STreehugger Robot     /// This method has the common code of two other methods, which differed in only one
1583*16467b97STreehugger Robot     /// function call.
1584*16467b97STreehugger Robot     /// </summary>
1585*16467b97STreehugger Robot     /// <param name="ph">The delegate, which has the chosen function</param>
1586*16467b97STreehugger Robot     /// <returns>The required object</returns>
FetchObject(const PH: TProcessHandler)1587*16467b97STreehugger Robot     function FetchObject(const PH: TProcessHandler): IANTLRInterface;
DupNode(const O: IANTLRInterface)1588*16467b97STreehugger Robot     function DupNode(const O: IANTLRInterface): IANTLRInterface;
1589*16467b97STreehugger Robot 
1590*16467b97STreehugger Robot     /// <summary>
1591*16467b97STreehugger Robot     /// Tests, if the to be returned object requires duplication
1592*16467b97STreehugger Robot     /// </summary>
1593*16467b97STreehugger Robot     /// <returns><code>true</code>, if positive, <code>false</code>, if negative.</returns>
RequiresDuplication()1594*16467b97STreehugger Robot     function RequiresDuplication: Boolean;
1595*16467b97STreehugger Robot 
1596*16467b97STreehugger Robot     /// <summary>
1597*16467b97STreehugger Robot     /// When constructing trees, sometimes we need to dup a token or AST
1598*16467b97STreehugger Robot     /// subtree. Dup'ing a token means just creating another AST node
1599*16467b97STreehugger Robot     /// around it. For trees, you must call the adaptor.dupTree()
1600*16467b97STreehugger Robot     /// unless the element is for a tree root; then it must be a node dup
1601*16467b97STreehugger Robot     /// </summary>
Dup(const O: IANTLRInterface)1602*16467b97STreehugger Robot     function Dup(const O: IANTLRInterface): IANTLRInterface;
1603*16467b97STreehugger Robot   protected
1604*16467b97STreehugger Robot     { IRewriteRuleElementStream }
NextNode()1605*16467b97STreehugger Robot     function NextNode: IANTLRInterface; override;
NextTree()1606*16467b97STreehugger Robot     function NextTree: IANTLRInterface; override;
1607*16467b97STreehugger Robot   end;
1608*16467b97STreehugger Robot 
1609*16467b97STreehugger Robot   TRewriteRuleTokenStream = class(TRewriteRuleElementStream, IRewriteRuleTokenStream)
1610*16467b97STreehugger Robot   protected
1611*16467b97STreehugger Robot     { IRewriteRuleElementStream }
NextNode()1612*16467b97STreehugger Robot     function NextNode: IANTLRInterface; override;
NextToken()1613*16467b97STreehugger Robot     function NextToken: IToken;
ToTree(const El: IANTLRInterface)1614*16467b97STreehugger Robot     function ToTree(const El: IANTLRInterface): IANTLRInterface; override;
1615*16467b97STreehugger Robot   end;
1616*16467b97STreehugger Robot 
1617*16467b97STreehugger Robot   TTreeParser = class(TBaseRecognizer, ITreeParser)
1618*16467b97STreehugger Robot   public
1619*16467b97STreehugger Robot     const
1620*16467b97STreehugger Robot       DOWN = TToken.DOWN;
1621*16467b97STreehugger Robot       UP = TToken.UP;
1622*16467b97STreehugger Robot   strict private
1623*16467b97STreehugger Robot     FInput: ITreeNodeStream;
1624*16467b97STreehugger Robot   strict protected
1625*16467b97STreehugger Robot     property Input: ITreeNodeStream read FInput;
1626*16467b97STreehugger Robot   protected
1627*16467b97STreehugger Robot     { IBaseRecognizer }
GetSourceName()1628*16467b97STreehugger Robot     function GetSourceName: String; override;
1629*16467b97STreehugger Robot     procedure Reset; override;
1630*16467b97STreehugger Robot     procedure MatchAny(const Input: IIntStream); override;
GetInput()1631*16467b97STreehugger Robot     function GetInput: IIntStream; override;
GetErrorHeader(const E: ERecognitionException)1632*16467b97STreehugger Robot     function GetErrorHeader(const E: ERecognitionException): String; override;
GetErrorMessage(const E: ERecognitionException;1633*16467b97STreehugger Robot     function GetErrorMessage(const E: ERecognitionException;
1634*16467b97STreehugger Robot       const TokenNames: TStringArray): String; override;
1635*16467b97STreehugger Robot   protected
1636*16467b97STreehugger Robot     { ITreeParser }
GetTreeNodeStream()1637*16467b97STreehugger Robot     function GetTreeNodeStream: ITreeNodeStream; virtual;
1638*16467b97STreehugger Robot     procedure SetTreeNodeStream(const Value: ITreeNodeStream); virtual;
1639*16467b97STreehugger Robot 
1640*16467b97STreehugger Robot     procedure TraceIn(const RuleName: String; const RuleIndex: Integer); reintroduce; overload; virtual;
1641*16467b97STreehugger Robot     procedure TraceOut(const RuleName: String; const RuleIndex: Integer); reintroduce; overload; virtual;
1642*16467b97STreehugger Robot   strict protected
GetCurrentInputSymbol(const Input: IIntStream)1643*16467b97STreehugger Robot     function GetCurrentInputSymbol(const Input: IIntStream): IANTLRInterface; override;
GetMissingSymbol(const Input: IIntStream;1644*16467b97STreehugger Robot     function GetMissingSymbol(const Input: IIntStream;
1645*16467b97STreehugger Robot       const E: ERecognitionException; const ExpectedTokenType: Integer;
1646*16467b97STreehugger Robot       const Follow: IBitSet): IANTLRInterface; override;
1647*16467b97STreehugger Robot     procedure Mismatch(const Input: IIntStream; const TokenType: Integer;
1648*16467b97STreehugger Robot       const Follow: IBitSet); override;
1649*16467b97STreehugger Robot   public
1650*16467b97STreehugger Robot     constructor Create(const AInput: ITreeNodeStream); overload;
1651*16467b97STreehugger Robot     constructor Create(const AInput: ITreeNodeStream;
1652*16467b97STreehugger Robot       const AState: IRecognizerSharedState); overload;
1653*16467b97STreehugger Robot   end;
1654*16467b97STreehugger Robot 
1655*16467b97STreehugger Robot   TTreePatternLexer = class(TANTLRObject, ITreePatternLexer)
1656*16467b97STreehugger Robot   public
1657*16467b97STreehugger Robot     const
1658*16467b97STreehugger Robot       EOF = -1;
1659*16467b97STreehugger Robot       START = 1;
1660*16467b97STreehugger Robot       STOP = 2;
1661*16467b97STreehugger Robot       ID = 3;
1662*16467b97STreehugger Robot       ARG = 4;
1663*16467b97STreehugger Robot       PERCENT = 5;
1664*16467b97STreehugger Robot       COLON = 6;
1665*16467b97STreehugger Robot       DOT = 7;
1666*16467b97STreehugger Robot   strict private
1667*16467b97STreehugger Robot     /// <summary>The tree pattern to lex like "(A B C)"</summary>
1668*16467b97STreehugger Robot     FPattern: String;
1669*16467b97STreehugger Robot 
1670*16467b97STreehugger Robot     /// <summary>Index into input string</summary>
1671*16467b97STreehugger Robot     FP: Integer;
1672*16467b97STreehugger Robot 
1673*16467b97STreehugger Robot     /// <summary>Current char</summary>
1674*16467b97STreehugger Robot     FC: Integer;
1675*16467b97STreehugger Robot 
1676*16467b97STreehugger Robot     /// <summary>How long is the pattern in char?</summary>
1677*16467b97STreehugger Robot     FN: Integer;
1678*16467b97STreehugger Robot 
1679*16467b97STreehugger Robot     /// <summary>
1680*16467b97STreehugger Robot     /// Set when token type is ID or ARG (name mimics Java's StreamTokenizer)
1681*16467b97STreehugger Robot     /// </summary>
1682*16467b97STreehugger Robot     FSVal: TStringBuilder;
1683*16467b97STreehugger Robot 
1684*16467b97STreehugger Robot     FError: Boolean;
1685*16467b97STreehugger Robot   protected
1686*16467b97STreehugger Robot     { ITreePatternLexer }
NextToken()1687*16467b97STreehugger Robot     function NextToken: Integer;
SVal()1688*16467b97STreehugger Robot     function SVal: String;
1689*16467b97STreehugger Robot   strict protected
1690*16467b97STreehugger Robot     procedure Consume;
1691*16467b97STreehugger Robot   public
1692*16467b97STreehugger Robot     constructor Create; overload;
1693*16467b97STreehugger Robot     constructor Create(const APattern: String); overload;
1694*16467b97STreehugger Robot     destructor Destroy; override;
1695*16467b97STreehugger Robot   end;
1696*16467b97STreehugger Robot 
1697*16467b97STreehugger Robot   TTreeWizard = class(TANTLRObject, ITreeWizard)
1698*16467b97STreehugger Robot   strict private
1699*16467b97STreehugger Robot     FAdaptor: ITreeAdaptor;
1700*16467b97STreehugger Robot     FTokenNameToTypeMap: IDictionary<String, Integer>;
1701*16467b97STreehugger Robot   public
1702*16467b97STreehugger Robot     type
1703*16467b97STreehugger Robot       /// <summary>
1704*16467b97STreehugger Robot       /// When using %label:TOKENNAME in a tree for parse(), we must track the label.
1705*16467b97STreehugger Robot       /// </summary>
1706*16467b97STreehugger Robot       ITreePattern = interface(ICommonTree)
1707*16467b97STreehugger Robot       ['{893C6B4E-8474-4A1E-BEAA-8B704868401B}']
1708*16467b97STreehugger Robot         { Property accessors }
GetHasTextArg()1709*16467b97STreehugger Robot         function GetHasTextArg: Boolean;
1710*16467b97STreehugger Robot         procedure SetHasTextArg(const Value: Boolean);
GetTokenLabel()1711*16467b97STreehugger Robot         function GetTokenLabel: String;
1712*16467b97STreehugger Robot         procedure SetTokenLabel(const Value: String);
1713*16467b97STreehugger Robot 
1714*16467b97STreehugger Robot         { Properties }
1715*16467b97STreehugger Robot         property HasTextArg: Boolean read GetHasTextArg write SetHasTextArg;
1716*16467b97STreehugger Robot         property TokenLabel: String read GetTokenLabel write SetTokenLabel;
1717*16467b97STreehugger Robot       end;
1718*16467b97STreehugger Robot 
1719*16467b97STreehugger Robot       IWildcardTreePattern = interface(ITreePattern)
1720*16467b97STreehugger Robot       ['{4778789A-5EAB-47E3-A05B-7F35CD87ECE4}']
1721*16467b97STreehugger Robot       end;
1722*16467b97STreehugger Robot     type
1723*16467b97STreehugger Robot       TVisitor = class abstract(TANTLRObject, IContextVisitor)
1724*16467b97STreehugger Robot       protected
1725*16467b97STreehugger Robot         { IContextVisitor }
1726*16467b97STreehugger Robot         procedure Visit(const T, Parent: IANTLRInterface; const ChildIndex: Integer;
1727*16467b97STreehugger Robot           const Labels: IDictionary<String, IANTLRInterface>); overload;
1728*16467b97STreehugger Robot       strict protected
1729*16467b97STreehugger Robot         procedure Visit(const T: IANTLRInterface); overload; virtual; abstract;
1730*16467b97STreehugger Robot       end;
1731*16467b97STreehugger Robot 
1732*16467b97STreehugger Robot       TTreePattern = class(TCommonTree, ITreePattern)
1733*16467b97STreehugger Robot       strict private
1734*16467b97STreehugger Robot         FLabel: String;
1735*16467b97STreehugger Robot         FHasTextArg: Boolean;
1736*16467b97STreehugger Robot       protected
1737*16467b97STreehugger Robot         { ITreePattern }
GetHasTextArg()1738*16467b97STreehugger Robot         function GetHasTextArg: Boolean;
1739*16467b97STreehugger Robot         procedure SetHasTextArg(const Value: Boolean);
GetTokenLabel()1740*16467b97STreehugger Robot         function GetTokenLabel: String;
1741*16467b97STreehugger Robot         procedure SetTokenLabel(const Value: String);
1742*16467b97STreehugger Robot       public
ToString()1743*16467b97STreehugger Robot         function ToString: String; override;
1744*16467b97STreehugger Robot       end;
1745*16467b97STreehugger Robot 
1746*16467b97STreehugger Robot       TWildcardTreePattern = class(TTreePattern, IWildcardTreePattern)
1747*16467b97STreehugger Robot 
1748*16467b97STreehugger Robot       end;
1749*16467b97STreehugger Robot 
1750*16467b97STreehugger Robot       /// <summary>
1751*16467b97STreehugger Robot       /// This adaptor creates TreePattern objects for use during scan()
1752*16467b97STreehugger Robot       /// </summary>
1753*16467b97STreehugger Robot       TTreePatternTreeAdaptor = class(TCommonTreeAdaptor)
1754*16467b97STreehugger Robot       protected
1755*16467b97STreehugger Robot         { ITreeAdaptor }
CreateNode(const Payload: IToken)1756*16467b97STreehugger Robot         function CreateNode(const Payload: IToken): IANTLRInterface; overload; override;
1757*16467b97STreehugger Robot       end;
1758*16467b97STreehugger Robot   strict private
1759*16467b97STreehugger Robot     type
1760*16467b97STreehugger Robot       TRecordAllElementsVisitor = class sealed(TVisitor)
1761*16467b97STreehugger Robot       strict private
1762*16467b97STreehugger Robot         FList: IList<IANTLRInterface>;
1763*16467b97STreehugger Robot       strict protected
1764*16467b97STreehugger Robot         procedure Visit(const T: IANTLRInterface); override;
1765*16467b97STreehugger Robot       public
1766*16467b97STreehugger Robot         constructor Create(const AList: IList<IANTLRInterface>);
1767*16467b97STreehugger Robot       end;
1768*16467b97STreehugger Robot 
1769*16467b97STreehugger Robot     type
1770*16467b97STreehugger Robot       TPatternMatchingContextVisitor = class sealed(TANTLRObject, IContextVisitor)
1771*16467b97STreehugger Robot       strict private
1772*16467b97STreehugger Robot         FOwner: TTreeWizard;
1773*16467b97STreehugger Robot         FPattern: ITreePattern;
1774*16467b97STreehugger Robot         FList: IList<IANTLRInterface>;
1775*16467b97STreehugger Robot       protected
1776*16467b97STreehugger Robot         { IContextVisitor }
1777*16467b97STreehugger Robot         procedure Visit(const T, Parent: IANTLRInterface; const ChildIndex: Integer;
1778*16467b97STreehugger Robot           const Labels: IDictionary<String, IANTLRInterface>); overload;
1779*16467b97STreehugger Robot       public
1780*16467b97STreehugger Robot         constructor Create(const AOwner: TTreeWizard; const APattern: ITreePattern;
1781*16467b97STreehugger Robot           const AList: IList<IANTLRInterface>);
1782*16467b97STreehugger Robot       end;
1783*16467b97STreehugger Robot 
1784*16467b97STreehugger Robot     type
1785*16467b97STreehugger Robot       TInvokeVisitorOnPatternMatchContextVisitor = class sealed(TANTLRObject, IContextVisitor)
1786*16467b97STreehugger Robot       strict private
1787*16467b97STreehugger Robot         FOwner: TTreeWizard;
1788*16467b97STreehugger Robot         FPattern: ITreePattern;
1789*16467b97STreehugger Robot         FVisitor: IContextVisitor;
1790*16467b97STreehugger Robot         FLabels: IDictionary<String, IANTLRInterface>;
1791*16467b97STreehugger Robot       protected
1792*16467b97STreehugger Robot         { IContextVisitor }
1793*16467b97STreehugger Robot         procedure Visit(const T, Parent: IANTLRInterface; const ChildIndex: Integer;
1794*16467b97STreehugger Robot           const UnusedLabels: IDictionary<String, IANTLRInterface>); overload;
1795*16467b97STreehugger Robot       public
1796*16467b97STreehugger Robot         constructor Create(const AOwner: TTreeWizard; const APattern: ITreePattern;
1797*16467b97STreehugger Robot           const AVisitor: IContextVisitor);
1798*16467b97STreehugger Robot       end;
1799*16467b97STreehugger Robot   protected
1800*16467b97STreehugger Robot     { ITreeWizard }
ComputeTokenTypes(const TokenNames: TStringArray)1801*16467b97STreehugger Robot     function ComputeTokenTypes(const TokenNames: TStringArray): IDictionary<String, Integer>;
GetTokenType(const TokenName: String)1802*16467b97STreehugger Robot     function GetTokenType(const TokenName: String): Integer;
Index(const T: IANTLRInterface)1803*16467b97STreehugger Robot     function Index(const T: IANTLRInterface): IDictionary<Integer, IList<IANTLRInterface>>;
Find(const T: IANTLRInterface; const TokenType: Integer)1804*16467b97STreehugger Robot     function Find(const T: IANTLRInterface; const TokenType: Integer): IList<IANTLRInterface>; overload;
Find(const T: IANTLRInterface; const Pattern: String)1805*16467b97STreehugger Robot     function Find(const T: IANTLRInterface; const Pattern: String): IList<IANTLRInterface>; overload;
FindFirst(const T: IANTLRInterface; const TokenType: Integer)1806*16467b97STreehugger Robot     function FindFirst(const T: IANTLRInterface; const TokenType: Integer): IANTLRInterface; overload;
FindFirst(const T: IANTLRInterface; const Pattern: String)1807*16467b97STreehugger Robot     function FindFirst(const T: IANTLRInterface; const Pattern: String): IANTLRInterface; overload;
1808*16467b97STreehugger Robot     procedure Visit(const T: IANTLRInterface; const TokenType: Integer;
1809*16467b97STreehugger Robot       const Visitor: IContextVisitor); overload;
1810*16467b97STreehugger Robot     procedure Visit(const T: IANTLRInterface; const Pattern: String;
1811*16467b97STreehugger Robot       const Visitor: IContextVisitor); overload;
Parse(const T: IANTLRInterface; const Pattern: String;1812*16467b97STreehugger Robot     function Parse(const T: IANTLRInterface; const Pattern: String;
1813*16467b97STreehugger Robot       const Labels: IDictionary<String, IANTLRInterface>): Boolean; overload;
Parse(const T: IANTLRInterface; const Pattern: String)1814*16467b97STreehugger Robot     function Parse(const T: IANTLRInterface; const Pattern: String): Boolean; overload;
CreateTreeOrNode(const Pattern: String)1815*16467b97STreehugger Robot     function CreateTreeOrNode(const Pattern: String): IANTLRInterface;
Equals(const T1, T2: IANTLRInterface)1816*16467b97STreehugger Robot     function Equals(const T1, T2: IANTLRInterface): Boolean; reintroduce; overload;
Equals(const T1, T2: IANTLRInterface;1817*16467b97STreehugger Robot     function Equals(const T1, T2: IANTLRInterface;
1818*16467b97STreehugger Robot       const Adaptor: ITreeAdaptor): Boolean; reintroduce; overload;
1819*16467b97STreehugger Robot   strict protected
_Parse(const T1: IANTLRInterface; const T2: ITreePattern;1820*16467b97STreehugger Robot     function _Parse(const T1: IANTLRInterface; const T2: ITreePattern;
1821*16467b97STreehugger Robot       const Labels: IDictionary<String, IANTLRInterface>): Boolean;
1822*16467b97STreehugger Robot 
1823*16467b97STreehugger Robot     /// <summary>Do the work for index</summary>
1824*16467b97STreehugger Robot     procedure _Index(const T: IANTLRInterface;
1825*16467b97STreehugger Robot       const M: IDictionary<Integer, IList<IANTLRInterface>>);
1826*16467b97STreehugger Robot 
1827*16467b97STreehugger Robot     /// <summary>Do the recursive work for visit</summary>
1828*16467b97STreehugger Robot     procedure _Visit(const T, Parent: IANTLRInterface; const ChildIndex,
1829*16467b97STreehugger Robot       TokenType: Integer; const Visitor: IContextVisitor);
1830*16467b97STreehugger Robot 
_Equals(const T1, T2: IANTLRInterface;1831*16467b97STreehugger Robot     class function _Equals(const T1, T2: IANTLRInterface;
1832*16467b97STreehugger Robot       const Adaptor: ITreeAdaptor): Boolean; static;
1833*16467b97STreehugger Robot   public
1834*16467b97STreehugger Robot     constructor Create(const AAdaptor: ITreeAdaptor); overload;
1835*16467b97STreehugger Robot     constructor Create(const AAdaptor: ITreeAdaptor;
1836*16467b97STreehugger Robot       const ATokenNameToTypeMap: IDictionary<String, Integer>); overload;
1837*16467b97STreehugger Robot     constructor Create(const AAdaptor: ITreeAdaptor;
1838*16467b97STreehugger Robot       const TokenNames: TStringArray); overload;
1839*16467b97STreehugger Robot     constructor Create(const TokenNames: TStringArray); overload;
1840*16467b97STreehugger Robot   end;
1841*16467b97STreehugger Robot 
1842*16467b97STreehugger Robot   TTreePatternParser = class(TANTLRObject, ITreePatternParser)
1843*16467b97STreehugger Robot   strict private
1844*16467b97STreehugger Robot     FTokenizer: ITreePatternLexer;
1845*16467b97STreehugger Robot     FTokenType: Integer;
1846*16467b97STreehugger Robot     FWizard: ITreeWizard;
1847*16467b97STreehugger Robot     FAdaptor: ITreeAdaptor;
1848*16467b97STreehugger Robot   protected
1849*16467b97STreehugger Robot     { ITreePatternParser }
Pattern()1850*16467b97STreehugger Robot     function Pattern: IANTLRInterface;
ParseTree()1851*16467b97STreehugger Robot     function ParseTree: IANTLRInterface;
ParseNode()1852*16467b97STreehugger Robot     function ParseNode: IANTLRInterface;
1853*16467b97STreehugger Robot   public
1854*16467b97STreehugger Robot     constructor Create(const ATokenizer: ITreePatternLexer;
1855*16467b97STreehugger Robot       const AWizard: ITreeWizard; const AAdaptor: ITreeAdaptor);
1856*16467b97STreehugger Robot   end;
1857*16467b97STreehugger Robot 
1858*16467b97STreehugger Robot   TTreeRuleReturnScope = class(TRuleReturnScope, ITreeRuleReturnScope)
1859*16467b97STreehugger Robot   strict private
1860*16467b97STreehugger Robot     /// <summary>First node or root node of tree matched for this rule.</summary>
1861*16467b97STreehugger Robot     FStart: IANTLRInterface;
1862*16467b97STreehugger Robot   protected
1863*16467b97STreehugger Robot     { IRuleReturnScope }
GetStart()1864*16467b97STreehugger Robot     function GetStart: IANTLRInterface; override;
1865*16467b97STreehugger Robot     procedure SetStart(const Value: IANTLRInterface); override;
1866*16467b97STreehugger Robot   end;
1867*16467b97STreehugger Robot 
1868*16467b97STreehugger Robot   TUnBufferedTreeNodeStream = class(TANTLRObject, IUnBufferedTreeNodeStream, ITreeNodeStream)
1869*16467b97STreehugger Robot   public
1870*16467b97STreehugger Robot     const
1871*16467b97STreehugger Robot       INITIAL_LOOKAHEAD_BUFFER_SIZE = 5;
1872*16467b97STreehugger Robot   strict protected
1873*16467b97STreehugger Robot     type
1874*16467b97STreehugger Robot       /// <summary>
1875*16467b97STreehugger Robot       /// When walking ahead with cyclic DFA or for syntactic predicates,
1876*16467b97STreehugger Robot       /// we need to record the state of the tree node stream.  This
1877*16467b97STreehugger Robot       /// class wraps up the current state of the UnBufferedTreeNodeStream.
1878*16467b97STreehugger Robot       /// Calling Mark() will push another of these on the markers stack.
1879*16467b97STreehugger Robot       /// </summary>
1880*16467b97STreehugger Robot       ITreeWalkState = interface(IANTLRInterface)
1881*16467b97STreehugger Robot       ['{506D1014-53CF-4B9D-BE0E-1666E9C22091}']
1882*16467b97STreehugger Robot         { Property accessors }
GetCurrentChildIndex()1883*16467b97STreehugger Robot         function GetCurrentChildIndex: Integer;
1884*16467b97STreehugger Robot         procedure SetCurrentChildIndex(const Value: Integer);
GetAbsoluteNodeIndex()1885*16467b97STreehugger Robot         function GetAbsoluteNodeIndex: Integer;
1886*16467b97STreehugger Robot         procedure SetAbsoluteNodeIndex(const Value: Integer);
GetCurrentNode()1887*16467b97STreehugger Robot         function GetCurrentNode: IANTLRInterface;
1888*16467b97STreehugger Robot         procedure SetCurrentNode(const Value: IANTLRInterface);
GetPreviousNode()1889*16467b97STreehugger Robot         function GetPreviousNode: IANTLRInterface;
1890*16467b97STreehugger Robot         procedure SetPreviousNode(const Value: IANTLRInterface);
GetNodeStackSize()1891*16467b97STreehugger Robot         function GetNodeStackSize: Integer;
1892*16467b97STreehugger Robot         procedure SetNodeStackSize(const Value: Integer);
GetIndexStackSize()1893*16467b97STreehugger Robot         function GetIndexStackSize: integer;
1894*16467b97STreehugger Robot         procedure SetIndexStackSize(const Value: integer);
GetLookAhead()1895*16467b97STreehugger Robot         function GetLookAhead: TANTLRInterfaceArray;
1896*16467b97STreehugger Robot         procedure SetLookAhead(const Value: TANTLRInterfaceArray);
1897*16467b97STreehugger Robot 
1898*16467b97STreehugger Robot         { Properties }
1899*16467b97STreehugger Robot         property CurrentChildIndex: Integer read GetCurrentChildIndex write SetCurrentChildIndex;
1900*16467b97STreehugger Robot         property AbsoluteNodeIndex: Integer read GetAbsoluteNodeIndex write SetAbsoluteNodeIndex;
1901*16467b97STreehugger Robot         property CurrentNode: IANTLRInterface read GetCurrentNode write SetCurrentNode;
1902*16467b97STreehugger Robot         property PreviousNode: IANTLRInterface read GetPreviousNode write SetPreviousNode;
1903*16467b97STreehugger Robot         ///<summary>Record state of the nodeStack</summary>
1904*16467b97STreehugger Robot         property NodeStackSize: Integer read GetNodeStackSize write SetNodeStackSize;
1905*16467b97STreehugger Robot         ///<summary>Record state of the indexStack</summary>
1906*16467b97STreehugger Robot         property IndexStackSize: integer read GetIndexStackSize write SetIndexStackSize;
1907*16467b97STreehugger Robot         property LookAhead: TANTLRInterfaceArray read GetLookAhead write SetLookAhead;
1908*16467b97STreehugger Robot       end;
1909*16467b97STreehugger Robot 
1910*16467b97STreehugger Robot       TTreeWalkState = class(TANTLRObject, ITreeWalkState)
1911*16467b97STreehugger Robot       strict private
1912*16467b97STreehugger Robot         FCurrentChildIndex: Integer;
1913*16467b97STreehugger Robot         FAbsoluteNodeIndex: Integer;
1914*16467b97STreehugger Robot         FCurrentNode: IANTLRInterface;
1915*16467b97STreehugger Robot         FPreviousNode: IANTLRInterface;
1916*16467b97STreehugger Robot         ///<summary>Record state of the nodeStack</summary>
1917*16467b97STreehugger Robot         FNodeStackSize: Integer;
1918*16467b97STreehugger Robot         ///<summary>Record state of the indexStack</summary>
1919*16467b97STreehugger Robot         FIndexStackSize: integer;
1920*16467b97STreehugger Robot         FLookAhead: TANTLRInterfaceArray;
1921*16467b97STreehugger Robot       protected
1922*16467b97STreehugger Robot         { ITreeWalkState }
GetCurrentChildIndex()1923*16467b97STreehugger Robot         function GetCurrentChildIndex: Integer;
1924*16467b97STreehugger Robot         procedure SetCurrentChildIndex(const Value: Integer);
GetAbsoluteNodeIndex()1925*16467b97STreehugger Robot         function GetAbsoluteNodeIndex: Integer;
1926*16467b97STreehugger Robot         procedure SetAbsoluteNodeIndex(const Value: Integer);
GetCurrentNode()1927*16467b97STreehugger Robot         function GetCurrentNode: IANTLRInterface;
1928*16467b97STreehugger Robot         procedure SetCurrentNode(const Value: IANTLRInterface);
GetPreviousNode()1929*16467b97STreehugger Robot         function GetPreviousNode: IANTLRInterface;
1930*16467b97STreehugger Robot         procedure SetPreviousNode(const Value: IANTLRInterface);
GetNodeStackSize()1931*16467b97STreehugger Robot         function GetNodeStackSize: Integer;
1932*16467b97STreehugger Robot         procedure SetNodeStackSize(const Value: Integer);
GetIndexStackSize()1933*16467b97STreehugger Robot         function GetIndexStackSize: integer;
1934*16467b97STreehugger Robot         procedure SetIndexStackSize(const Value: integer);
GetLookAhead()1935*16467b97STreehugger Robot         function GetLookAhead: TANTLRInterfaceArray;
1936*16467b97STreehugger Robot         procedure SetLookAhead(const Value: TANTLRInterfaceArray);
1937*16467b97STreehugger Robot       end;
1938*16467b97STreehugger Robot   strict private
1939*16467b97STreehugger Robot     /// <summary>Reuse same DOWN, UP navigation nodes unless this is true</summary>
1940*16467b97STreehugger Robot     FUniqueNavigationNodes: Boolean;
1941*16467b97STreehugger Robot 
1942*16467b97STreehugger Robot     /// <summary>Pull nodes from which tree? </summary>
1943*16467b97STreehugger Robot     FRoot: IANTLRInterface;
1944*16467b97STreehugger Robot 
1945*16467b97STreehugger Robot     /// <summary>IF this tree (root) was created from a token stream, track it.</summary>
1946*16467b97STreehugger Robot     FTokens: ITokenStream;
1947*16467b97STreehugger Robot 
1948*16467b97STreehugger Robot     /// <summary>What tree adaptor was used to build these trees</summary>
1949*16467b97STreehugger Robot     FAdaptor: ITreeAdaptor;
1950*16467b97STreehugger Robot 
1951*16467b97STreehugger Robot     /// <summary>
1952*16467b97STreehugger Robot     /// As we walk down the nodes, we must track parent nodes so we know
1953*16467b97STreehugger Robot     /// where to go after walking the last child of a node.  When visiting
1954*16467b97STreehugger Robot     /// a child, push current node and current index.
1955*16467b97STreehugger Robot     /// </summary>
1956*16467b97STreehugger Robot     FNodeStack: IStackList<IANTLRInterface>;
1957*16467b97STreehugger Robot 
1958*16467b97STreehugger Robot     /// <summary>
1959*16467b97STreehugger Robot     /// Track which child index you are visiting for each node we push.
1960*16467b97STreehugger Robot     /// TODO: pretty inefficient...use int[] when you have time
1961*16467b97STreehugger Robot     /// </summary>
1962*16467b97STreehugger Robot     FIndexStack: IStackList<Integer>;
1963*16467b97STreehugger Robot 
1964*16467b97STreehugger Robot     /// <summary>Which node are we currently visiting? </summary>
1965*16467b97STreehugger Robot     FCurrentNode: IANTLRInterface;
1966*16467b97STreehugger Robot 
1967*16467b97STreehugger Robot     /// <summary>Which node did we visit last?  Used for LT(-1) calls. </summary>
1968*16467b97STreehugger Robot     FPreviousNode: IANTLRInterface;
1969*16467b97STreehugger Robot 
1970*16467b97STreehugger Robot     /// <summary>
1971*16467b97STreehugger Robot     /// Which child are we currently visiting?  If -1 we have not visited
1972*16467b97STreehugger Robot     /// this node yet; next Consume() request will set currentIndex to 0.
1973*16467b97STreehugger Robot     /// </summary>
1974*16467b97STreehugger Robot     FCurrentChildIndex: Integer;
1975*16467b97STreehugger Robot 
1976*16467b97STreehugger Robot     /// <summary>
1977*16467b97STreehugger Robot     /// What node index did we just consume?  i=0..n-1 for n node trees.
1978*16467b97STreehugger Robot     /// IntStream.next is hence 1 + this value.  Size will be same.
1979*16467b97STreehugger Robot     /// </summary>
1980*16467b97STreehugger Robot     FAbsoluteNodeIndex: Integer;
1981*16467b97STreehugger Robot 
1982*16467b97STreehugger Robot     /// <summary>
1983*16467b97STreehugger Robot     /// Buffer tree node stream for use with LT(i).  This list grows
1984*16467b97STreehugger Robot     /// to fit new lookahead depths, but Consume() wraps like a circular
1985*16467b97STreehugger Robot     /// buffer.
1986*16467b97STreehugger Robot     /// </summary>
1987*16467b97STreehugger Robot     FLookahead: TANTLRInterfaceArray;
1988*16467b97STreehugger Robot 
1989*16467b97STreehugger Robot     /// <summary>lookahead[head] is the first symbol of lookahead, LT(1). </summary>
1990*16467b97STreehugger Robot     FHead: Integer;
1991*16467b97STreehugger Robot 
1992*16467b97STreehugger Robot     /// <summary>
1993*16467b97STreehugger Robot     /// Add new lookahead at lookahead[tail].  tail wraps around at the
1994*16467b97STreehugger Robot     /// end of the lookahead buffer so tail could be less than head.
1995*16467b97STreehugger Robot     /// </summary>
1996*16467b97STreehugger Robot     FTail: Integer;
1997*16467b97STreehugger Robot 
1998*16467b97STreehugger Robot     /// <summary>
1999*16467b97STreehugger Robot     /// Calls to Mark() may be nested so we have to track a stack of them.
2000*16467b97STreehugger Robot     /// The marker is an index into this stack. This is a List&lt;TreeWalkState&gt;.
2001*16467b97STreehugger Robot     /// Indexed from 1..markDepth. A null is kept at index 0. It is created
2002*16467b97STreehugger Robot     /// upon first call to Mark().
2003*16467b97STreehugger Robot     /// </summary>
2004*16467b97STreehugger Robot     FMarkers: IList<ITreeWalkState>;
2005*16467b97STreehugger Robot 
2006*16467b97STreehugger Robot     ///<summary>
2007*16467b97STreehugger Robot     /// tracks how deep Mark() calls are nested
2008*16467b97STreehugger Robot     /// </summary>
2009*16467b97STreehugger Robot     FMarkDepth: Integer;
2010*16467b97STreehugger Robot 
2011*16467b97STreehugger Robot     ///<summary>
2012*16467b97STreehugger Robot     /// Track the last Mark() call result value for use in Rewind().
2013*16467b97STreehugger Robot     /// </summary>
2014*16467b97STreehugger Robot     FLastMarker: Integer;
2015*16467b97STreehugger Robot 
2016*16467b97STreehugger Robot     // navigation nodes
2017*16467b97STreehugger Robot     FDown: IANTLRInterface;
2018*16467b97STreehugger Robot     FUp: IANTLRInterface;
2019*16467b97STreehugger Robot     FEof: IANTLRInterface;
2020*16467b97STreehugger Robot 
2021*16467b97STreehugger Robot     FCurrentEnumerationNode: ITree;
2022*16467b97STreehugger Robot   protected
2023*16467b97STreehugger Robot     { IIntStream }
GetSourceName()2024*16467b97STreehugger Robot     function GetSourceName: String;
2025*16467b97STreehugger Robot 
2026*16467b97STreehugger Robot     procedure Consume; virtual;
LA(I: Integer)2027*16467b97STreehugger Robot     function LA(I: Integer): Integer; virtual;
LAChar(I: Integer)2028*16467b97STreehugger Robot     function LAChar(I: Integer): Char;
Mark()2029*16467b97STreehugger Robot     function Mark: Integer; virtual;
Index()2030*16467b97STreehugger Robot     function Index: Integer; virtual;
2031*16467b97STreehugger Robot     procedure Rewind(const Marker: Integer); overload; virtual;
2032*16467b97STreehugger Robot     procedure Rewind; overload;
2033*16467b97STreehugger Robot     procedure Release(const Marker: Integer); virtual;
2034*16467b97STreehugger Robot     procedure Seek(const Index: Integer); virtual;
Size()2035*16467b97STreehugger Robot     function Size: Integer; virtual;
2036*16467b97STreehugger Robot   protected
2037*16467b97STreehugger Robot     { ITreeNodeStream }
GetTreeSource()2038*16467b97STreehugger Robot     function GetTreeSource: IANTLRInterface; virtual;
GetTokenStream()2039*16467b97STreehugger Robot     function GetTokenStream: ITokenStream;
GetTreeAdaptor()2040*16467b97STreehugger Robot     function GetTreeAdaptor: ITreeAdaptor;
2041*16467b97STreehugger Robot 
Get(const I: Integer)2042*16467b97STreehugger Robot     function Get(const I: Integer): IANTLRInterface; virtual;
LT(const K: Integer)2043*16467b97STreehugger Robot     function LT(const K: Integer): IANTLRInterface; virtual;
ToString(const Start, Stop: IANTLRInterface)2044*16467b97STreehugger Robot     function ToString(const Start, Stop: IANTLRInterface): String; reintroduce; overload; virtual;
2045*16467b97STreehugger Robot     procedure ReplaceChildren(const Parent: IANTLRInterface; const StartChildIndex,
2046*16467b97STreehugger Robot       StopChildIndex: Integer; const T: IANTLRInterface);
2047*16467b97STreehugger Robot   protected
2048*16467b97STreehugger Robot     { IUnBufferedTreeNodeStream }
GetHasUniqueNavigationNodes()2049*16467b97STreehugger Robot     function GetHasUniqueNavigationNodes: Boolean;
2050*16467b97STreehugger Robot     procedure SetHasUniqueNavigationNodes(const Value: Boolean);
GetCurrent()2051*16467b97STreehugger Robot     function GetCurrent: IANTLRInterface; virtual;
2052*16467b97STreehugger Robot     procedure SetTokenStream(const Value: ITokenStream);
2053*16467b97STreehugger Robot 
2054*16467b97STreehugger Robot     procedure Reset; virtual;
2055*16467b97STreehugger Robot 
2056*16467b97STreehugger Robot     /// <summary>
2057*16467b97STreehugger Robot     /// Navigates to the next node found during a depth-first walk of root.
2058*16467b97STreehugger Robot     /// Also, adds these nodes and DOWN/UP imaginary nodes into the lokoahead
2059*16467b97STreehugger Robot     /// buffer as a side-effect.  Normally side-effects are bad, but because
2060*16467b97STreehugger Robot     /// we can Emit many tokens for every MoveNext() call, it's pretty hard to
2061*16467b97STreehugger Robot     /// use a single return value for that.  We must add these tokens to
2062*16467b97STreehugger Robot     /// the lookahead buffer.
2063*16467b97STreehugger Robot     ///
2064*16467b97STreehugger Robot     /// This routine does *not* cause the 'Current' property to ever return the
2065*16467b97STreehugger Robot     /// DOWN/UP nodes; those are only returned by the LT() method.
2066*16467b97STreehugger Robot     ///
2067*16467b97STreehugger Robot     /// Ugh.  This mechanism is much more complicated than a recursive
2068*16467b97STreehugger Robot     /// solution, but it's the only way to provide nodes on-demand instead
2069*16467b97STreehugger Robot     /// of walking once completely through and buffering up the nodes. :(
2070*16467b97STreehugger Robot     /// </summary>
MoveNext()2071*16467b97STreehugger Robot     function MoveNext: Boolean; virtual;
2072*16467b97STreehugger Robot   strict protected
2073*16467b97STreehugger Robot     /// <summary>Make sure we have at least k symbols in lookahead buffer </summary>
2074*16467b97STreehugger Robot     procedure Fill(const K: Integer); virtual;
LookaheadSize()2075*16467b97STreehugger Robot     function LookaheadSize: Integer;
2076*16467b97STreehugger Robot 
2077*16467b97STreehugger Robot     /// <summary>
2078*16467b97STreehugger Robot     /// Add a node to the lookahead buffer.  Add at lookahead[tail].
2079*16467b97STreehugger Robot     /// If you tail+1 == head, then we must create a bigger buffer
2080*16467b97STreehugger Robot     /// and copy all the nodes over plus reset head, tail.  After
2081*16467b97STreehugger Robot     /// this method, LT(1) will be lookahead[0].
2082*16467b97STreehugger Robot     /// </summary>
2083*16467b97STreehugger Robot     procedure AddLookahead(const Node: IANTLRInterface); virtual;
2084*16467b97STreehugger Robot 
2085*16467b97STreehugger Robot     procedure ToStringWork(const P, Stop: IANTLRInterface;
2086*16467b97STreehugger Robot       const Buf: TStringBuilder); virtual;
2087*16467b97STreehugger Robot 
HandleRootNode()2088*16467b97STreehugger Robot     function HandleRootNode: IANTLRInterface; virtual;
VisitChild(const Child: Integer)2089*16467b97STreehugger Robot     function VisitChild(const Child: Integer): IANTLRInterface; virtual;
2090*16467b97STreehugger Robot 
2091*16467b97STreehugger Robot     /// <summary>
2092*16467b97STreehugger Robot     ///  Walk upwards looking for a node with more children to walk.
2093*16467b97STreehugger Robot     /// </summary>
2094*16467b97STreehugger Robot     procedure WalkBackToMostRecentNodeWithUnvisitedChildren; virtual;
2095*16467b97STreehugger Robot 
2096*16467b97STreehugger Robot     /// <summary>
2097*16467b97STreehugger Robot     /// As we flatten the tree, we use UP, DOWN nodes to represent
2098*16467b97STreehugger Robot     /// the tree structure.  When debugging we need unique nodes
2099*16467b97STreehugger Robot     /// so instantiate new ones when uniqueNavigationNodes is true.
2100*16467b97STreehugger Robot     /// </summary>
2101*16467b97STreehugger Robot     procedure AddNavigationNode(const TokenType: Integer); virtual;
2102*16467b97STreehugger Robot   public
2103*16467b97STreehugger Robot     constructor Create; overload;
2104*16467b97STreehugger Robot     constructor Create(const ATree: IANTLRInterface); overload;
2105*16467b97STreehugger Robot     constructor Create(const AAdaptor: ITreeAdaptor; const ATree: IANTLRInterface); overload;
2106*16467b97STreehugger Robot 
ToString()2107*16467b97STreehugger Robot     function ToString: String; overload; override;
2108*16467b97STreehugger Robot   end;
2109*16467b97STreehugger Robot 
2110*16467b97STreehugger Robot { These functions return X or, if X = nil, an empty default instance }
Def(const X: ICommonTree)2111*16467b97STreehugger Robot function Def(const X: ICommonTree): ICommonTree; overload;
2112*16467b97STreehugger Robot 
2113*16467b97STreehugger Robot implementation
2114*16467b97STreehugger Robot 
2115*16467b97STreehugger Robot uses
2116*16467b97STreehugger Robot   Math;
2117*16467b97STreehugger Robot 
2118*16467b97STreehugger Robot { TTree }
2119*16467b97STreehugger Robot 
2120*16467b97STreehugger Robot class procedure TTree.Initialize;
2121*16467b97STreehugger Robot begin
2122*16467b97STreehugger Robot   FINVALID_NODE := TCommonTree.Create(TToken.INVALID_TOKEN);
2123*16467b97STreehugger Robot end;
2124*16467b97STreehugger Robot 
2125*16467b97STreehugger Robot { TBaseTree }
2126*16467b97STreehugger Robot 
2127*16467b97STreehugger Robot constructor TBaseTree.Create;
2128*16467b97STreehugger Robot begin
2129*16467b97STreehugger Robot   inherited;
2130*16467b97STreehugger Robot end;
2131*16467b97STreehugger Robot 
2132*16467b97STreehugger Robot procedure TBaseTree.AddChild(const T: ITree);
2133*16467b97STreehugger Robot var
2134*16467b97STreehugger Robot   ChildTree: IBaseTree;
2135*16467b97STreehugger Robot   C: IBaseTree;
2136*16467b97STreehugger Robot begin
2137*16467b97STreehugger Robot   if (T = nil) then
2138*16467b97STreehugger Robot     Exit;
2139*16467b97STreehugger Robot 
2140*16467b97STreehugger Robot   ChildTree := T as IBaseTree;
2141*16467b97STreehugger Robot   if ChildTree.IsNil then // t is an empty node possibly with children
2142*16467b97STreehugger Robot   begin
2143*16467b97STreehugger Robot     if Assigned(FChildren) and SameObj(FChildren, ChildTree.Children) then
2144*16467b97STreehugger Robot       raise EInvalidOperation.Create('Attempt to add child list to itself');
2145*16467b97STreehugger Robot 
2146*16467b97STreehugger Robot     // just add all of childTree's children to this
2147*16467b97STreehugger Robot     if Assigned(ChildTree.Children) then
2148*16467b97STreehugger Robot     begin
2149*16467b97STreehugger Robot       if Assigned(FChildren) then // must copy, this has children already
2150*16467b97STreehugger Robot       begin
2151*16467b97STreehugger Robot         for C in ChildTree.Children do
2152*16467b97STreehugger Robot         begin
2153*16467b97STreehugger Robot           FChildren.Add(C);
2154*16467b97STreehugger Robot           // handle double-link stuff for each child of nil root
2155*16467b97STreehugger Robot           C.Parent := Self;
2156*16467b97STreehugger Robot           C.ChildIndex := FChildren.Count - 1;
2157*16467b97STreehugger Robot         end;
2158*16467b97STreehugger Robot       end
2159*16467b97STreehugger Robot       else begin
2160*16467b97STreehugger Robot         // no children for this but t has children; just set pointer
2161*16467b97STreehugger Robot         // call general freshener routine
2162*16467b97STreehugger Robot         FChildren := ChildTree.Children;
2163*16467b97STreehugger Robot         FreshenParentAndChildIndexes;
2164*16467b97STreehugger Robot       end;
2165*16467b97STreehugger Robot     end;
2166*16467b97STreehugger Robot   end
2167*16467b97STreehugger Robot   else
2168*16467b97STreehugger Robot   begin
2169*16467b97STreehugger Robot     // child is not nil (don't care about children)
2170*16467b97STreehugger Robot     if (FChildren = nil) then
2171*16467b97STreehugger Robot     begin
2172*16467b97STreehugger Robot       FChildren := CreateChildrenList; // create children list on demand
2173*16467b97STreehugger Robot     end;
2174*16467b97STreehugger Robot     FChildren.Add(ChildTree);
2175*16467b97STreehugger Robot     ChildTree.Parent := Self;
2176*16467b97STreehugger Robot     ChildTree.ChildIndex := FChildren.Count - 1;
2177*16467b97STreehugger Robot   end;
2178*16467b97STreehugger Robot end;
2179*16467b97STreehugger Robot 
2180*16467b97STreehugger Robot procedure TBaseTree.AddChildren(const Kids: IList<IBaseTree>);
2181*16467b97STreehugger Robot var
2182*16467b97STreehugger Robot   T: IBaseTree;
2183*16467b97STreehugger Robot begin
2184*16467b97STreehugger Robot   for T in Kids do
2185*16467b97STreehugger Robot     AddChild(T);
2186*16467b97STreehugger Robot end;
2187*16467b97STreehugger Robot 
2188*16467b97STreehugger Robot constructor TBaseTree.Create(const ANode: ITree);
2189*16467b97STreehugger Robot begin
2190*16467b97STreehugger Robot   Create;
2191*16467b97STreehugger Robot   // No default implementation
2192*16467b97STreehugger Robot end;
2193*16467b97STreehugger Robot 
CreateChildrenListnull2194*16467b97STreehugger Robot function TBaseTree.CreateChildrenList: IList<IBaseTree>;
2195*16467b97STreehugger Robot begin
2196*16467b97STreehugger Robot   Result := TList<IBaseTree>.Create;
2197*16467b97STreehugger Robot end;
2198*16467b97STreehugger Robot 
TBaseTree.DeleteChild(const I: Integer)2199*16467b97STreehugger Robot function TBaseTree.DeleteChild(const I: Integer): IANTLRInterface;
2200*16467b97STreehugger Robot begin
2201*16467b97STreehugger Robot   if (FChildren = nil) then
2202*16467b97STreehugger Robot     Result := nil
2203*16467b97STreehugger Robot   else
2204*16467b97STreehugger Robot   begin
2205*16467b97STreehugger Robot     Result := FChildren[I];
2206*16467b97STreehugger Robot     FChildren.Delete(I);
2207*16467b97STreehugger Robot     // walk rest and decrement their child indexes
2208*16467b97STreehugger Robot     FreshenParentAndChildIndexes(I);
2209*16467b97STreehugger Robot   end;
2210*16467b97STreehugger Robot end;
2211*16467b97STreehugger Robot 
2212*16467b97STreehugger Robot procedure TBaseTree.FreshenParentAndChildIndexes(const Offset: Integer);
2213*16467b97STreehugger Robot var
2214*16467b97STreehugger Robot   N, C: Integer;
2215*16467b97STreehugger Robot   Child: ITree;
2216*16467b97STreehugger Robot begin
2217*16467b97STreehugger Robot   N := GetChildCount;
2218*16467b97STreehugger Robot   for C := Offset to N - 1 do
2219*16467b97STreehugger Robot   begin
2220*16467b97STreehugger Robot     Child := GetChild(C);
2221*16467b97STreehugger Robot     Child.ChildIndex := C;
2222*16467b97STreehugger Robot     Child.Parent := Self;
2223*16467b97STreehugger Robot   end;
2224*16467b97STreehugger Robot end;
2225*16467b97STreehugger Robot 
2226*16467b97STreehugger Robot procedure TBaseTree.FreshenParentAndChildIndexes;
2227*16467b97STreehugger Robot begin
2228*16467b97STreehugger Robot   FreshenParentAndChildIndexes(0);
2229*16467b97STreehugger Robot end;
2230*16467b97STreehugger Robot 
TBaseTree.GetCharPositionInLine()2231*16467b97STreehugger Robot function TBaseTree.GetCharPositionInLine: Integer;
2232*16467b97STreehugger Robot begin
2233*16467b97STreehugger Robot   Result := 0;
2234*16467b97STreehugger Robot end;
2235*16467b97STreehugger Robot 
TBaseTree.GetChild(const I: Integer)2236*16467b97STreehugger Robot function TBaseTree.GetChild(const I: Integer): ITree;
2237*16467b97STreehugger Robot begin
2238*16467b97STreehugger Robot   if (FChildren = nil) or (I >= FChildren.Count) then
2239*16467b97STreehugger Robot     Result := nil
2240*16467b97STreehugger Robot   else
2241*16467b97STreehugger Robot     Result := FChildren[I];
2242*16467b97STreehugger Robot end;
2243*16467b97STreehugger Robot 
GetChildCountnull2244*16467b97STreehugger Robot function TBaseTree.GetChildCount: Integer;
2245*16467b97STreehugger Robot begin
2246*16467b97STreehugger Robot   if Assigned(FChildren) then
2247*16467b97STreehugger Robot     Result := FChildren.Count
2248*16467b97STreehugger Robot   else
2249*16467b97STreehugger Robot     Result := 0;
2250*16467b97STreehugger Robot end;
2251*16467b97STreehugger Robot 
GetChildIndexnull2252*16467b97STreehugger Robot function TBaseTree.GetChildIndex: Integer;
2253*16467b97STreehugger Robot begin
2254*16467b97STreehugger Robot   // No default implementation
2255*16467b97STreehugger Robot   Result := 0;
2256*16467b97STreehugger Robot end;
2257*16467b97STreehugger Robot 
GetChildrennull2258*16467b97STreehugger Robot function TBaseTree.GetChildren: IList<IBaseTree>;
2259*16467b97STreehugger Robot begin
2260*16467b97STreehugger Robot   Result := FChildren;
2261*16467b97STreehugger Robot end;
2262*16467b97STreehugger Robot 
TBaseTree.GetIsNil()2263*16467b97STreehugger Robot function TBaseTree.GetIsNil: Boolean;
2264*16467b97STreehugger Robot begin
2265*16467b97STreehugger Robot   Result := False;
2266*16467b97STreehugger Robot end;
2267*16467b97STreehugger Robot 
GetLinenull2268*16467b97STreehugger Robot function TBaseTree.GetLine: Integer;
2269*16467b97STreehugger Robot begin
2270*16467b97STreehugger Robot   Result := 0;
2271*16467b97STreehugger Robot end;
2272*16467b97STreehugger Robot 
GetParentnull2273*16467b97STreehugger Robot function TBaseTree.GetParent: ITree;
2274*16467b97STreehugger Robot begin
2275*16467b97STreehugger Robot   // No default implementation
2276*16467b97STreehugger Robot   Result := nil;
2277*16467b97STreehugger Robot end;
2278*16467b97STreehugger Robot 
2279*16467b97STreehugger Robot procedure TBaseTree.ReplaceChildren(const StartChildIndex,
2280*16467b97STreehugger Robot   StopChildIndex: Integer; const T: IANTLRInterface);
2281*16467b97STreehugger Robot var
2282*16467b97STreehugger Robot   ReplacingHowMany, ReplacingWithHowMany, NumNewChildren, Delta, I, J: Integer;
2283*16467b97STreehugger Robot   IndexToDelete, C, ReplacedSoFar: Integer;
2284*16467b97STreehugger Robot   NewTree, Killed: IBaseTree;
2285*16467b97STreehugger Robot   NewChildren: IList<IBaseTree>;
2286*16467b97STreehugger Robot   Child: IBaseTree;
2287*16467b97STreehugger Robot begin
2288*16467b97STreehugger Robot   if (FChildren = nil) then
2289*16467b97STreehugger Robot     raise EArgumentException.Create('indexes invalid; no children in list');
2290*16467b97STreehugger Robot   ReplacingHowMany := StopChildIndex - StartChildIndex + 1;
2291*16467b97STreehugger Robot   NewTree := T as IBaseTree;
2292*16467b97STreehugger Robot 
2293*16467b97STreehugger Robot   // normalize to a list of children to add: newChildren
2294*16467b97STreehugger Robot   if (NewTree.IsNil) then
2295*16467b97STreehugger Robot     NewChildren := NewTree.Children
2296*16467b97STreehugger Robot   else
2297*16467b97STreehugger Robot   begin
2298*16467b97STreehugger Robot     NewChildren := TList<IBaseTree>.Create;
2299*16467b97STreehugger Robot     NewChildren.Add(NewTree);
2300*16467b97STreehugger Robot   end;
2301*16467b97STreehugger Robot 
2302*16467b97STreehugger Robot   ReplacingWithHowMany := NewChildren.Count;
2303*16467b97STreehugger Robot   NumNewChildren := NewChildren.Count;
2304*16467b97STreehugger Robot   Delta := ReplacingHowMany - ReplacingWithHowMany;
2305*16467b97STreehugger Robot 
2306*16467b97STreehugger Robot   // if same number of nodes, do direct replace
2307*16467b97STreehugger Robot   if (Delta = 0) then
2308*16467b97STreehugger Robot   begin
2309*16467b97STreehugger Robot     J := 0; // index into new children
2310*16467b97STreehugger Robot     for I := StartChildIndex to StopChildIndex do
2311*16467b97STreehugger Robot     begin
2312*16467b97STreehugger Robot       Child := NewChildren[J];
2313*16467b97STreehugger Robot       FChildren[I] := Child;
2314*16467b97STreehugger Robot       Child.Parent := Self;
2315*16467b97STreehugger Robot       Child.ChildIndex := I;
2316*16467b97STreehugger Robot       Inc(J);
2317*16467b97STreehugger Robot     end;
2318*16467b97STreehugger Robot   end
2319*16467b97STreehugger Robot   else
2320*16467b97STreehugger Robot     if (Delta > 0) then
2321*16467b97STreehugger Robot     begin
2322*16467b97STreehugger Robot       // fewer new nodes than there were
2323*16467b97STreehugger Robot       // set children and then delete extra
2324*16467b97STreehugger Robot       for J := 0 to NumNewChildren - 1 do
2325*16467b97STreehugger Robot         FChildren[StartChildIndex + J] := NewChildren[J];
2326*16467b97STreehugger Robot       IndexToDelete := StartChildIndex + NumNewChildren;
2327*16467b97STreehugger Robot       for C := IndexToDelete to StopChildIndex do
2328*16467b97STreehugger Robot       begin
2329*16467b97STreehugger Robot         // delete same index, shifting everybody down each time
2330*16467b97STreehugger Robot         Killed := FChildren[IndexToDelete];
2331*16467b97STreehugger Robot         FChildren.Delete(IndexToDelete);
2332*16467b97STreehugger Robot       end;
2333*16467b97STreehugger Robot       FreshenParentAndChildIndexes(StartChildIndex);
2334*16467b97STreehugger Robot     end
2335*16467b97STreehugger Robot     else
2336*16467b97STreehugger Robot       begin
2337*16467b97STreehugger Robot         // more new nodes than were there before
2338*16467b97STreehugger Robot         // fill in as many children as we can (replacingHowMany) w/o moving data
2339*16467b97STreehugger Robot         ReplacedSoFar := 0;
2340*16467b97STreehugger Robot         while (ReplacedSoFar < ReplacingHowMany) do
2341*16467b97STreehugger Robot         begin
2342*16467b97STreehugger Robot           FChildren[StartChildIndex + ReplacedSoFar] := NewChildren[ReplacedSoFar];
2343*16467b97STreehugger Robot           Inc(ReplacedSoFar);
2344*16467b97STreehugger Robot         end;
2345*16467b97STreehugger Robot 
2346*16467b97STreehugger Robot         // replacedSoFar has correct index for children to add
2347*16467b97STreehugger Robot         while (ReplacedSoFar < ReplacingWithHowMany) do
2348*16467b97STreehugger Robot         begin
2349*16467b97STreehugger Robot           FChildren.Insert(StartChildIndex + ReplacedSoFar,NewChildren[ReplacedSoFar]);
2350*16467b97STreehugger Robot           Inc(ReplacedSoFar);
2351*16467b97STreehugger Robot         end;
2352*16467b97STreehugger Robot 
2353*16467b97STreehugger Robot         FreshenParentAndChildIndexes(StartChildIndex);
2354*16467b97STreehugger Robot       end;
2355*16467b97STreehugger Robot end;
2356*16467b97STreehugger Robot 
2357*16467b97STreehugger Robot procedure TBaseTree.SanityCheckParentAndChildIndexes;
2358*16467b97STreehugger Robot begin
2359*16467b97STreehugger Robot   SanityCheckParentAndChildIndexes(nil, -1);
2360*16467b97STreehugger Robot end;
2361*16467b97STreehugger Robot 
2362*16467b97STreehugger Robot procedure TBaseTree.SanityCheckParentAndChildIndexes(const Parent: ITree;
2363*16467b97STreehugger Robot   const I: Integer);
2364*16467b97STreehugger Robot var
2365*16467b97STreehugger Robot   N, C: Integer;
2366*16467b97STreehugger Robot   Child: ICommonTree;
2367*16467b97STreehugger Robot begin
2368*16467b97STreehugger Robot   if not SameObj(Parent, GetParent) then
2369*16467b97STreehugger Robot     raise EArgumentException.Create('parents don''t match; expected '
2370*16467b97STreehugger Robot       + Parent.ToString + ' found ' + GetParent.ToString);
2371*16467b97STreehugger Robot 
2372*16467b97STreehugger Robot   if (I <> GetChildIndex) then
2373*16467b97STreehugger Robot     raise EArgumentException.Create('child indexes don''t match; expected '
2374*16467b97STreehugger Robot       + IntToStr(I) + ' found ' + IntToStr(GetChildIndex));
2375*16467b97STreehugger Robot 
2376*16467b97STreehugger Robot   N := GetChildCount;
2377*16467b97STreehugger Robot   for C := 0 to N - 1 do
2378*16467b97STreehugger Robot   begin
2379*16467b97STreehugger Robot     Child := GetChild(C) as ICommonTree;
2380*16467b97STreehugger Robot     Child.SanityCheckParentAndChildIndexes(Self, C);
2381*16467b97STreehugger Robot   end;
2382*16467b97STreehugger Robot end;
2383*16467b97STreehugger Robot 
2384*16467b97STreehugger Robot procedure TBaseTree.SetChild(const I: Integer; const T: ITree);
2385*16467b97STreehugger Robot begin
2386*16467b97STreehugger Robot   if (T = nil) then
2387*16467b97STreehugger Robot     Exit;
2388*16467b97STreehugger Robot 
2389*16467b97STreehugger Robot   if T.IsNil then
2390*16467b97STreehugger Robot     raise EArgumentException.Create('Cannot set single child to a list');
2391*16467b97STreehugger Robot 
2392*16467b97STreehugger Robot   if (FChildren = nil) then
2393*16467b97STreehugger Robot   begin
2394*16467b97STreehugger Robot     FChildren := CreateChildrenList;
2395*16467b97STreehugger Robot   end;
2396*16467b97STreehugger Robot 
2397*16467b97STreehugger Robot   FChildren[I] := T as IBaseTree;
2398*16467b97STreehugger Robot   T.Parent := Self;
2399*16467b97STreehugger Robot   T.ChildIndex := I;
2400*16467b97STreehugger Robot end;
2401*16467b97STreehugger Robot 
2402*16467b97STreehugger Robot procedure TBaseTree.SetChildIndex(const Value: Integer);
2403*16467b97STreehugger Robot begin
2404*16467b97STreehugger Robot   // No default implementation
2405*16467b97STreehugger Robot end;
2406*16467b97STreehugger Robot 
2407*16467b97STreehugger Robot procedure TBaseTree.SetParent(const Value: ITree);
2408*16467b97STreehugger Robot begin
2409*16467b97STreehugger Robot   // No default implementation
2410*16467b97STreehugger Robot end;
2411*16467b97STreehugger Robot 
ToStringTreenull2412*16467b97STreehugger Robot function TBaseTree.ToStringTree: String;
2413*16467b97STreehugger Robot var
2414*16467b97STreehugger Robot   Buf: TStringBuilder;
2415*16467b97STreehugger Robot   I: Integer;
2416*16467b97STreehugger Robot   T: IBaseTree;
2417*16467b97STreehugger Robot begin
2418*16467b97STreehugger Robot   if (FChildren = nil) or (FChildren.Count = 0) then
2419*16467b97STreehugger Robot     Result := ToString
2420*16467b97STreehugger Robot   else
2421*16467b97STreehugger Robot   begin
2422*16467b97STreehugger Robot     Buf := TStringBuilder.Create;
2423*16467b97STreehugger Robot     try
2424*16467b97STreehugger Robot       if (not GetIsNil) then
2425*16467b97STreehugger Robot       begin
2426*16467b97STreehugger Robot         Buf.Append('(');
2427*16467b97STreehugger Robot         Buf.Append(ToString);
2428*16467b97STreehugger Robot         Buf.Append(' ');
2429*16467b97STreehugger Robot       end;
2430*16467b97STreehugger Robot 
2431*16467b97STreehugger Robot       for I := 0 to FChildren.Count - 1 do
2432*16467b97STreehugger Robot       begin
2433*16467b97STreehugger Robot         T := FChildren[I];
2434*16467b97STreehugger Robot         if (I > 0) then
2435*16467b97STreehugger Robot           Buf.Append(' ');
2436*16467b97STreehugger Robot         Buf.Append(T.ToStringTree);
2437*16467b97STreehugger Robot       end;
2438*16467b97STreehugger Robot 
2439*16467b97STreehugger Robot       if (not GetIsNil) then
2440*16467b97STreehugger Robot         Buf.Append(')');
2441*16467b97STreehugger Robot 
2442*16467b97STreehugger Robot       Result := Buf.ToString;
2443*16467b97STreehugger Robot     finally
2444*16467b97STreehugger Robot       Buf.Free;
2445*16467b97STreehugger Robot     end;
2446*16467b97STreehugger Robot   end;
2447*16467b97STreehugger Robot end;
2448*16467b97STreehugger Robot 
2449*16467b97STreehugger Robot { TCommonTree }
2450*16467b97STreehugger Robot 
2451*16467b97STreehugger Robot constructor TCommonTree.Create;
2452*16467b97STreehugger Robot begin
2453*16467b97STreehugger Robot   inherited;
2454*16467b97STreehugger Robot   FStartIndex := -1;
2455*16467b97STreehugger Robot   FStopIndex := -1;
2456*16467b97STreehugger Robot   FChildIndex := -1;
2457*16467b97STreehugger Robot end;
2458*16467b97STreehugger Robot 
2459*16467b97STreehugger Robot constructor TCommonTree.Create(const ANode: ICommonTree);
2460*16467b97STreehugger Robot begin
2461*16467b97STreehugger Robot   inherited Create(ANode);
2462*16467b97STreehugger Robot   FToken := ANode.Token;
2463*16467b97STreehugger Robot   FStartIndex := ANode.StartIndex;
2464*16467b97STreehugger Robot   FStopIndex := ANode.StopIndex;
2465*16467b97STreehugger Robot   FChildIndex := -1;
2466*16467b97STreehugger Robot end;
2467*16467b97STreehugger Robot 
2468*16467b97STreehugger Robot constructor TCommonTree.Create(const AToken: IToken);
2469*16467b97STreehugger Robot begin
2470*16467b97STreehugger Robot   Create;
2471*16467b97STreehugger Robot   FToken := AToken;
2472*16467b97STreehugger Robot end;
2473*16467b97STreehugger Robot 
TCommonTree.DupNode()2474*16467b97STreehugger Robot function TCommonTree.DupNode: ITree;
2475*16467b97STreehugger Robot begin
2476*16467b97STreehugger Robot   Result := TCommonTree.Create(Self) as ICommonTree;
2477*16467b97STreehugger Robot end;
2478*16467b97STreehugger Robot 
TCommonTree.GetCharPositionInLine()2479*16467b97STreehugger Robot function TCommonTree.GetCharPositionInLine: Integer;
2480*16467b97STreehugger Robot begin
2481*16467b97STreehugger Robot   if (FToken = nil) or (FToken.CharPositionInLine = -1) then
2482*16467b97STreehugger Robot   begin
2483*16467b97STreehugger Robot     if (GetChildCount > 0) then
2484*16467b97STreehugger Robot       Result := GetChild(0).CharPositionInLine
2485*16467b97STreehugger Robot     else
2486*16467b97STreehugger Robot       Result := 0;
2487*16467b97STreehugger Robot   end
2488*16467b97STreehugger Robot   else
2489*16467b97STreehugger Robot     Result := FToken.CharPositionInLine;
2490*16467b97STreehugger Robot end;
2491*16467b97STreehugger Robot 
GetChildIndexnull2492*16467b97STreehugger Robot function TCommonTree.GetChildIndex: Integer;
2493*16467b97STreehugger Robot begin
2494*16467b97STreehugger Robot   Result := FChildIndex;
2495*16467b97STreehugger Robot end;
2496*16467b97STreehugger Robot 
TCommonTree.GetIsNil()2497*16467b97STreehugger Robot function TCommonTree.GetIsNil: Boolean;
2498*16467b97STreehugger Robot begin
2499*16467b97STreehugger Robot   Result := (FToken = nil);
2500*16467b97STreehugger Robot end;
2501*16467b97STreehugger Robot 
GetLinenull2502*16467b97STreehugger Robot function TCommonTree.GetLine: Integer;
2503*16467b97STreehugger Robot begin
2504*16467b97STreehugger Robot   if (FToken = nil) or (FToken.Line = 0) then
2505*16467b97STreehugger Robot   begin
2506*16467b97STreehugger Robot     if (GetChildCount > 0) then
2507*16467b97STreehugger Robot       Result := GetChild(0).Line
2508*16467b97STreehugger Robot     else
2509*16467b97STreehugger Robot       Result := 0
2510*16467b97STreehugger Robot   end
2511*16467b97STreehugger Robot   else
2512*16467b97STreehugger Robot     Result := FToken.Line;
2513*16467b97STreehugger Robot end;
2514*16467b97STreehugger Robot 
GetParentnull2515*16467b97STreehugger Robot function TCommonTree.GetParent: ITree;
2516*16467b97STreehugger Robot begin
2517*16467b97STreehugger Robot   Result := ITree(FParent);
2518*16467b97STreehugger Robot end;
2519*16467b97STreehugger Robot 
GetStartIndexnull2520*16467b97STreehugger Robot function TCommonTree.GetStartIndex: Integer;
2521*16467b97STreehugger Robot begin
2522*16467b97STreehugger Robot   Result := FStartIndex;
2523*16467b97STreehugger Robot end;
2524*16467b97STreehugger Robot 
TCommonTree.GetStopIndex()2525*16467b97STreehugger Robot function TCommonTree.GetStopIndex: Integer;
2526*16467b97STreehugger Robot begin
2527*16467b97STreehugger Robot   Result := FStopIndex;
2528*16467b97STreehugger Robot end;
2529*16467b97STreehugger Robot 
GetTextnull2530*16467b97STreehugger Robot function TCommonTree.GetText: String;
2531*16467b97STreehugger Robot begin
2532*16467b97STreehugger Robot   if (FToken = nil) then
2533*16467b97STreehugger Robot     Result := ''
2534*16467b97STreehugger Robot   else
2535*16467b97STreehugger Robot     Result := FToken.Text;
2536*16467b97STreehugger Robot end;
2537*16467b97STreehugger Robot 
GetTokennull2538*16467b97STreehugger Robot function TCommonTree.GetToken: IToken;
2539*16467b97STreehugger Robot begin
2540*16467b97STreehugger Robot   Result := FToken;
2541*16467b97STreehugger Robot end;
2542*16467b97STreehugger Robot 
TCommonTree.GetTokenStartIndex()2543*16467b97STreehugger Robot function TCommonTree.GetTokenStartIndex: Integer;
2544*16467b97STreehugger Robot begin
2545*16467b97STreehugger Robot   if (FStartIndex = -1) and (FToken <> nil) then
2546*16467b97STreehugger Robot     Result := FToken.TokenIndex
2547*16467b97STreehugger Robot   else
2548*16467b97STreehugger Robot     Result := FStartIndex;
2549*16467b97STreehugger Robot end;
2550*16467b97STreehugger Robot 
GetTokenStopIndexnull2551*16467b97STreehugger Robot function TCommonTree.GetTokenStopIndex: Integer;
2552*16467b97STreehugger Robot begin
2553*16467b97STreehugger Robot   if (FStopIndex = -1) and (FToken <> nil) then
2554*16467b97STreehugger Robot     Result := FToken.TokenIndex
2555*16467b97STreehugger Robot   else
2556*16467b97STreehugger Robot     Result := FStopIndex;
2557*16467b97STreehugger Robot end;
2558*16467b97STreehugger Robot 
TCommonTree.GetTokenType()2559*16467b97STreehugger Robot function TCommonTree.GetTokenType: Integer;
2560*16467b97STreehugger Robot begin
2561*16467b97STreehugger Robot   if (FToken = nil) then
2562*16467b97STreehugger Robot     Result := TToken.INVALID_TOKEN_TYPE
2563*16467b97STreehugger Robot   else
2564*16467b97STreehugger Robot     Result := FToken.TokenType;
2565*16467b97STreehugger Robot end;
2566*16467b97STreehugger Robot 
2567*16467b97STreehugger Robot procedure TCommonTree.SetChildIndex(const Value: Integer);
2568*16467b97STreehugger Robot begin
2569*16467b97STreehugger Robot   FChildIndex := Value;
2570*16467b97STreehugger Robot end;
2571*16467b97STreehugger Robot 
2572*16467b97STreehugger Robot procedure TCommonTree.SetParent(const Value: ITree);
2573*16467b97STreehugger Robot begin
2574*16467b97STreehugger Robot   FParent := Pointer(Value as ICommonTree);
2575*16467b97STreehugger Robot end;
2576*16467b97STreehugger Robot 
2577*16467b97STreehugger Robot procedure TCommonTree.SetStartIndex(const Value: Integer);
2578*16467b97STreehugger Robot begin
2579*16467b97STreehugger Robot   FStartIndex := Value;
2580*16467b97STreehugger Robot end;
2581*16467b97STreehugger Robot 
2582*16467b97STreehugger Robot procedure TCommonTree.SetStopIndex(const Value: Integer);
2583*16467b97STreehugger Robot begin
2584*16467b97STreehugger Robot   FStopIndex := Value;
2585*16467b97STreehugger Robot end;
2586*16467b97STreehugger Robot 
2587*16467b97STreehugger Robot procedure TCommonTree.SetTokenStartIndex(const Value: Integer);
2588*16467b97STreehugger Robot begin
2589*16467b97STreehugger Robot   FStartIndex := Value;
2590*16467b97STreehugger Robot end;
2591*16467b97STreehugger Robot 
2592*16467b97STreehugger Robot procedure TCommonTree.SetTokenStopIndex(const Value: Integer);
2593*16467b97STreehugger Robot begin
2594*16467b97STreehugger Robot   FStopIndex := Value;
2595*16467b97STreehugger Robot end;
2596*16467b97STreehugger Robot 
TCommonTree.ToString()2597*16467b97STreehugger Robot function TCommonTree.ToString: String;
2598*16467b97STreehugger Robot begin
2599*16467b97STreehugger Robot   if (GetIsNil) then
2600*16467b97STreehugger Robot     Result := 'nil'
2601*16467b97STreehugger Robot   else
2602*16467b97STreehugger Robot     if (GetTokenType = TToken.INVALID_TOKEN_TYPE) then
2603*16467b97STreehugger Robot       Result := '<errornode>'
2604*16467b97STreehugger Robot     else
2605*16467b97STreehugger Robot       if (FToken = nil) then
2606*16467b97STreehugger Robot         Result := ''
2607*16467b97STreehugger Robot       else
2608*16467b97STreehugger Robot         Result := FToken.Text;
2609*16467b97STreehugger Robot end;
2610*16467b97STreehugger Robot 
2611*16467b97STreehugger Robot { TCommonErrorNode }
2612*16467b97STreehugger Robot 
2613*16467b97STreehugger Robot constructor TCommonErrorNode.Create(const AInput: ITokenStream; const AStart,
2614*16467b97STreehugger Robot   AStop: IToken; const AException: ERecognitionException);
2615*16467b97STreehugger Robot begin
2616*16467b97STreehugger Robot   inherited Create;
2617*16467b97STreehugger Robot   if (AStop = nil) or ((AStop.TokenIndex < AStart.TokenIndex)
2618*16467b97STreehugger Robot     and (AStop.TokenType <> TToken.EOF))
2619*16467b97STreehugger Robot   then
2620*16467b97STreehugger Robot     // sometimes resync does not consume a token (when LT(1) is
2621*16467b97STreehugger Robot     // in follow set). So, stop will be 1 to left to start. adjust.
2622*16467b97STreehugger Robot     // Also handle case where start is the first token and no token
2623*16467b97STreehugger Robot     // is consumed during recovery; LT(-1) will return null.
2624*16467b97STreehugger Robot     FStop := AStart
2625*16467b97STreehugger Robot   else
2626*16467b97STreehugger Robot     FStop := AStop;
2627*16467b97STreehugger Robot   FInput := AInput;
2628*16467b97STreehugger Robot   FStart := AStart;
2629*16467b97STreehugger Robot   FTrappedException := AException;
2630*16467b97STreehugger Robot end;
2631*16467b97STreehugger Robot 
GetIsNilnull2632*16467b97STreehugger Robot function TCommonErrorNode.GetIsNil: Boolean;
2633*16467b97STreehugger Robot begin
2634*16467b97STreehugger Robot   Result := False;
2635*16467b97STreehugger Robot end;
2636*16467b97STreehugger Robot 
TCommonErrorNode.GetText()2637*16467b97STreehugger Robot function TCommonErrorNode.GetText: String;
2638*16467b97STreehugger Robot var
2639*16467b97STreehugger Robot   I, J: Integer;
2640*16467b97STreehugger Robot begin
2641*16467b97STreehugger Robot   I := FStart.TokenIndex;
2642*16467b97STreehugger Robot   if (FStop.TokenType = TToken.EOF) then
2643*16467b97STreehugger Robot     J := (FInput as ITokenStream).Size
2644*16467b97STreehugger Robot   else
2645*16467b97STreehugger Robot     J := FStop.TokenIndex;
2646*16467b97STreehugger Robot   Result := (FInput as ITokenStream).ToString(I, J);
2647*16467b97STreehugger Robot end;
2648*16467b97STreehugger Robot 
TCommonErrorNode.GetTokenType()2649*16467b97STreehugger Robot function TCommonErrorNode.GetTokenType: Integer;
2650*16467b97STreehugger Robot begin
2651*16467b97STreehugger Robot   Result := TToken.INVALID_TOKEN_TYPE;
2652*16467b97STreehugger Robot end;
2653*16467b97STreehugger Robot 
TCommonErrorNode.ToString()2654*16467b97STreehugger Robot function TCommonErrorNode.ToString: String;
2655*16467b97STreehugger Robot begin
2656*16467b97STreehugger Robot   if (FTrappedException is EMissingTokenException) then
2657*16467b97STreehugger Robot     Result := '<missing type: '
2658*16467b97STreehugger Robot       + IntToStr(EMissingTokenException(FTrappedException).MissingType) + '>'
2659*16467b97STreehugger Robot   else
2660*16467b97STreehugger Robot     if (FTrappedException is EUnwantedTokenException) then
2661*16467b97STreehugger Robot       Result := '<extraneous: '
2662*16467b97STreehugger Robot         + EUnwantedTokenException(FTrappedException).UnexpectedToken.ToString
2663*16467b97STreehugger Robot         + ', resync=' + GetText + '>'
2664*16467b97STreehugger Robot     else
2665*16467b97STreehugger Robot       if (FTrappedException is EMismatchedTokenException) then
2666*16467b97STreehugger Robot         Result := '<mismatched token: ' + FTrappedException.Token.ToString
2667*16467b97STreehugger Robot           + ', resync=' + GetText + '>'
2668*16467b97STreehugger Robot       else
2669*16467b97STreehugger Robot         if (FTrappedException is ENoViableAltException) then
2670*16467b97STreehugger Robot           Result := '<unexpected: ' + FTrappedException.Token.ToString
2671*16467b97STreehugger Robot             + ', resync=' + GetText + '>'
2672*16467b97STreehugger Robot         else
2673*16467b97STreehugger Robot           Result := '<error: ' + GetText + '>';
2674*16467b97STreehugger Robot end;
2675*16467b97STreehugger Robot 
2676*16467b97STreehugger Robot { TBaseTreeAdaptor }
2677*16467b97STreehugger Robot 
2678*16467b97STreehugger Robot procedure TBaseTreeAdaptor.AddChild(const T, Child: IANTLRInterface);
2679*16467b97STreehugger Robot begin
2680*16467b97STreehugger Robot   if Assigned(T) and Assigned(Child) then
2681*16467b97STreehugger Robot     (T as ITree).AddChild(Child as ITree);
2682*16467b97STreehugger Robot end;
2683*16467b97STreehugger Robot 
BecomeRootnull2684*16467b97STreehugger Robot function TBaseTreeAdaptor.BecomeRoot(const NewRoot,
2685*16467b97STreehugger Robot   OldRoot: IANTLRInterface): IANTLRInterface;
2686*16467b97STreehugger Robot var
2687*16467b97STreehugger Robot   NewRootTree, OldRootTree: ITree;
2688*16467b97STreehugger Robot   NC: Integer;
2689*16467b97STreehugger Robot begin
2690*16467b97STreehugger Robot   NewRootTree := NewRoot as ITree;
2691*16467b97STreehugger Robot   OldRootTree := OldRoot as ITree;
2692*16467b97STreehugger Robot   if (OldRoot = nil) then
2693*16467b97STreehugger Robot     Result := NewRoot
2694*16467b97STreehugger Robot   else
2695*16467b97STreehugger Robot   begin
2696*16467b97STreehugger Robot     // handle ^(nil real-node)
2697*16467b97STreehugger Robot     if (NewRootTree.IsNil) then
2698*16467b97STreehugger Robot     begin
2699*16467b97STreehugger Robot       NC := NewRootTree.ChildCount;
2700*16467b97STreehugger Robot       if (NC = 1) then
2701*16467b97STreehugger Robot         NewRootTree := NewRootTree.GetChild(0)
2702*16467b97STreehugger Robot       else
2703*16467b97STreehugger Robot         if (NC > 1) then
2704*16467b97STreehugger Robot           raise Exception.Create('more than one node as root');
2705*16467b97STreehugger Robot     end;
2706*16467b97STreehugger Robot     // add oldRoot to newRoot; AddChild takes care of case where oldRoot
2707*16467b97STreehugger Robot     // is a flat list (i.e., nil-rooted tree).  All children of oldRoot
2708*16467b97STreehugger Robot     // are added to newRoot.
2709*16467b97STreehugger Robot     NewRootTree.AddChild(OldRootTree);
2710*16467b97STreehugger Robot     Result := NewRootTree;
2711*16467b97STreehugger Robot   end;
2712*16467b97STreehugger Robot end;
2713*16467b97STreehugger Robot 
BecomeRootnull2714*16467b97STreehugger Robot function TBaseTreeAdaptor.BecomeRoot(const NewRoot: IToken;
2715*16467b97STreehugger Robot   const OldRoot: IANTLRInterface): IANTLRInterface;
2716*16467b97STreehugger Robot begin
2717*16467b97STreehugger Robot   Result := BecomeRoot(CreateNode(NewRoot), OldRoot);
2718*16467b97STreehugger Robot end;
2719*16467b97STreehugger Robot 
TBaseTreeAdaptor.CreateNode(const TokenType: Integer;2720*16467b97STreehugger Robot function TBaseTreeAdaptor.CreateNode(const TokenType: Integer;
2721*16467b97STreehugger Robot   const FromToken: IToken): IANTLRInterface;
2722*16467b97STreehugger Robot var
2723*16467b97STreehugger Robot   Token: IToken;
2724*16467b97STreehugger Robot begin
2725*16467b97STreehugger Robot   Token := CreateToken(FromToken);
2726*16467b97STreehugger Robot   Token.TokenType := TokenType;
2727*16467b97STreehugger Robot   Result := CreateNode(Token);
2728*16467b97STreehugger Robot end;
2729*16467b97STreehugger Robot 
TBaseTreeAdaptor.CreateNode(const TokenType: Integer;2730*16467b97STreehugger Robot function TBaseTreeAdaptor.CreateNode(const TokenType: Integer;
2731*16467b97STreehugger Robot   const Text: String): IANTLRInterface;
2732*16467b97STreehugger Robot var
2733*16467b97STreehugger Robot   Token: IToken;
2734*16467b97STreehugger Robot begin
2735*16467b97STreehugger Robot   Token := CreateToken(TokenType, Text);
2736*16467b97STreehugger Robot   Result := CreateNode(Token);
2737*16467b97STreehugger Robot end;
2738*16467b97STreehugger Robot 
TBaseTreeAdaptor.CreateNode(const TokenType: Integer;2739*16467b97STreehugger Robot function TBaseTreeAdaptor.CreateNode(const TokenType: Integer;
2740*16467b97STreehugger Robot   const FromToken: IToken; const Text: String): IANTLRInterface;
2741*16467b97STreehugger Robot var
2742*16467b97STreehugger Robot   Token: IToken;
2743*16467b97STreehugger Robot begin
2744*16467b97STreehugger Robot   Token := CreateToken(FromToken);
2745*16467b97STreehugger Robot   Token.TokenType := TokenType;
2746*16467b97STreehugger Robot   Token.Text := Text;
2747*16467b97STreehugger Robot   Result := CreateNode(Token);
2748*16467b97STreehugger Robot end;
2749*16467b97STreehugger Robot 
2750*16467b97STreehugger Robot constructor TBaseTreeAdaptor.Create;
2751*16467b97STreehugger Robot begin
2752*16467b97STreehugger Robot   inherited Create;
2753*16467b97STreehugger Robot   FUniqueNodeID := 1;
2754*16467b97STreehugger Robot end;
2755*16467b97STreehugger Robot 
DeleteChildnull2756*16467b97STreehugger Robot function TBaseTreeAdaptor.DeleteChild(const T: IANTLRInterface;
2757*16467b97STreehugger Robot   const I: Integer): IANTLRInterface;
2758*16467b97STreehugger Robot begin
2759*16467b97STreehugger Robot   Result := (T as ITree).DeleteChild(I);
2760*16467b97STreehugger Robot end;
2761*16467b97STreehugger Robot 
TBaseTreeAdaptor.DupTree(const T,2762*16467b97STreehugger Robot function TBaseTreeAdaptor.DupTree(const T,
2763*16467b97STreehugger Robot   Parent: IANTLRInterface): IANTLRInterface;
2764*16467b97STreehugger Robot var
2765*16467b97STreehugger Robot   I, N: Integer;
2766*16467b97STreehugger Robot   Child, NewSubTree: IANTLRInterface;
2767*16467b97STreehugger Robot begin
2768*16467b97STreehugger Robot   if (T = nil) then
2769*16467b97STreehugger Robot     Result := nil
2770*16467b97STreehugger Robot   else
2771*16467b97STreehugger Robot   begin
2772*16467b97STreehugger Robot     Result := DupNode(T);
2773*16467b97STreehugger Robot     // ensure new subtree root has parent/child index set
2774*16467b97STreehugger Robot     SetChildIdex(Result, GetChildIndex(T));
2775*16467b97STreehugger Robot     SetParent(Result, Parent);
2776*16467b97STreehugger Robot     N := GetChildCount(T);
2777*16467b97STreehugger Robot     for I := 0 to N - 1 do
2778*16467b97STreehugger Robot     begin
2779*16467b97STreehugger Robot       Child := GetChild(T, I);
2780*16467b97STreehugger Robot       NewSubTree := DupTree(Child, T);
2781*16467b97STreehugger Robot       AddChild(Result, NewSubTree);
2782*16467b97STreehugger Robot     end;
2783*16467b97STreehugger Robot   end;
2784*16467b97STreehugger Robot end;
2785*16467b97STreehugger Robot 
TBaseTreeAdaptor.DupTree(const Tree: IANTLRInterface)2786*16467b97STreehugger Robot function TBaseTreeAdaptor.DupTree(const Tree: IANTLRInterface): IANTLRInterface;
2787*16467b97STreehugger Robot begin
2788*16467b97STreehugger Robot   Result := DupTree(Tree, nil);
2789*16467b97STreehugger Robot end;
2790*16467b97STreehugger Robot 
TBaseTreeAdaptor.ErrorNode(const Input: ITokenStream; const Start,2791*16467b97STreehugger Robot function TBaseTreeAdaptor.ErrorNode(const Input: ITokenStream; const Start,
2792*16467b97STreehugger Robot   Stop: IToken; const E: ERecognitionException): IANTLRInterface;
2793*16467b97STreehugger Robot begin
2794*16467b97STreehugger Robot   Result := TCommonErrorNode.Create(Input, Start, Stop, E);
2795*16467b97STreehugger Robot end;
2796*16467b97STreehugger Robot 
TBaseTreeAdaptor.GetChild(const T: IANTLRInterface;2797*16467b97STreehugger Robot function TBaseTreeAdaptor.GetChild(const T: IANTLRInterface;
2798*16467b97STreehugger Robot   const I: Integer): IANTLRInterface;
2799*16467b97STreehugger Robot begin
2800*16467b97STreehugger Robot   Result := (T as ITree).GetChild(I);
2801*16467b97STreehugger Robot end;
2802*16467b97STreehugger Robot 
GetChildCountnull2803*16467b97STreehugger Robot function TBaseTreeAdaptor.GetChildCount(const T: IANTLRInterface): Integer;
2804*16467b97STreehugger Robot begin
2805*16467b97STreehugger Robot   Result := (T as ITree).ChildCount;
2806*16467b97STreehugger Robot end;
2807*16467b97STreehugger Robot 
TBaseTreeAdaptor.GetNilNode()2808*16467b97STreehugger Robot function TBaseTreeAdaptor.GetNilNode: IANTLRInterface;
2809*16467b97STreehugger Robot begin
2810*16467b97STreehugger Robot   Result := CreateNode(nil);
2811*16467b97STreehugger Robot end;
2812*16467b97STreehugger Robot 
GetNodeTextnull2813*16467b97STreehugger Robot function TBaseTreeAdaptor.GetNodeText(const T: IANTLRInterface): String;
2814*16467b97STreehugger Robot begin
2815*16467b97STreehugger Robot   Result := (T as ITree).Text;
2816*16467b97STreehugger Robot end;
2817*16467b97STreehugger Robot 
GetNodeTypenull2818*16467b97STreehugger Robot function TBaseTreeAdaptor.GetNodeType(const T: IANTLRInterface): Integer;
2819*16467b97STreehugger Robot begin
2820*16467b97STreehugger Robot   Result := 0;
2821*16467b97STreehugger Robot end;
2822*16467b97STreehugger Robot 
GetUniqueIDnull2823*16467b97STreehugger Robot function TBaseTreeAdaptor.GetUniqueID(const Node: IANTLRInterface): Integer;
2824*16467b97STreehugger Robot begin
2825*16467b97STreehugger Robot   if (FTreeToUniqueIDMap = nil) then
2826*16467b97STreehugger Robot     FTreeToUniqueIDMap := TDictionary<IANTLRInterface, Integer>.Create;
2827*16467b97STreehugger Robot   if (not FTreeToUniqueIDMap.TryGetValue(Node, Result)) then
2828*16467b97STreehugger Robot   begin
2829*16467b97STreehugger Robot     Result := FUniqueNodeID;
2830*16467b97STreehugger Robot     FTreeToUniqueIDMap[Node] := Result;
2831*16467b97STreehugger Robot     Inc(FUniqueNodeID);
2832*16467b97STreehugger Robot   end;
2833*16467b97STreehugger Robot end;
2834*16467b97STreehugger Robot 
IsNilnull2835*16467b97STreehugger Robot function TBaseTreeAdaptor.IsNil(const Tree: IANTLRInterface): Boolean;
2836*16467b97STreehugger Robot begin
2837*16467b97STreehugger Robot   Result := (Tree as ITree).IsNil;
2838*16467b97STreehugger Robot end;
2839*16467b97STreehugger Robot 
TBaseTreeAdaptor.RulePostProcessing(2840*16467b97STreehugger Robot function TBaseTreeAdaptor.RulePostProcessing(
2841*16467b97STreehugger Robot   const Root: IANTLRInterface): IANTLRInterface;
2842*16467b97STreehugger Robot var
2843*16467b97STreehugger Robot   R: ITree;
2844*16467b97STreehugger Robot begin
2845*16467b97STreehugger Robot   R := Root as ITree;
2846*16467b97STreehugger Robot   if Assigned(R) and (R.IsNil) then
2847*16467b97STreehugger Robot   begin
2848*16467b97STreehugger Robot     if (R.ChildCount = 0) then
2849*16467b97STreehugger Robot       R := nil
2850*16467b97STreehugger Robot     else
2851*16467b97STreehugger Robot       if (R.ChildCount = 1) then
2852*16467b97STreehugger Robot       begin
2853*16467b97STreehugger Robot         R := R.GetChild(0);
2854*16467b97STreehugger Robot         // whoever invokes rule will set parent and child index
2855*16467b97STreehugger Robot         R.Parent := nil;
2856*16467b97STreehugger Robot         R.ChildIndex := -1;
2857*16467b97STreehugger Robot       end;
2858*16467b97STreehugger Robot   end;
2859*16467b97STreehugger Robot   Result := R;
2860*16467b97STreehugger Robot end;
2861*16467b97STreehugger Robot 
2862*16467b97STreehugger Robot procedure TBaseTreeAdaptor.SetChild(const T: IANTLRInterface; const I: Integer;
2863*16467b97STreehugger Robot   const Child: IANTLRInterface);
2864*16467b97STreehugger Robot begin
2865*16467b97STreehugger Robot   (T as ITree).SetChild(I, Child as ITree);
2866*16467b97STreehugger Robot end;
2867*16467b97STreehugger Robot 
2868*16467b97STreehugger Robot procedure TBaseTreeAdaptor.SetNodeText(const T: IANTLRInterface;
2869*16467b97STreehugger Robot   const Text: String);
2870*16467b97STreehugger Robot begin
2871*16467b97STreehugger Robot   raise EInvalidOperation.Create('don''t know enough about Tree node');
2872*16467b97STreehugger Robot end;
2873*16467b97STreehugger Robot 
2874*16467b97STreehugger Robot procedure TBaseTreeAdaptor.SetNodeType(const T: IANTLRInterface;
2875*16467b97STreehugger Robot   const NodeType: Integer);
2876*16467b97STreehugger Robot begin
2877*16467b97STreehugger Robot   raise EInvalidOperation.Create('don''t know enough about Tree node');
2878*16467b97STreehugger Robot end;
2879*16467b97STreehugger Robot 
2880*16467b97STreehugger Robot { TCommonTreeAdaptor }
2881*16467b97STreehugger Robot 
TCommonTreeAdaptor.CreateNode(const Payload: IToken)2882*16467b97STreehugger Robot function TCommonTreeAdaptor.CreateNode(const Payload: IToken): IANTLRInterface;
2883*16467b97STreehugger Robot begin
2884*16467b97STreehugger Robot   Result := TCommonTree.Create(Payload);
2885*16467b97STreehugger Robot end;
2886*16467b97STreehugger Robot 
TCommonTreeAdaptor.CreateToken(const TokenType: Integer;2887*16467b97STreehugger Robot function TCommonTreeAdaptor.CreateToken(const TokenType: Integer;
2888*16467b97STreehugger Robot   const Text: String): IToken;
2889*16467b97STreehugger Robot begin
2890*16467b97STreehugger Robot   Result := TCommonToken.Create(TokenType, Text);
2891*16467b97STreehugger Robot end;
2892*16467b97STreehugger Robot 
TCommonTreeAdaptor.CreateToken(const FromToken: IToken)2893*16467b97STreehugger Robot function TCommonTreeAdaptor.CreateToken(const FromToken: IToken): IToken;
2894*16467b97STreehugger Robot begin
2895*16467b97STreehugger Robot   Result := TCommonToken.Create(FromToken);
2896*16467b97STreehugger Robot end;
2897*16467b97STreehugger Robot 
TCommonTreeAdaptor.DupNode(2898*16467b97STreehugger Robot function TCommonTreeAdaptor.DupNode(
2899*16467b97STreehugger Robot   const TreeNode: IANTLRInterface): IANTLRInterface;
2900*16467b97STreehugger Robot begin
2901*16467b97STreehugger Robot   if (TreeNode = nil) then
2902*16467b97STreehugger Robot     Result := nil
2903*16467b97STreehugger Robot   else
2904*16467b97STreehugger Robot     Result := (TreeNode as ITree).DupNode;
2905*16467b97STreehugger Robot end;
2906*16467b97STreehugger Robot 
TCommonTreeAdaptor.GetChild(const T: IANTLRInterface;2907*16467b97STreehugger Robot function TCommonTreeAdaptor.GetChild(const T: IANTLRInterface;
2908*16467b97STreehugger Robot   const I: Integer): IANTLRInterface;
2909*16467b97STreehugger Robot begin
2910*16467b97STreehugger Robot   if (T = nil) then
2911*16467b97STreehugger Robot     Result := nil
2912*16467b97STreehugger Robot   else
2913*16467b97STreehugger Robot     Result := (T as ITree).GetChild(I);
2914*16467b97STreehugger Robot end;
2915*16467b97STreehugger Robot 
GetChildCountnull2916*16467b97STreehugger Robot function TCommonTreeAdaptor.GetChildCount(const T: IANTLRInterface): Integer;
2917*16467b97STreehugger Robot begin
2918*16467b97STreehugger Robot   if (T = nil) then
2919*16467b97STreehugger Robot     Result := 0
2920*16467b97STreehugger Robot   else
2921*16467b97STreehugger Robot     Result := (T as ITree).ChildCount;
2922*16467b97STreehugger Robot end;
2923*16467b97STreehugger Robot 
GetChildIndexnull2924*16467b97STreehugger Robot function TCommonTreeAdaptor.GetChildIndex(const T: IANTLRInterface): Integer;
2925*16467b97STreehugger Robot begin
2926*16467b97STreehugger Robot   Result := (T as ITree).ChildIndex;
2927*16467b97STreehugger Robot end;
2928*16467b97STreehugger Robot 
TCommonTreeAdaptor.GetNodeText(const T: IANTLRInterface)2929*16467b97STreehugger Robot function TCommonTreeAdaptor.GetNodeText(const T: IANTLRInterface): String;
2930*16467b97STreehugger Robot begin
2931*16467b97STreehugger Robot   if (T = nil) then
2932*16467b97STreehugger Robot     Result := ''
2933*16467b97STreehugger Robot   else
2934*16467b97STreehugger Robot     Result := (T as ITree).Text;
2935*16467b97STreehugger Robot end;
2936*16467b97STreehugger Robot 
TCommonTreeAdaptor.GetNodeType(const T: IANTLRInterface)2937*16467b97STreehugger Robot function TCommonTreeAdaptor.GetNodeType(const T: IANTLRInterface): Integer;
2938*16467b97STreehugger Robot begin
2939*16467b97STreehugger Robot   if (T = nil) then
2940*16467b97STreehugger Robot     Result := TToken.INVALID_TOKEN_TYPE
2941*16467b97STreehugger Robot   else
2942*16467b97STreehugger Robot     Result := (T as ITree).TokenType;
2943*16467b97STreehugger Robot end;
2944*16467b97STreehugger Robot 
GetParentnull2945*16467b97STreehugger Robot function TCommonTreeAdaptor.GetParent(
2946*16467b97STreehugger Robot   const T: IANTLRInterface): IANTLRInterface;
2947*16467b97STreehugger Robot begin
2948*16467b97STreehugger Robot   Result := (T as ITree).Parent;
2949*16467b97STreehugger Robot end;
2950*16467b97STreehugger Robot 
TCommonTreeAdaptor.GetToken(const TreeNode: IANTLRInterface)2951*16467b97STreehugger Robot function TCommonTreeAdaptor.GetToken(const TreeNode: IANTLRInterface): IToken;
2952*16467b97STreehugger Robot var
2953*16467b97STreehugger Robot   CommonTree: ICommonTree;
2954*16467b97STreehugger Robot begin
2955*16467b97STreehugger Robot   if Supports(TreeNode, ICommonTree, CommonTree) then
2956*16467b97STreehugger Robot     Result := CommonTree.Token
2957*16467b97STreehugger Robot   else
2958*16467b97STreehugger Robot     Result := nil; // no idea what to do
2959*16467b97STreehugger Robot end;
2960*16467b97STreehugger Robot 
TCommonTreeAdaptor.GetTokenStartIndex(2961*16467b97STreehugger Robot function TCommonTreeAdaptor.GetTokenStartIndex(
2962*16467b97STreehugger Robot   const T: IANTLRInterface): Integer;
2963*16467b97STreehugger Robot begin
2964*16467b97STreehugger Robot   if (T = nil) then
2965*16467b97STreehugger Robot     Result := -1
2966*16467b97STreehugger Robot   else
2967*16467b97STreehugger Robot     Result := (T as ITree).TokenStartIndex;
2968*16467b97STreehugger Robot end;
2969*16467b97STreehugger Robot 
TCommonTreeAdaptor.GetTokenStopIndex(2970*16467b97STreehugger Robot function TCommonTreeAdaptor.GetTokenStopIndex(
2971*16467b97STreehugger Robot   const T: IANTLRInterface): Integer;
2972*16467b97STreehugger Robot begin
2973*16467b97STreehugger Robot   if (T = nil) then
2974*16467b97STreehugger Robot     Result := -1
2975*16467b97STreehugger Robot   else
2976*16467b97STreehugger Robot     Result := (T as ITree).TokenStopIndex;
2977*16467b97STreehugger Robot end;
2978*16467b97STreehugger Robot 
2979*16467b97STreehugger Robot procedure TCommonTreeAdaptor.ReplaceChildren(const Parent: IANTLRInterface;
2980*16467b97STreehugger Robot   const StartChildIndex, StopChildIndex: Integer; const T: IANTLRInterface);
2981*16467b97STreehugger Robot begin
2982*16467b97STreehugger Robot   if Assigned(Parent) then
2983*16467b97STreehugger Robot     (Parent as ITree).ReplaceChildren(StartChildIndex, StopChildIndex, T);
2984*16467b97STreehugger Robot end;
2985*16467b97STreehugger Robot 
2986*16467b97STreehugger Robot procedure TCommonTreeAdaptor.SetChildIdex(const T: IANTLRInterface;
2987*16467b97STreehugger Robot   const Index: Integer);
2988*16467b97STreehugger Robot begin
2989*16467b97STreehugger Robot   (T as ITree).ChildIndex := Index;
2990*16467b97STreehugger Robot end;
2991*16467b97STreehugger Robot 
2992*16467b97STreehugger Robot procedure TCommonTreeAdaptor.SetParent(const T, Parent: IANTLRInterface);
2993*16467b97STreehugger Robot begin
2994*16467b97STreehugger Robot   (T as ITree).Parent := (Parent as ITree);
2995*16467b97STreehugger Robot end;
2996*16467b97STreehugger Robot 
2997*16467b97STreehugger Robot procedure TCommonTreeAdaptor.SetTokenBoundaries(const T: IANTLRInterface;
2998*16467b97STreehugger Robot   const StartToken, StopToken: IToken);
2999*16467b97STreehugger Robot var
3000*16467b97STreehugger Robot   Start, Stop: Integer;
3001*16467b97STreehugger Robot begin
3002*16467b97STreehugger Robot   if Assigned(T) then
3003*16467b97STreehugger Robot   begin
3004*16467b97STreehugger Robot     if Assigned(StartToken) then
3005*16467b97STreehugger Robot       Start := StartToken.TokenIndex
3006*16467b97STreehugger Robot     else
3007*16467b97STreehugger Robot       Start := 0;
3008*16467b97STreehugger Robot 
3009*16467b97STreehugger Robot     if Assigned(StopToken) then
3010*16467b97STreehugger Robot       Stop := StopToken.TokenIndex
3011*16467b97STreehugger Robot     else
3012*16467b97STreehugger Robot       Stop := 0;
3013*16467b97STreehugger Robot 
3014*16467b97STreehugger Robot     (T as ITree).TokenStartIndex := Start;
3015*16467b97STreehugger Robot     (T as ITree).TokenStopIndex := Stop;
3016*16467b97STreehugger Robot   end;
3017*16467b97STreehugger Robot end;
3018*16467b97STreehugger Robot 
3019*16467b97STreehugger Robot { TCommonTreeNodeStream }
3020*16467b97STreehugger Robot 
3021*16467b97STreehugger Robot procedure TCommonTreeNodeStream.AddNavigationNode(const TokenType: Integer);
3022*16467b97STreehugger Robot var
3023*16467b97STreehugger Robot   NavNode: IANTLRInterface;
3024*16467b97STreehugger Robot begin
3025*16467b97STreehugger Robot   if (TokenType = TToken.DOWN) then
3026*16467b97STreehugger Robot   begin
3027*16467b97STreehugger Robot     if (GetHasUniqueNavigationNodes) then
3028*16467b97STreehugger Robot       NavNode := FAdaptor.CreateNode(TToken.DOWN, 'DOWN')
3029*16467b97STreehugger Robot     else
3030*16467b97STreehugger Robot       NavNode := FDown;
3031*16467b97STreehugger Robot   end
3032*16467b97STreehugger Robot   else
3033*16467b97STreehugger Robot   begin
3034*16467b97STreehugger Robot     if (GetHasUniqueNavigationNodes) then
3035*16467b97STreehugger Robot       NavNode := FAdaptor.CreateNode(TToken.UP, 'UP')
3036*16467b97STreehugger Robot     else
3037*16467b97STreehugger Robot       NavNode := FUp;
3038*16467b97STreehugger Robot   end;
3039*16467b97STreehugger Robot   FNodes.Add(NavNode);
3040*16467b97STreehugger Robot end;
3041*16467b97STreehugger Robot 
3042*16467b97STreehugger Robot procedure TCommonTreeNodeStream.Consume;
3043*16467b97STreehugger Robot begin
3044*16467b97STreehugger Robot   if (FP = -1) then
3045*16467b97STreehugger Robot     FillBuffer;
3046*16467b97STreehugger Robot   Inc(FP);
3047*16467b97STreehugger Robot end;
3048*16467b97STreehugger Robot 
3049*16467b97STreehugger Robot constructor TCommonTreeNodeStream.Create;
3050*16467b97STreehugger Robot begin
3051*16467b97STreehugger Robot   inherited;
3052*16467b97STreehugger Robot   FP := -1;
3053*16467b97STreehugger Robot end;
3054*16467b97STreehugger Robot 
3055*16467b97STreehugger Robot constructor TCommonTreeNodeStream.Create(const ATree: IANTLRInterface);
3056*16467b97STreehugger Robot begin
3057*16467b97STreehugger Robot   Create(TCommonTreeAdaptor.Create, ATree);
3058*16467b97STreehugger Robot end;
3059*16467b97STreehugger Robot 
3060*16467b97STreehugger Robot constructor TCommonTreeNodeStream.Create(const AAdaptor: ITreeAdaptor;
3061*16467b97STreehugger Robot   const ATree: IANTLRInterface);
3062*16467b97STreehugger Robot begin
3063*16467b97STreehugger Robot   Create(AAdaptor, ATree, DEFAULT_INITIAL_BUFFER_SIZE);
3064*16467b97STreehugger Robot end;
3065*16467b97STreehugger Robot 
3066*16467b97STreehugger Robot constructor TCommonTreeNodeStream.Create(const AAdaptor: ITreeAdaptor;
3067*16467b97STreehugger Robot   const ATree: IANTLRInterface; const AInitialBufferSize: Integer);
3068*16467b97STreehugger Robot begin
3069*16467b97STreehugger Robot   Create;
3070*16467b97STreehugger Robot   FRoot := ATree;
3071*16467b97STreehugger Robot   FAdaptor := AAdaptor;
3072*16467b97STreehugger Robot   FNodes := TList<IANTLRInterface>.Create;
3073*16467b97STreehugger Robot   FNodes.Capacity := AInitialBufferSize;
3074*16467b97STreehugger Robot   FDown := FAdaptor.CreateNode(TToken.DOWN, 'DOWN');
3075*16467b97STreehugger Robot   FUp := FAdaptor.CreateNode(TToken.UP, 'UP');
3076*16467b97STreehugger Robot   FEof := FAdaptor.CreateNode(TToken.EOF, 'EOF');
3077*16467b97STreehugger Robot end;
3078*16467b97STreehugger Robot 
3079*16467b97STreehugger Robot procedure TCommonTreeNodeStream.FillBuffer;
3080*16467b97STreehugger Robot begin
3081*16467b97STreehugger Robot   FillBuffer(FRoot);
3082*16467b97STreehugger Robot   FP := 0; // buffer of nodes intialized now
3083*16467b97STreehugger Robot end;
3084*16467b97STreehugger Robot 
3085*16467b97STreehugger Robot procedure TCommonTreeNodeStream.FillBuffer(const T: IANTLRInterface);
3086*16467b97STreehugger Robot var
3087*16467b97STreehugger Robot   IsNil: Boolean;
3088*16467b97STreehugger Robot   C, N: Integer;
3089*16467b97STreehugger Robot begin
3090*16467b97STreehugger Robot   IsNil := FAdaptor.IsNil(T);
3091*16467b97STreehugger Robot   if (not IsNil) then
3092*16467b97STreehugger Robot     FNodes.Add(T); // add this node
3093*16467b97STreehugger Robot 
3094*16467b97STreehugger Robot   // add DOWN node if t has children
3095*16467b97STreehugger Robot   N := FAdaptor.GetChildCount(T);
3096*16467b97STreehugger Robot   if (not IsNil) and (N > 0) then
3097*16467b97STreehugger Robot     AddNavigationNode(TToken.DOWN);
3098*16467b97STreehugger Robot 
3099*16467b97STreehugger Robot   // and now add all its children
3100*16467b97STreehugger Robot   for C := 0 to N - 1 do
3101*16467b97STreehugger Robot     FillBuffer(FAdaptor.GetChild(T, C));
3102*16467b97STreehugger Robot 
3103*16467b97STreehugger Robot   // add UP node if t has children
3104*16467b97STreehugger Robot   if (not IsNil) and (N > 0) then
3105*16467b97STreehugger Robot     AddNavigationNode(TToken.UP);
3106*16467b97STreehugger Robot end;
3107*16467b97STreehugger Robot 
TCommonTreeNodeStream.Get(const I: Integer)3108*16467b97STreehugger Robot function TCommonTreeNodeStream.Get(const I: Integer): IANTLRInterface;
3109*16467b97STreehugger Robot begin
3110*16467b97STreehugger Robot   if (FP = -1) then
3111*16467b97STreehugger Robot     FillBuffer;
3112*16467b97STreehugger Robot   Result := FNodes[I];
3113*16467b97STreehugger Robot end;
3114*16467b97STreehugger Robot 
TCommonTreeNodeStream.GetCurrentSymbol()3115*16467b97STreehugger Robot function TCommonTreeNodeStream.GetCurrentSymbol: IANTLRInterface;
3116*16467b97STreehugger Robot begin
3117*16467b97STreehugger Robot   Result := LT(1);
3118*16467b97STreehugger Robot end;
3119*16467b97STreehugger Robot 
GetHasUniqueNavigationNodesnull3120*16467b97STreehugger Robot function TCommonTreeNodeStream.GetHasUniqueNavigationNodes: Boolean;
3121*16467b97STreehugger Robot begin
3122*16467b97STreehugger Robot   Result := FUniqueNavigationNodes;
3123*16467b97STreehugger Robot end;
3124*16467b97STreehugger Robot 
TCommonTreeNodeStream.GetNodeIndex(3125*16467b97STreehugger Robot function TCommonTreeNodeStream.GetNodeIndex(
3126*16467b97STreehugger Robot   const Node: IANTLRInterface): Integer;
3127*16467b97STreehugger Robot var
3128*16467b97STreehugger Robot   T: IANTLRInterface;
3129*16467b97STreehugger Robot begin
3130*16467b97STreehugger Robot   if (FP = -1) then
3131*16467b97STreehugger Robot     FillBuffer;
3132*16467b97STreehugger Robot   for Result := 0 to FNodes.Count - 1 do
3133*16467b97STreehugger Robot   begin
3134*16467b97STreehugger Robot     T := FNodes[Result];
3135*16467b97STreehugger Robot     if (T = Node) then
3136*16467b97STreehugger Robot       Exit;
3137*16467b97STreehugger Robot   end;
3138*16467b97STreehugger Robot   Result := -1;
3139*16467b97STreehugger Robot end;
3140*16467b97STreehugger Robot 
GetSourceNamenull3141*16467b97STreehugger Robot function TCommonTreeNodeStream.GetSourceName: String;
3142*16467b97STreehugger Robot begin
3143*16467b97STreehugger Robot   Result := GetTokenStream.SourceName;
3144*16467b97STreehugger Robot end;
3145*16467b97STreehugger Robot 
TCommonTreeNodeStream.GetTokenStream()3146*16467b97STreehugger Robot function TCommonTreeNodeStream.GetTokenStream: ITokenStream;
3147*16467b97STreehugger Robot begin
3148*16467b97STreehugger Robot   Result := FTokens;
3149*16467b97STreehugger Robot end;
3150*16467b97STreehugger Robot 
TCommonTreeNodeStream.GetTreeAdaptor()3151*16467b97STreehugger Robot function TCommonTreeNodeStream.GetTreeAdaptor: ITreeAdaptor;
3152*16467b97STreehugger Robot begin
3153*16467b97STreehugger Robot   Result := FAdaptor;
3154*16467b97STreehugger Robot end;
3155*16467b97STreehugger Robot 
TCommonTreeNodeStream.GetTreeSource()3156*16467b97STreehugger Robot function TCommonTreeNodeStream.GetTreeSource: IANTLRInterface;
3157*16467b97STreehugger Robot begin
3158*16467b97STreehugger Robot   Result := FRoot;
3159*16467b97STreehugger Robot end;
3160*16467b97STreehugger Robot 
Indexnull3161*16467b97STreehugger Robot function TCommonTreeNodeStream.Index: Integer;
3162*16467b97STreehugger Robot begin
3163*16467b97STreehugger Robot   Result := FP;
3164*16467b97STreehugger Robot end;
3165*16467b97STreehugger Robot 
LAnull3166*16467b97STreehugger Robot function TCommonTreeNodeStream.LA(I: Integer): Integer;
3167*16467b97STreehugger Robot begin
3168*16467b97STreehugger Robot   Result := FAdaptor.GetNodeType(LT(I));
3169*16467b97STreehugger Robot end;
3170*16467b97STreehugger Robot 
TCommonTreeNodeStream.LAChar(I: Integer)3171*16467b97STreehugger Robot function TCommonTreeNodeStream.LAChar(I: Integer): Char;
3172*16467b97STreehugger Robot begin
3173*16467b97STreehugger Robot   Result := Char(LA(I));
3174*16467b97STreehugger Robot end;
3175*16467b97STreehugger Robot 
LBnull3176*16467b97STreehugger Robot function TCommonTreeNodeStream.LB(const K: Integer): IANTLRInterface;
3177*16467b97STreehugger Robot begin
3178*16467b97STreehugger Robot   if (K = 0) then
3179*16467b97STreehugger Robot     Result := nil
3180*16467b97STreehugger Robot   else
3181*16467b97STreehugger Robot     if ((FP - K) < 0) then
3182*16467b97STreehugger Robot       Result := nil
3183*16467b97STreehugger Robot     else
3184*16467b97STreehugger Robot       Result := FNodes[FP - K];
3185*16467b97STreehugger Robot end;
3186*16467b97STreehugger Robot 
LTnull3187*16467b97STreehugger Robot function TCommonTreeNodeStream.LT(const K: Integer): IANTLRInterface;
3188*16467b97STreehugger Robot begin
3189*16467b97STreehugger Robot   if (FP = -1) then
3190*16467b97STreehugger Robot     FillBuffer;
3191*16467b97STreehugger Robot   if (K = 0) then
3192*16467b97STreehugger Robot     Result := nil
3193*16467b97STreehugger Robot   else
3194*16467b97STreehugger Robot     if (K < 0) then
3195*16467b97STreehugger Robot       Result := LB(-K)
3196*16467b97STreehugger Robot     else
3197*16467b97STreehugger Robot       if ((FP + K - 1) >= FNodes.Count) then
3198*16467b97STreehugger Robot         Result := FEof
3199*16467b97STreehugger Robot       else
3200*16467b97STreehugger Robot         Result := FNodes[FP + K - 1];
3201*16467b97STreehugger Robot end;
3202*16467b97STreehugger Robot 
TCommonTreeNodeStream.Mark()3203*16467b97STreehugger Robot function TCommonTreeNodeStream.Mark: Integer;
3204*16467b97STreehugger Robot begin
3205*16467b97STreehugger Robot   if (FP = -1) then
3206*16467b97STreehugger Robot     FillBuffer;
3207*16467b97STreehugger Robot   FLastMarker := Index;
3208*16467b97STreehugger Robot   Result := FLastMarker;
3209*16467b97STreehugger Robot end;
3210*16467b97STreehugger Robot 
Popnull3211*16467b97STreehugger Robot function TCommonTreeNodeStream.Pop: Integer;
3212*16467b97STreehugger Robot begin
3213*16467b97STreehugger Robot   Result := FCalls.Pop;
3214*16467b97STreehugger Robot   Seek(Result);
3215*16467b97STreehugger Robot end;
3216*16467b97STreehugger Robot 
3217*16467b97STreehugger Robot procedure TCommonTreeNodeStream.Push(const Index: Integer);
3218*16467b97STreehugger Robot begin
3219*16467b97STreehugger Robot   if (FCalls = nil) then
3220*16467b97STreehugger Robot     FCalls := TStackList<Integer>.Create;
3221*16467b97STreehugger Robot   FCalls.Push(FP); // save current index
3222*16467b97STreehugger Robot   Seek(Index);
3223*16467b97STreehugger Robot end;
3224*16467b97STreehugger Robot 
3225*16467b97STreehugger Robot procedure TCommonTreeNodeStream.Release(const Marker: Integer);
3226*16467b97STreehugger Robot begin
3227*16467b97STreehugger Robot   // no resources to release
3228*16467b97STreehugger Robot end;
3229*16467b97STreehugger Robot 
3230*16467b97STreehugger Robot procedure TCommonTreeNodeStream.ReplaceChildren(const Parent: IANTLRInterface;
3231*16467b97STreehugger Robot   const StartChildIndex, StopChildIndex: Integer; const T: IANTLRInterface);
3232*16467b97STreehugger Robot begin
3233*16467b97STreehugger Robot   if Assigned(Parent) then
3234*16467b97STreehugger Robot     FAdaptor.ReplaceChildren(Parent, StartChildIndex, StopChildIndex, T);
3235*16467b97STreehugger Robot end;
3236*16467b97STreehugger Robot 
3237*16467b97STreehugger Robot procedure TCommonTreeNodeStream.Reset;
3238*16467b97STreehugger Robot begin
3239*16467b97STreehugger Robot   FP := -1;
3240*16467b97STreehugger Robot   FLastMarker := 0;
3241*16467b97STreehugger Robot   if Assigned(FCalls) then
3242*16467b97STreehugger Robot     FCalls.Clear;
3243*16467b97STreehugger Robot end;
3244*16467b97STreehugger Robot 
3245*16467b97STreehugger Robot procedure TCommonTreeNodeStream.Rewind(const Marker: Integer);
3246*16467b97STreehugger Robot begin
3247*16467b97STreehugger Robot   Seek(Marker);
3248*16467b97STreehugger Robot end;
3249*16467b97STreehugger Robot 
3250*16467b97STreehugger Robot procedure TCommonTreeNodeStream.Rewind;
3251*16467b97STreehugger Robot begin
3252*16467b97STreehugger Robot   Seek(FLastMarker);
3253*16467b97STreehugger Robot end;
3254*16467b97STreehugger Robot 
3255*16467b97STreehugger Robot procedure TCommonTreeNodeStream.Seek(const Index: Integer);
3256*16467b97STreehugger Robot begin
3257*16467b97STreehugger Robot   if (FP = -1) then
3258*16467b97STreehugger Robot     FillBuffer;
3259*16467b97STreehugger Robot   FP := Index;
3260*16467b97STreehugger Robot end;
3261*16467b97STreehugger Robot 
3262*16467b97STreehugger Robot procedure TCommonTreeNodeStream.SetHasUniqueNavigationNodes(
3263*16467b97STreehugger Robot   const Value: Boolean);
3264*16467b97STreehugger Robot begin
3265*16467b97STreehugger Robot   FUniqueNavigationNodes := Value;
3266*16467b97STreehugger Robot end;
3267*16467b97STreehugger Robot 
3268*16467b97STreehugger Robot procedure TCommonTreeNodeStream.SetTokenStream(const Value: ITokenStream);
3269*16467b97STreehugger Robot begin
3270*16467b97STreehugger Robot   FTokens := Value;
3271*16467b97STreehugger Robot end;
3272*16467b97STreehugger Robot 
3273*16467b97STreehugger Robot procedure TCommonTreeNodeStream.SetTreeAdaptor(const Value: ITreeAdaptor);
3274*16467b97STreehugger Robot begin
3275*16467b97STreehugger Robot   FAdaptor := Value;
3276*16467b97STreehugger Robot end;
3277*16467b97STreehugger Robot 
Sizenull3278*16467b97STreehugger Robot function TCommonTreeNodeStream.Size: Integer;
3279*16467b97STreehugger Robot begin
3280*16467b97STreehugger Robot   if (FP = -1) then
3281*16467b97STreehugger Robot     FillBuffer;
3282*16467b97STreehugger Robot   Result := FNodes.Count;
3283*16467b97STreehugger Robot end;
3284*16467b97STreehugger Robot 
TCommonTreeNodeStream.ToString(const Start,3285*16467b97STreehugger Robot function TCommonTreeNodeStream.ToString(const Start,
3286*16467b97STreehugger Robot   Stop: IANTLRInterface): String;
3287*16467b97STreehugger Robot var
3288*16467b97STreehugger Robot   CommonTree: ICommonTree;
3289*16467b97STreehugger Robot   I, BeginTokenIndex, EndTokenIndex: Integer;
3290*16467b97STreehugger Robot   T: IANTLRInterface;
3291*16467b97STreehugger Robot   Buf: TStringBuilder;
3292*16467b97STreehugger Robot   Text: String;
3293*16467b97STreehugger Robot begin
3294*16467b97STreehugger Robot   WriteLn('ToString');
3295*16467b97STreehugger Robot   if (Start = nil) or (Stop = nil) then
3296*16467b97STreehugger Robot     Exit;
3297*16467b97STreehugger Robot   if (FP = -1) then
3298*16467b97STreehugger Robot     FillBuffer;
3299*16467b97STreehugger Robot 
3300*16467b97STreehugger Robot   if Supports(Start, ICommonTree, CommonTree) then
3301*16467b97STreehugger Robot     Write('ToString: ' + CommonTree.Token.ToString + ', ')
3302*16467b97STreehugger Robot   else
3303*16467b97STreehugger Robot     WriteLn(Start.ToString);
3304*16467b97STreehugger Robot 
3305*16467b97STreehugger Robot   if Supports(Stop, ICommonTree, CommonTree) then
3306*16467b97STreehugger Robot     WriteLn(CommonTree.Token.ToString)
3307*16467b97STreehugger Robot   else
3308*16467b97STreehugger Robot     WriteLn(Stop.ToString);
3309*16467b97STreehugger Robot 
3310*16467b97STreehugger Robot   // if we have the token stream, use that to dump text in order
3311*16467b97STreehugger Robot   if Assigned(FTokens) then
3312*16467b97STreehugger Robot   begin
3313*16467b97STreehugger Robot     BeginTokenIndex := FAdaptor.GetTokenStartIndex(Start);
3314*16467b97STreehugger Robot     EndTokenIndex := FAdaptor.GetTokenStartIndex(Stop);
3315*16467b97STreehugger Robot     // if it's a tree, use start/stop index from start node
3316*16467b97STreehugger Robot     // else use token range from start/stop nodes
3317*16467b97STreehugger Robot     if (FAdaptor.GetNodeType(Stop) = TToken.UP) then
3318*16467b97STreehugger Robot       EndTokenIndex := FAdaptor.GetTokenStopIndex(Start)
3319*16467b97STreehugger Robot     else
3320*16467b97STreehugger Robot       if (FAdaptor.GetNodeType(Stop) = TToken.EOF) then
3321*16467b97STreehugger Robot         EndTokenIndex := Size - 2; // don't use EOF
3322*16467b97STreehugger Robot     Result := FTokens.ToString(BeginTokenIndex, EndTokenIndex);
3323*16467b97STreehugger Robot     Exit;
3324*16467b97STreehugger Robot   end;
3325*16467b97STreehugger Robot 
3326*16467b97STreehugger Robot   // walk nodes looking for start
3327*16467b97STreehugger Robot   T := nil;
3328*16467b97STreehugger Robot   I := 0;
3329*16467b97STreehugger Robot   while (I < FNodes.Count) do
3330*16467b97STreehugger Robot   begin
3331*16467b97STreehugger Robot     T := FNodes[I];
3332*16467b97STreehugger Robot     if SameObj(T, Start) then
3333*16467b97STreehugger Robot       Break;
3334*16467b97STreehugger Robot     Inc(I);
3335*16467b97STreehugger Robot   end;
3336*16467b97STreehugger Robot 
3337*16467b97STreehugger Robot   // now walk until we see stop, filling string buffer with text
3338*16467b97STreehugger Robot   Buf := TStringBuilder.Create;
3339*16467b97STreehugger Robot   try
3340*16467b97STreehugger Robot     T := FNodes[I];
3341*16467b97STreehugger Robot     while (T <> Stop) do
3342*16467b97STreehugger Robot     begin
3343*16467b97STreehugger Robot       Text := FAdaptor.GetNodeText(T);
3344*16467b97STreehugger Robot       if (Text = '') then
3345*16467b97STreehugger Robot         Text := ' ' + IntToStr(FAdaptor.GetNodeType(T));
3346*16467b97STreehugger Robot       Buf.Append(Text);
3347*16467b97STreehugger Robot       Inc(I);
3348*16467b97STreehugger Robot       T := FNodes[I];
3349*16467b97STreehugger Robot     end;
3350*16467b97STreehugger Robot 
3351*16467b97STreehugger Robot     // include stop node too
3352*16467b97STreehugger Robot     Text := FAdaptor.GetNodeText(Stop);
3353*16467b97STreehugger Robot     if (Text = '') then
3354*16467b97STreehugger Robot       Text := ' ' + IntToStr(FAdaptor.GetNodeType(Stop));
3355*16467b97STreehugger Robot     Buf.Append(Text);
3356*16467b97STreehugger Robot     Result := Buf.ToString;
3357*16467b97STreehugger Robot   finally
3358*16467b97STreehugger Robot     Buf.Free;
3359*16467b97STreehugger Robot   end;
3360*16467b97STreehugger Robot end;
3361*16467b97STreehugger Robot 
TCommonTreeNodeStream.ToString()3362*16467b97STreehugger Robot function TCommonTreeNodeStream.ToString: String;
3363*16467b97STreehugger Robot var
3364*16467b97STreehugger Robot   Buf: TStringBuilder;
3365*16467b97STreehugger Robot   T: IANTLRInterface;
3366*16467b97STreehugger Robot begin
3367*16467b97STreehugger Robot   if (FP = -1) then
3368*16467b97STreehugger Robot     FillBuffer;
3369*16467b97STreehugger Robot   Buf := TStringBuilder.Create;
3370*16467b97STreehugger Robot   try
3371*16467b97STreehugger Robot     for T in FNodes do
3372*16467b97STreehugger Robot     begin
3373*16467b97STreehugger Robot       Buf.Append(' ');
3374*16467b97STreehugger Robot       Buf.Append(FAdaptor.GetNodeType(T));
3375*16467b97STreehugger Robot     end;
3376*16467b97STreehugger Robot     Result := Buf.ToString;
3377*16467b97STreehugger Robot   finally
3378*16467b97STreehugger Robot     Buf.Free;
3379*16467b97STreehugger Robot   end;
3380*16467b97STreehugger Robot end;
3381*16467b97STreehugger Robot 
TCommonTreeNodeStream.ToTokenString(const Start,3382*16467b97STreehugger Robot function TCommonTreeNodeStream.ToTokenString(const Start,
3383*16467b97STreehugger Robot   Stop: Integer): String;
3384*16467b97STreehugger Robot var
3385*16467b97STreehugger Robot   I: Integer;
3386*16467b97STreehugger Robot   T: IANTLRInterface;
3387*16467b97STreehugger Robot   Buf: TStringBuilder;
3388*16467b97STreehugger Robot begin
3389*16467b97STreehugger Robot   if (FP = -1) then
3390*16467b97STreehugger Robot     FillBuffer;
3391*16467b97STreehugger Robot   Buf := TStringBuilder.Create;
3392*16467b97STreehugger Robot   try
3393*16467b97STreehugger Robot     for I := Stop to Min(FNodes.Count - 1, Stop) do
3394*16467b97STreehugger Robot     begin
3395*16467b97STreehugger Robot       T := FNodes[I];
3396*16467b97STreehugger Robot       Buf.Append(' ');
3397*16467b97STreehugger Robot       Buf.Append(FAdaptor.GetToken(T).ToString);
3398*16467b97STreehugger Robot     end;
3399*16467b97STreehugger Robot 
3400*16467b97STreehugger Robot     Result := Buf.ToString;
3401*16467b97STreehugger Robot   finally
3402*16467b97STreehugger Robot     Buf.Free;
3403*16467b97STreehugger Robot   end;
3404*16467b97STreehugger Robot end;
3405*16467b97STreehugger Robot 
3406*16467b97STreehugger Robot { TParseTree }
3407*16467b97STreehugger Robot 
3408*16467b97STreehugger Robot constructor TParseTree.Create(const ALabel: IANTLRInterface);
3409*16467b97STreehugger Robot begin
3410*16467b97STreehugger Robot   inherited Create;
3411*16467b97STreehugger Robot   FPayload := ALabel;
3412*16467b97STreehugger Robot end;
3413*16467b97STreehugger Robot 
TParseTree.DupNode()3414*16467b97STreehugger Robot function TParseTree.DupNode: ITree;
3415*16467b97STreehugger Robot begin
3416*16467b97STreehugger Robot   Result := nil;
3417*16467b97STreehugger Robot end;
3418*16467b97STreehugger Robot 
TParseTree.GetText()3419*16467b97STreehugger Robot function TParseTree.GetText: String;
3420*16467b97STreehugger Robot begin
3421*16467b97STreehugger Robot   Result := ToString;
3422*16467b97STreehugger Robot end;
3423*16467b97STreehugger Robot 
GetTokenStartIndexnull3424*16467b97STreehugger Robot function TParseTree.GetTokenStartIndex: Integer;
3425*16467b97STreehugger Robot begin
3426*16467b97STreehugger Robot   Result := 0;
3427*16467b97STreehugger Robot end;
3428*16467b97STreehugger Robot 
TParseTree.GetTokenStopIndex()3429*16467b97STreehugger Robot function TParseTree.GetTokenStopIndex: Integer;
3430*16467b97STreehugger Robot begin
3431*16467b97STreehugger Robot   Result := 0;
3432*16467b97STreehugger Robot end;
3433*16467b97STreehugger Robot 
GetTokenTypenull3434*16467b97STreehugger Robot function TParseTree.GetTokenType: Integer;
3435*16467b97STreehugger Robot begin
3436*16467b97STreehugger Robot   Result := 0;
3437*16467b97STreehugger Robot end;
3438*16467b97STreehugger Robot 
3439*16467b97STreehugger Robot procedure TParseTree.SetTokenStartIndex(const Value: Integer);
3440*16467b97STreehugger Robot begin
3441*16467b97STreehugger Robot   // No implementation
3442*16467b97STreehugger Robot end;
3443*16467b97STreehugger Robot 
3444*16467b97STreehugger Robot procedure TParseTree.SetTokenStopIndex(const Value: Integer);
3445*16467b97STreehugger Robot begin
3446*16467b97STreehugger Robot   // No implementation
3447*16467b97STreehugger Robot end;
3448*16467b97STreehugger Robot 
ToInputStringnull3449*16467b97STreehugger Robot function TParseTree.ToInputString: String;
3450*16467b97STreehugger Robot var
3451*16467b97STreehugger Robot   Buf: TStringBuilder;
3452*16467b97STreehugger Robot begin
3453*16467b97STreehugger Robot   Buf := TStringBuilder.Create;
3454*16467b97STreehugger Robot   try
3455*16467b97STreehugger Robot     _ToStringLeaves(Buf);
3456*16467b97STreehugger Robot     Result := Buf.ToString;
3457*16467b97STreehugger Robot   finally
3458*16467b97STreehugger Robot     Buf.Free;
3459*16467b97STreehugger Robot   end;
3460*16467b97STreehugger Robot end;
3461*16467b97STreehugger Robot 
TParseTree.ToString()3462*16467b97STreehugger Robot function TParseTree.ToString: String;
3463*16467b97STreehugger Robot var
3464*16467b97STreehugger Robot   T: IToken;
3465*16467b97STreehugger Robot begin
3466*16467b97STreehugger Robot   if Supports(FPayload, IToken, T) then
3467*16467b97STreehugger Robot   begin
3468*16467b97STreehugger Robot     if (T.TokenType = TToken.EOF) then
3469*16467b97STreehugger Robot       Result := '<EOF>'
3470*16467b97STreehugger Robot     else
3471*16467b97STreehugger Robot       Result := T.Text;
3472*16467b97STreehugger Robot   end
3473*16467b97STreehugger Robot   else
3474*16467b97STreehugger Robot     Result := FPayload.ToString;
3475*16467b97STreehugger Robot end;
3476*16467b97STreehugger Robot 
ToStringWithHiddenTokensnull3477*16467b97STreehugger Robot function TParseTree.ToStringWithHiddenTokens: String;
3478*16467b97STreehugger Robot var
3479*16467b97STreehugger Robot   Buf: TStringBuilder;
3480*16467b97STreehugger Robot   Hidden: IToken;
3481*16467b97STreehugger Robot   NodeText: String;
3482*16467b97STreehugger Robot begin
3483*16467b97STreehugger Robot   Buf := TStringBuilder.Create;
3484*16467b97STreehugger Robot   try
3485*16467b97STreehugger Robot     if Assigned(FHiddenTokens) then
3486*16467b97STreehugger Robot     begin
3487*16467b97STreehugger Robot       for Hidden in FHiddenTokens do
3488*16467b97STreehugger Robot         Buf.Append(Hidden.Text);
3489*16467b97STreehugger Robot     end;
3490*16467b97STreehugger Robot     NodeText := ToString;
3491*16467b97STreehugger Robot     if (NodeText <> '<EOF>') then
3492*16467b97STreehugger Robot       Buf.Append(NodeText);
3493*16467b97STreehugger Robot     Result := Buf.ToString;
3494*16467b97STreehugger Robot   finally
3495*16467b97STreehugger Robot     Buf.Free;
3496*16467b97STreehugger Robot   end;
3497*16467b97STreehugger Robot end;
3498*16467b97STreehugger Robot 
3499*16467b97STreehugger Robot procedure TParseTree._ToStringLeaves(const Buf: TStringBuilder);
3500*16467b97STreehugger Robot var
3501*16467b97STreehugger Robot   T: IBaseTree;
3502*16467b97STreehugger Robot begin
3503*16467b97STreehugger Robot   if Supports(FPayload, IToken) then
3504*16467b97STreehugger Robot   begin
3505*16467b97STreehugger Robot     // leaf node token?
3506*16467b97STreehugger Robot     Buf.Append(ToStringWithHiddenTokens);
3507*16467b97STreehugger Robot     Exit;
3508*16467b97STreehugger Robot   end;
3509*16467b97STreehugger Robot   if Assigned(FChildren) then
3510*16467b97STreehugger Robot     for T in FChildren do
3511*16467b97STreehugger Robot       (T as IParseTree)._ToStringLeaves(Buf);
3512*16467b97STreehugger Robot end;
3513*16467b97STreehugger Robot 
3514*16467b97STreehugger Robot { ERewriteCardinalityException }
3515*16467b97STreehugger Robot 
3516*16467b97STreehugger Robot constructor ERewriteCardinalityException.Create(
3517*16467b97STreehugger Robot   const AElementDescription: String);
3518*16467b97STreehugger Robot begin
3519*16467b97STreehugger Robot   inherited Create(AElementDescription);
3520*16467b97STreehugger Robot   FElementDescription := AElementDescription;
3521*16467b97STreehugger Robot end;
3522*16467b97STreehugger Robot 
3523*16467b97STreehugger Robot { TRewriteRuleElementStream }
3524*16467b97STreehugger Robot 
3525*16467b97STreehugger Robot procedure TRewriteRuleElementStream.Add(const El: IANTLRInterface);
3526*16467b97STreehugger Robot begin
3527*16467b97STreehugger Robot   if (El = nil) then
3528*16467b97STreehugger Robot     Exit;
3529*16467b97STreehugger Robot   if Assigned(FElements) then
3530*16467b97STreehugger Robot      // if in list, just add
3531*16467b97STreehugger Robot     FElements.Add(El)
3532*16467b97STreehugger Robot   else
3533*16467b97STreehugger Robot     if (FSingleElement = nil) then
3534*16467b97STreehugger Robot       // no elements yet, track w/o list
3535*16467b97STreehugger Robot       FSingleElement := El
3536*16467b97STreehugger Robot     else
3537*16467b97STreehugger Robot     begin
3538*16467b97STreehugger Robot       // adding 2nd element, move to list
3539*16467b97STreehugger Robot       FElements := TList<IANTLRInterface>.Create;
3540*16467b97STreehugger Robot       FElements.Capacity := 5;
3541*16467b97STreehugger Robot       FElements.Add(FSingleElement);
3542*16467b97STreehugger Robot       FSingleElement := nil;
3543*16467b97STreehugger Robot       FElements.Add(El);
3544*16467b97STreehugger Robot     end;
3545*16467b97STreehugger Robot end;
3546*16467b97STreehugger Robot 
3547*16467b97STreehugger Robot constructor TRewriteRuleElementStream.Create(const AAdaptor: ITreeAdaptor;
3548*16467b97STreehugger Robot   const AElementDescription: String);
3549*16467b97STreehugger Robot begin
3550*16467b97STreehugger Robot   inherited Create;
3551*16467b97STreehugger Robot   FAdaptor := AAdaptor;
3552*16467b97STreehugger Robot   FElementDescription := AElementDescription;
3553*16467b97STreehugger Robot end;
3554*16467b97STreehugger Robot 
3555*16467b97STreehugger Robot constructor TRewriteRuleElementStream.Create(const AAdaptor: ITreeAdaptor;
3556*16467b97STreehugger Robot   const AElementDescription: String; const AOneElement: IANTLRInterface);
3557*16467b97STreehugger Robot begin
3558*16467b97STreehugger Robot   Create(AAdaptor, AElementDescription);
3559*16467b97STreehugger Robot   Add(AOneElement);
3560*16467b97STreehugger Robot end;
3561*16467b97STreehugger Robot 
3562*16467b97STreehugger Robot constructor TRewriteRuleElementStream.Create(const AAdaptor: ITreeAdaptor;
3563*16467b97STreehugger Robot   const AElementDescription: String; const AElements: IList<IANTLRInterface>);
3564*16467b97STreehugger Robot begin
3565*16467b97STreehugger Robot   Create(AAdaptor, AElementDescription);
3566*16467b97STreehugger Robot   FElements := AElements;
3567*16467b97STreehugger Robot end;
3568*16467b97STreehugger Robot 
GetDescriptionnull3569*16467b97STreehugger Robot function TRewriteRuleElementStream.GetDescription: String;
3570*16467b97STreehugger Robot begin
3571*16467b97STreehugger Robot   Result := FElementDescription;
3572*16467b97STreehugger Robot end;
3573*16467b97STreehugger Robot 
TRewriteRuleElementStream.HasNext()3574*16467b97STreehugger Robot function TRewriteRuleElementStream.HasNext: Boolean;
3575*16467b97STreehugger Robot begin
3576*16467b97STreehugger Robot   Result := ((FSingleElement <> nil) and (FCursor < 1))
3577*16467b97STreehugger Robot     or ((FElements <> nil) and (FCursor < FElements.Count));
3578*16467b97STreehugger Robot end;
3579*16467b97STreehugger Robot 
NextTreenull3580*16467b97STreehugger Robot function TRewriteRuleElementStream.NextTree: IANTLRInterface;
3581*16467b97STreehugger Robot begin
3582*16467b97STreehugger Robot   Result := _Next;
3583*16467b97STreehugger Robot end;
3584*16467b97STreehugger Robot 
3585*16467b97STreehugger Robot procedure TRewriteRuleElementStream.Reset;
3586*16467b97STreehugger Robot begin
3587*16467b97STreehugger Robot   FCursor := 0;
3588*16467b97STreehugger Robot   FDirty := True;
3589*16467b97STreehugger Robot end;
3590*16467b97STreehugger Robot 
Sizenull3591*16467b97STreehugger Robot function TRewriteRuleElementStream.Size: Integer;
3592*16467b97STreehugger Robot begin
3593*16467b97STreehugger Robot   if Assigned(FSingleElement) then
3594*16467b97STreehugger Robot     Result := 1
3595*16467b97STreehugger Robot   else
3596*16467b97STreehugger Robot     if Assigned(FElements) then
3597*16467b97STreehugger Robot       Result := FElements.Count
3598*16467b97STreehugger Robot     else
3599*16467b97STreehugger Robot       Result := 0;
3600*16467b97STreehugger Robot end;
3601*16467b97STreehugger Robot 
ToTreenull3602*16467b97STreehugger Robot function TRewriteRuleElementStream.ToTree(const El: IANTLRInterface): IANTLRInterface;
3603*16467b97STreehugger Robot begin
3604*16467b97STreehugger Robot   Result := El;
3605*16467b97STreehugger Robot end;
3606*16467b97STreehugger Robot 
TRewriteRuleElementStream._Next()3607*16467b97STreehugger Robot function TRewriteRuleElementStream._Next: IANTLRInterface;
3608*16467b97STreehugger Robot var
3609*16467b97STreehugger Robot   Size: Integer;
3610*16467b97STreehugger Robot begin
3611*16467b97STreehugger Robot   Size := Self.Size;
3612*16467b97STreehugger Robot   if (Size = 0) then
3613*16467b97STreehugger Robot     raise ERewriteEmptyStreamException.Create(FElementDescription);
3614*16467b97STreehugger Robot 
3615*16467b97STreehugger Robot   if (FCursor >= Size) then
3616*16467b97STreehugger Robot   begin
3617*16467b97STreehugger Robot      // out of elements?
3618*16467b97STreehugger Robot      if (Size = 1) then
3619*16467b97STreehugger Robot        // if size is 1, it's ok; return and we'll dup
3620*16467b97STreehugger Robot        Result := ToTree(FSingleElement)
3621*16467b97STreehugger Robot      else
3622*16467b97STreehugger Robot        // out of elements and size was not 1, so we can't dup
3623*16467b97STreehugger Robot        raise ERewriteCardinalityException.Create(FElementDescription);
3624*16467b97STreehugger Robot   end
3625*16467b97STreehugger Robot   else
3626*16467b97STreehugger Robot   begin
3627*16467b97STreehugger Robot     // we have elements
3628*16467b97STreehugger Robot     if Assigned(FSingleElement) then
3629*16467b97STreehugger Robot     begin
3630*16467b97STreehugger Robot       Inc(FCursor); // move cursor even for single element list
3631*16467b97STreehugger Robot       Result := ToTree(FSingleElement);
3632*16467b97STreehugger Robot     end
3633*16467b97STreehugger Robot     else
3634*16467b97STreehugger Robot     begin
3635*16467b97STreehugger Robot       // must have more than one in list, pull from elements
3636*16467b97STreehugger Robot       Result := ToTree(FElements[FCursor]);
3637*16467b97STreehugger Robot       Inc(FCursor);
3638*16467b97STreehugger Robot     end;
3639*16467b97STreehugger Robot   end;
3640*16467b97STreehugger Robot end;
3641*16467b97STreehugger Robot 
3642*16467b97STreehugger Robot { TRewriteRuleNodeStream }
3643*16467b97STreehugger Robot 
TRewriteRuleNodeStream.NextNode()3644*16467b97STreehugger Robot function TRewriteRuleNodeStream.NextNode: IANTLRInterface;
3645*16467b97STreehugger Robot begin
3646*16467b97STreehugger Robot   Result := _Next;
3647*16467b97STreehugger Robot end;
3648*16467b97STreehugger Robot 
ToTreenull3649*16467b97STreehugger Robot function TRewriteRuleNodeStream.ToTree(
3650*16467b97STreehugger Robot   const El: IANTLRInterface): IANTLRInterface;
3651*16467b97STreehugger Robot begin
3652*16467b97STreehugger Robot   Result := FAdaptor.DupNode(El);
3653*16467b97STreehugger Robot end;
3654*16467b97STreehugger Robot 
3655*16467b97STreehugger Robot { TRewriteRuleSubtreeStream }
3656*16467b97STreehugger Robot 
TRewriteRuleSubtreeStream.Dup(3657*16467b97STreehugger Robot function TRewriteRuleSubtreeStream.Dup(
3658*16467b97STreehugger Robot   const O: IANTLRInterface): IANTLRInterface;
3659*16467b97STreehugger Robot begin
3660*16467b97STreehugger Robot   Result := FAdaptor.DupTree(O);
3661*16467b97STreehugger Robot end;
3662*16467b97STreehugger Robot 
TRewriteRuleSubtreeStream.DupNode(3663*16467b97STreehugger Robot function TRewriteRuleSubtreeStream.DupNode(
3664*16467b97STreehugger Robot   const O: IANTLRInterface): IANTLRInterface;
3665*16467b97STreehugger Robot begin
3666*16467b97STreehugger Robot   Result := FAdaptor.DupNode(O);
3667*16467b97STreehugger Robot end;
3668*16467b97STreehugger Robot 
TRewriteRuleSubtreeStream.FetchObject(3669*16467b97STreehugger Robot function TRewriteRuleSubtreeStream.FetchObject(
3670*16467b97STreehugger Robot   const PH: TProcessHandler): IANTLRInterface;
3671*16467b97STreehugger Robot begin
3672*16467b97STreehugger Robot   if (RequiresDuplication) then
3673*16467b97STreehugger Robot     // process the object
3674*16467b97STreehugger Robot     Result := PH(_Next)
3675*16467b97STreehugger Robot   else
3676*16467b97STreehugger Robot     // test above then fetch
3677*16467b97STreehugger Robot     Result := _Next;
3678*16467b97STreehugger Robot end;
3679*16467b97STreehugger Robot 
NextNodenull3680*16467b97STreehugger Robot function TRewriteRuleSubtreeStream.NextNode: IANTLRInterface;
3681*16467b97STreehugger Robot begin
3682*16467b97STreehugger Robot   // if necessary, dup (at most a single node since this is for making root nodes).
3683*16467b97STreehugger Robot   Result := FetchObject(DupNode);
3684*16467b97STreehugger Robot end;
3685*16467b97STreehugger Robot 
NextTreenull3686*16467b97STreehugger Robot function TRewriteRuleSubtreeStream.NextTree: IANTLRInterface;
3687*16467b97STreehugger Robot begin
3688*16467b97STreehugger Robot   // if out of elements and size is 1, dup
3689*16467b97STreehugger Robot   Result := FetchObject(Dup);
3690*16467b97STreehugger Robot end;
3691*16467b97STreehugger Robot 
RequiresDuplicationnull3692*16467b97STreehugger Robot function TRewriteRuleSubtreeStream.RequiresDuplication: Boolean;
3693*16467b97STreehugger Robot var
3694*16467b97STreehugger Robot   Size: Integer;
3695*16467b97STreehugger Robot begin
3696*16467b97STreehugger Robot   Size := Self.Size;
3697*16467b97STreehugger Robot   // if dirty or if out of elements and size is 1
3698*16467b97STreehugger Robot   Result := FDirty or ((FCursor >= Size) and (Size = 1));
3699*16467b97STreehugger Robot end;
3700*16467b97STreehugger Robot 
3701*16467b97STreehugger Robot { TRewriteRuleTokenStream }
3702*16467b97STreehugger Robot 
NextNodenull3703*16467b97STreehugger Robot function TRewriteRuleTokenStream.NextNode: IANTLRInterface;
3704*16467b97STreehugger Robot begin
3705*16467b97STreehugger Robot   Result := FAdaptor.CreateNode(_Next as IToken)
3706*16467b97STreehugger Robot end;
3707*16467b97STreehugger Robot 
NextTokennull3708*16467b97STreehugger Robot function TRewriteRuleTokenStream.NextToken: IToken;
3709*16467b97STreehugger Robot begin
3710*16467b97STreehugger Robot   Result := _Next as IToken;
3711*16467b97STreehugger Robot end;
3712*16467b97STreehugger Robot 
ToTreenull3713*16467b97STreehugger Robot function TRewriteRuleTokenStream.ToTree(
3714*16467b97STreehugger Robot   const El: IANTLRInterface): IANTLRInterface;
3715*16467b97STreehugger Robot begin
3716*16467b97STreehugger Robot   Result := El;
3717*16467b97STreehugger Robot end;
3718*16467b97STreehugger Robot 
3719*16467b97STreehugger Robot { TTreeParser }
3720*16467b97STreehugger Robot 
3721*16467b97STreehugger Robot constructor TTreeParser.Create(const AInput: ITreeNodeStream);
3722*16467b97STreehugger Robot begin
3723*16467b97STreehugger Robot   inherited Create; // highlight that we go to super to set state object
3724*16467b97STreehugger Robot   SetTreeNodeStream(AInput);
3725*16467b97STreehugger Robot end;
3726*16467b97STreehugger Robot 
3727*16467b97STreehugger Robot constructor TTreeParser.Create(const AInput: ITreeNodeStream;
3728*16467b97STreehugger Robot   const AState: IRecognizerSharedState);
3729*16467b97STreehugger Robot begin
3730*16467b97STreehugger Robot   inherited Create(AState); // share the state object with another parser
3731*16467b97STreehugger Robot   SetTreeNodeStream(AInput);
3732*16467b97STreehugger Robot end;
3733*16467b97STreehugger Robot 
GetCurrentInputSymbolnull3734*16467b97STreehugger Robot function TTreeParser.GetCurrentInputSymbol(
3735*16467b97STreehugger Robot   const Input: IIntStream): IANTLRInterface;
3736*16467b97STreehugger Robot begin
3737*16467b97STreehugger Robot   Result := FInput.LT(1);
3738*16467b97STreehugger Robot end;
3739*16467b97STreehugger Robot 
GetErrorHeadernull3740*16467b97STreehugger Robot function TTreeParser.GetErrorHeader(const E: ERecognitionException): String;
3741*16467b97STreehugger Robot begin
3742*16467b97STreehugger Robot   Result := GetGrammarFileName + ': node from ';
3743*16467b97STreehugger Robot   if (E.ApproximateLineInfo) then
3744*16467b97STreehugger Robot     Result := Result + 'after ';
3745*16467b97STreehugger Robot   Result := Result + 'line ' + IntToStr(E.Line) + ':' + IntToStr(E.CharPositionInLine);
3746*16467b97STreehugger Robot end;
3747*16467b97STreehugger Robot 
TTreeParser.GetErrorMessage(const E: ERecognitionException;3748*16467b97STreehugger Robot function TTreeParser.GetErrorMessage(const E: ERecognitionException;
3749*16467b97STreehugger Robot   const TokenNames: TStringArray): String;
3750*16467b97STreehugger Robot var
3751*16467b97STreehugger Robot   Adaptor: ITreeAdaptor;
3752*16467b97STreehugger Robot begin
3753*16467b97STreehugger Robot   if (Self is TTreeParser) then
3754*16467b97STreehugger Robot   begin
3755*16467b97STreehugger Robot     Adaptor := (E.Input as ITreeNodeStream).TreeAdaptor;
3756*16467b97STreehugger Robot     E.Token := Adaptor.GetToken(E.Node);
3757*16467b97STreehugger Robot     if (E.Token = nil) then
3758*16467b97STreehugger Robot       // could be an UP/DOWN node
3759*16467b97STreehugger Robot       E.Token := TCommonToken.Create(Adaptor.GetNodeType(E.Node),
3760*16467b97STreehugger Robot         Adaptor.GetNodeText(E.Node));
3761*16467b97STreehugger Robot   end;
3762*16467b97STreehugger Robot   Result := inherited GetErrorMessage(E, TokenNames);
3763*16467b97STreehugger Robot end;
3764*16467b97STreehugger Robot 
GetInputnull3765*16467b97STreehugger Robot function TTreeParser.GetInput: IIntStream;
3766*16467b97STreehugger Robot begin
3767*16467b97STreehugger Robot   Result := FInput;
3768*16467b97STreehugger Robot end;
3769*16467b97STreehugger Robot 
TTreeParser.GetMissingSymbol(const Input: IIntStream;3770*16467b97STreehugger Robot function TTreeParser.GetMissingSymbol(const Input: IIntStream;
3771*16467b97STreehugger Robot   const E: ERecognitionException; const ExpectedTokenType: Integer;
3772*16467b97STreehugger Robot   const Follow: IBitSet): IANTLRInterface;
3773*16467b97STreehugger Robot var
3774*16467b97STreehugger Robot   TokenText: String;
3775*16467b97STreehugger Robot begin
3776*16467b97STreehugger Robot   TokenText := '<missing ' + GetTokenNames[ExpectedTokenType] + '>';
3777*16467b97STreehugger Robot   Result := TCommonTree.Create(TCommonToken.Create(ExpectedTokenType, TokenText));
3778*16467b97STreehugger Robot end;
3779*16467b97STreehugger Robot 
TTreeParser.GetSourceName()3780*16467b97STreehugger Robot function TTreeParser.GetSourceName: String;
3781*16467b97STreehugger Robot begin
3782*16467b97STreehugger Robot   Result := FInput.SourceName;
3783*16467b97STreehugger Robot end;
3784*16467b97STreehugger Robot 
GetTreeNodeStreamnull3785*16467b97STreehugger Robot function TTreeParser.GetTreeNodeStream: ITreeNodeStream;
3786*16467b97STreehugger Robot begin
3787*16467b97STreehugger Robot   Result := FInput;
3788*16467b97STreehugger Robot end;
3789*16467b97STreehugger Robot 
3790*16467b97STreehugger Robot procedure TTreeParser.MatchAny(const Input: IIntStream);
3791*16467b97STreehugger Robot var
3792*16467b97STreehugger Robot   Look: IANTLRInterface;
3793*16467b97STreehugger Robot   Level, TokenType: Integer;
3794*16467b97STreehugger Robot begin
3795*16467b97STreehugger Robot   FState.ErrorRecovery := False;
3796*16467b97STreehugger Robot   FState.Failed := False;
3797*16467b97STreehugger Robot   Look := FInput.LT(1);
3798*16467b97STreehugger Robot   if (FInput.TreeAdaptor.GetChildCount(Look) = 0) then
3799*16467b97STreehugger Robot   begin
3800*16467b97STreehugger Robot     FInput.Consume; // not subtree, consume 1 node and return
3801*16467b97STreehugger Robot     Exit;
3802*16467b97STreehugger Robot   end;
3803*16467b97STreehugger Robot 
3804*16467b97STreehugger Robot   // current node is a subtree, skip to corresponding UP.
3805*16467b97STreehugger Robot   // must count nesting level to get right UP
3806*16467b97STreehugger Robot   Level := 0;
3807*16467b97STreehugger Robot   TokenType := FInput.TreeAdaptor.GetNodeType(Look);
3808*16467b97STreehugger Robot   while (TokenType <> TToken.EOF) and not ((TokenType = UP) and (Level = 0)) do
3809*16467b97STreehugger Robot   begin
3810*16467b97STreehugger Robot     FInput.Consume;
3811*16467b97STreehugger Robot     Look := FInput.LT(1);
3812*16467b97STreehugger Robot     TokenType := FInput.TreeAdaptor.GetNodeType(Look);
3813*16467b97STreehugger Robot     if (TokenType = DOWN) then
3814*16467b97STreehugger Robot       Inc(Level)
3815*16467b97STreehugger Robot     else
3816*16467b97STreehugger Robot       if (TokenType = UP) then
3817*16467b97STreehugger Robot         Dec(Level);
3818*16467b97STreehugger Robot   end;
3819*16467b97STreehugger Robot   FInput.Consume; // consume UP
3820*16467b97STreehugger Robot end;
3821*16467b97STreehugger Robot 
3822*16467b97STreehugger Robot procedure TTreeParser.Mismatch(const Input: IIntStream;
3823*16467b97STreehugger Robot   const TokenType: Integer; const Follow: IBitSet);
3824*16467b97STreehugger Robot begin
3825*16467b97STreehugger Robot   raise EMismatchedTreeNodeException.Create(TokenType, FInput);
3826*16467b97STreehugger Robot end;
3827*16467b97STreehugger Robot 
3828*16467b97STreehugger Robot procedure TTreeParser.Reset;
3829*16467b97STreehugger Robot begin
3830*16467b97STreehugger Robot   inherited; // reset all recognizer state variables
3831*16467b97STreehugger Robot   if Assigned(FInput) then
3832*16467b97STreehugger Robot     FInput.Seek(0); // rewind the input
3833*16467b97STreehugger Robot end;
3834*16467b97STreehugger Robot 
3835*16467b97STreehugger Robot procedure TTreeParser.SetTreeNodeStream(const Value: ITreeNodeStream);
3836*16467b97STreehugger Robot begin
3837*16467b97STreehugger Robot   FInput := Value;
3838*16467b97STreehugger Robot end;
3839*16467b97STreehugger Robot 
3840*16467b97STreehugger Robot procedure TTreeParser.TraceIn(const RuleName: String; const RuleIndex: Integer);
3841*16467b97STreehugger Robot begin
3842*16467b97STreehugger Robot   inherited TraceIn(RuleName, RuleIndex, FInput.LT(1).ToString);
3843*16467b97STreehugger Robot end;
3844*16467b97STreehugger Robot 
3845*16467b97STreehugger Robot procedure TTreeParser.TraceOut(const RuleName: String;
3846*16467b97STreehugger Robot   const RuleIndex: Integer);
3847*16467b97STreehugger Robot begin
3848*16467b97STreehugger Robot   inherited TraceOut(RuleName, RuleIndex, FInput.LT(1).ToString);
3849*16467b97STreehugger Robot end;
3850*16467b97STreehugger Robot 
3851*16467b97STreehugger Robot { TTreePatternLexer }
3852*16467b97STreehugger Robot 
3853*16467b97STreehugger Robot constructor TTreePatternLexer.Create;
3854*16467b97STreehugger Robot begin
3855*16467b97STreehugger Robot   inherited;
3856*16467b97STreehugger Robot   FSVal := TStringBuilder.Create;
3857*16467b97STreehugger Robot end;
3858*16467b97STreehugger Robot 
3859*16467b97STreehugger Robot procedure TTreePatternLexer.Consume;
3860*16467b97STreehugger Robot begin
3861*16467b97STreehugger Robot   Inc(FP);
3862*16467b97STreehugger Robot   if (FP > FN) then
3863*16467b97STreehugger Robot     FC := EOF
3864*16467b97STreehugger Robot   else
3865*16467b97STreehugger Robot     FC := Integer(FPattern[FP]);
3866*16467b97STreehugger Robot end;
3867*16467b97STreehugger Robot 
3868*16467b97STreehugger Robot constructor TTreePatternLexer.Create(const APattern: String);
3869*16467b97STreehugger Robot begin
3870*16467b97STreehugger Robot   Create;
3871*16467b97STreehugger Robot   FPattern := APattern;
3872*16467b97STreehugger Robot   FN := Length(FPattern);
3873*16467b97STreehugger Robot   Consume;
3874*16467b97STreehugger Robot end;
3875*16467b97STreehugger Robot 
3876*16467b97STreehugger Robot destructor TTreePatternLexer.Destroy;
3877*16467b97STreehugger Robot begin
3878*16467b97STreehugger Robot   FSVal.Free;
3879*16467b97STreehugger Robot   inherited;
3880*16467b97STreehugger Robot end;
3881*16467b97STreehugger Robot 
TTreePatternLexer.NextToken()3882*16467b97STreehugger Robot function TTreePatternLexer.NextToken: Integer;
3883*16467b97STreehugger Robot begin
3884*16467b97STreehugger Robot   FSVal.Length := 0; // reset, but reuse buffer
3885*16467b97STreehugger Robot   while (FC <> EOF) do
3886*16467b97STreehugger Robot   begin
3887*16467b97STreehugger Robot     if (FC = 32) or (FC = 10) or (FC = 13) or (FC = 9) then
3888*16467b97STreehugger Robot     begin
3889*16467b97STreehugger Robot       Consume;
3890*16467b97STreehugger Robot       Continue;
3891*16467b97STreehugger Robot     end;
3892*16467b97STreehugger Robot 
3893*16467b97STreehugger Robot     if ((FC >= Ord('a')) and (FC <= Ord('z')))
3894*16467b97STreehugger Robot       or ((FC >= Ord('A')) and (FC <= Ord('Z')))
3895*16467b97STreehugger Robot       or (FC = Ord('_'))
3896*16467b97STreehugger Robot     then begin
3897*16467b97STreehugger Robot       FSVal.Append(Char(FC));
3898*16467b97STreehugger Robot       Consume;
3899*16467b97STreehugger Robot       while ((FC >= Ord('a')) and (FC <= Ord('z')))
3900*16467b97STreehugger Robot         or ((FC >= Ord('A')) and (FC <= Ord('Z')))
3901*16467b97STreehugger Robot         or ((FC >= Ord('0')) and (FC <= Ord('9')))
3902*16467b97STreehugger Robot         or (FC = Ord('_')) do
3903*16467b97STreehugger Robot       begin
3904*16467b97STreehugger Robot         FSVal.Append(Char(FC));
3905*16467b97STreehugger Robot         Consume;
3906*16467b97STreehugger Robot       end;
3907*16467b97STreehugger Robot       Exit(ID);
3908*16467b97STreehugger Robot     end;
3909*16467b97STreehugger Robot 
3910*16467b97STreehugger Robot     if (FC = Ord('(')) then
3911*16467b97STreehugger Robot     begin
3912*16467b97STreehugger Robot       Consume;
3913*16467b97STreehugger Robot       Exit(START);
3914*16467b97STreehugger Robot     end;
3915*16467b97STreehugger Robot 
3916*16467b97STreehugger Robot     if (FC = Ord(')')) then
3917*16467b97STreehugger Robot     begin
3918*16467b97STreehugger Robot       Consume;
3919*16467b97STreehugger Robot       Exit(STOP);
3920*16467b97STreehugger Robot     end;
3921*16467b97STreehugger Robot 
3922*16467b97STreehugger Robot     if (FC = Ord('%')) then
3923*16467b97STreehugger Robot     begin
3924*16467b97STreehugger Robot       Consume;
3925*16467b97STreehugger Robot       Exit(PERCENT);
3926*16467b97STreehugger Robot     end;
3927*16467b97STreehugger Robot 
3928*16467b97STreehugger Robot     if (FC = Ord(':')) then
3929*16467b97STreehugger Robot     begin
3930*16467b97STreehugger Robot       Consume;
3931*16467b97STreehugger Robot       Exit(COLON);
3932*16467b97STreehugger Robot     end;
3933*16467b97STreehugger Robot 
3934*16467b97STreehugger Robot     if (FC = Ord('.')) then
3935*16467b97STreehugger Robot     begin
3936*16467b97STreehugger Robot       Consume;
3937*16467b97STreehugger Robot       Exit(DOT);
3938*16467b97STreehugger Robot     end;
3939*16467b97STreehugger Robot 
3940*16467b97STreehugger Robot     if (FC = Ord('[')) then
3941*16467b97STreehugger Robot     begin
3942*16467b97STreehugger Robot       // grab [x] as a string, returning x
3943*16467b97STreehugger Robot       Consume;
3944*16467b97STreehugger Robot       while (FC <> Ord(']')) do
3945*16467b97STreehugger Robot       begin
3946*16467b97STreehugger Robot         if (FC = Ord('\')) then
3947*16467b97STreehugger Robot         begin
3948*16467b97STreehugger Robot           Consume;
3949*16467b97STreehugger Robot           if (FC <> Ord(']')) then
3950*16467b97STreehugger Robot             FSVal.Append('\');
3951*16467b97STreehugger Robot           FSVal.Append(Char(FC));
3952*16467b97STreehugger Robot         end
3953*16467b97STreehugger Robot         else
3954*16467b97STreehugger Robot           FSVal.Append(Char(FC));
3955*16467b97STreehugger Robot         Consume;
3956*16467b97STreehugger Robot       end;
3957*16467b97STreehugger Robot       Consume;
3958*16467b97STreehugger Robot       Exit(ARG);
3959*16467b97STreehugger Robot     end;
3960*16467b97STreehugger Robot 
3961*16467b97STreehugger Robot     Consume;
3962*16467b97STreehugger Robot     FError := True;
3963*16467b97STreehugger Robot     Exit(EOF);
3964*16467b97STreehugger Robot   end;
3965*16467b97STreehugger Robot   Result := EOF;
3966*16467b97STreehugger Robot end;
3967*16467b97STreehugger Robot 
TTreePatternLexer.SVal()3968*16467b97STreehugger Robot function TTreePatternLexer.SVal: String;
3969*16467b97STreehugger Robot begin
3970*16467b97STreehugger Robot   Result := FSVal.ToString;
3971*16467b97STreehugger Robot end;
3972*16467b97STreehugger Robot 
3973*16467b97STreehugger Robot { TTreeWizard }
3974*16467b97STreehugger Robot 
TTreeWizard.ComputeTokenTypes(3975*16467b97STreehugger Robot function TTreeWizard.ComputeTokenTypes(
3976*16467b97STreehugger Robot   const TokenNames: TStringArray): IDictionary<String, Integer>;
3977*16467b97STreehugger Robot var
3978*16467b97STreehugger Robot   TokenType: Integer;
3979*16467b97STreehugger Robot begin
3980*16467b97STreehugger Robot   Result := TDictionary<String, Integer>.Create;
3981*16467b97STreehugger Robot   if (Length(TokenNames) > 0)then
3982*16467b97STreehugger Robot   begin
3983*16467b97STreehugger Robot     for TokenType := TToken.MIN_TOKEN_TYPE to Length(TokenNames) - 1 do
3984*16467b97STreehugger Robot       Result.Add(TokenNames[TokenType], TokenType);
3985*16467b97STreehugger Robot   end;
3986*16467b97STreehugger Robot end;
3987*16467b97STreehugger Robot 
3988*16467b97STreehugger Robot constructor TTreeWizard.Create(const AAdaptor: ITreeAdaptor);
3989*16467b97STreehugger Robot begin
3990*16467b97STreehugger Robot   inherited Create;
3991*16467b97STreehugger Robot   FAdaptor := AAdaptor;
3992*16467b97STreehugger Robot end;
3993*16467b97STreehugger Robot 
3994*16467b97STreehugger Robot constructor TTreeWizard.Create(const AAdaptor: ITreeAdaptor;
3995*16467b97STreehugger Robot   const ATokenNameToTypeMap: IDictionary<String, Integer>);
3996*16467b97STreehugger Robot begin
3997*16467b97STreehugger Robot   inherited Create;
3998*16467b97STreehugger Robot   FAdaptor := AAdaptor;
3999*16467b97STreehugger Robot   FTokenNameToTypeMap := ATokenNameToTypeMap;
4000*16467b97STreehugger Robot end;
4001*16467b97STreehugger Robot 
4002*16467b97STreehugger Robot constructor TTreeWizard.Create(const AAdaptor: ITreeAdaptor;
4003*16467b97STreehugger Robot   const TokenNames: TStringArray);
4004*16467b97STreehugger Robot begin
4005*16467b97STreehugger Robot   inherited Create;
4006*16467b97STreehugger Robot   FAdaptor := AAdaptor;
4007*16467b97STreehugger Robot   FTokenNameToTypeMap := ComputeTokenTypes(TokenNames);
4008*16467b97STreehugger Robot end;
4009*16467b97STreehugger Robot 
CreateTreeOrNodenull4010*16467b97STreehugger Robot function TTreeWizard.CreateTreeOrNode(const Pattern: String): IANTLRInterface;
4011*16467b97STreehugger Robot var
4012*16467b97STreehugger Robot   Tokenizer: ITreePatternLexer;
4013*16467b97STreehugger Robot   Parser: ITreePatternParser;
4014*16467b97STreehugger Robot begin
4015*16467b97STreehugger Robot   Tokenizer := TTreePatternLexer.Create(Pattern);
4016*16467b97STreehugger Robot   Parser := TTreePatternParser.Create(Tokenizer, Self, FAdaptor);
4017*16467b97STreehugger Robot   Result := Parser.Pattern;
4018*16467b97STreehugger Robot end;
4019*16467b97STreehugger Robot 
TTreeWizard.Equals(const T1, T2: IANTLRInterface;4020*16467b97STreehugger Robot function TTreeWizard.Equals(const T1, T2: IANTLRInterface;
4021*16467b97STreehugger Robot   const Adaptor: ITreeAdaptor): Boolean;
4022*16467b97STreehugger Robot begin
4023*16467b97STreehugger Robot   Result := _Equals(T1, T2, Adaptor);
4024*16467b97STreehugger Robot end;
4025*16467b97STreehugger Robot 
TTreeWizard.Equals(const T1, T2: IANTLRInterface)4026*16467b97STreehugger Robot function TTreeWizard.Equals(const T1, T2: IANTLRInterface): Boolean;
4027*16467b97STreehugger Robot begin
4028*16467b97STreehugger Robot   Result := _Equals(T1, T2, FAdaptor);
4029*16467b97STreehugger Robot end;
4030*16467b97STreehugger Robot 
Findnull4031*16467b97STreehugger Robot function TTreeWizard.Find(const T: IANTLRInterface;
4032*16467b97STreehugger Robot   const Pattern: String): IList<IANTLRInterface>;
4033*16467b97STreehugger Robot var
4034*16467b97STreehugger Robot   Tokenizer: ITreePatternLexer;
4035*16467b97STreehugger Robot   Parser: ITreePatternParser;
4036*16467b97STreehugger Robot   TreePattern: ITreePattern;
4037*16467b97STreehugger Robot   RootTokenType: Integer;
4038*16467b97STreehugger Robot   Visitor: IContextVisitor;
4039*16467b97STreehugger Robot begin
4040*16467b97STreehugger Robot   Result := TList<IANTLRInterface>.Create;
4041*16467b97STreehugger Robot 
4042*16467b97STreehugger Robot   // Create a TreePattern from the pattern
4043*16467b97STreehugger Robot   Tokenizer := TTreePatternLexer.Create(Pattern);
4044*16467b97STreehugger Robot   Parser := TTreePatternParser.Create(Tokenizer, Self, TTreePatternTreeAdaptor.Create);
4045*16467b97STreehugger Robot   TreePattern := Parser.Pattern as ITreePattern;
4046*16467b97STreehugger Robot 
4047*16467b97STreehugger Robot   // don't allow invalid patterns
4048*16467b97STreehugger Robot   if (TreePattern = nil) or (TreePattern.IsNil)
4049*16467b97STreehugger Robot     or Supports(TreePattern, IWildcardTreePattern)
4050*16467b97STreehugger Robot   then
4051*16467b97STreehugger Robot     Exit(nil);
4052*16467b97STreehugger Robot 
4053*16467b97STreehugger Robot   RootTokenType := TreePattern.TokenType;
4054*16467b97STreehugger Robot   Visitor := TPatternMatchingContextVisitor.Create(Self, TreePattern, Result);
4055*16467b97STreehugger Robot   Visit(T, RootTokenType, Visitor);
4056*16467b97STreehugger Robot end;
4057*16467b97STreehugger Robot 
Findnull4058*16467b97STreehugger Robot function TTreeWizard.Find(const T: IANTLRInterface;
4059*16467b97STreehugger Robot   const TokenType: Integer): IList<IANTLRInterface>;
4060*16467b97STreehugger Robot begin
4061*16467b97STreehugger Robot   Result := TList<IANTLRInterface>.Create;
4062*16467b97STreehugger Robot   Visit(T, TokenType, TRecordAllElementsVisitor.Create(Result));
4063*16467b97STreehugger Robot end;
4064*16467b97STreehugger Robot 
FindFirstnull4065*16467b97STreehugger Robot function TTreeWizard.FindFirst(const T: IANTLRInterface;
4066*16467b97STreehugger Robot   const TokenType: Integer): IANTLRInterface;
4067*16467b97STreehugger Robot begin
4068*16467b97STreehugger Robot   Result := nil;
4069*16467b97STreehugger Robot end;
4070*16467b97STreehugger Robot 
FindFirstnull4071*16467b97STreehugger Robot function TTreeWizard.FindFirst(const T: IANTLRInterface;
4072*16467b97STreehugger Robot   const Pattern: String): IANTLRInterface;
4073*16467b97STreehugger Robot begin
4074*16467b97STreehugger Robot   Result := nil;
4075*16467b97STreehugger Robot end;
4076*16467b97STreehugger Robot 
TTreeWizard.GetTokenType(const TokenName: String)4077*16467b97STreehugger Robot function TTreeWizard.GetTokenType(const TokenName: String): Integer;
4078*16467b97STreehugger Robot begin
4079*16467b97STreehugger Robot   if (FTokenNameToTypeMap = nil) then
4080*16467b97STreehugger Robot     Exit(TToken.INVALID_TOKEN_TYPE);
4081*16467b97STreehugger Robot   if (not FTokenNameToTypeMap.TryGetValue(TokenName, Result)) then
4082*16467b97STreehugger Robot     Result := TToken.INVALID_TOKEN_TYPE;
4083*16467b97STreehugger Robot end;
4084*16467b97STreehugger Robot 
TTreeWizard.Index(4085*16467b97STreehugger Robot function TTreeWizard.Index(
4086*16467b97STreehugger Robot   const T: IANTLRInterface): IDictionary<Integer, IList<IANTLRInterface>>;
4087*16467b97STreehugger Robot begin
4088*16467b97STreehugger Robot   Result := TDictionary<Integer, IList<IANTLRInterface>>.Create;
4089*16467b97STreehugger Robot   _Index(T, Result);
4090*16467b97STreehugger Robot end;
4091*16467b97STreehugger Robot 
Parsenull4092*16467b97STreehugger Robot function TTreeWizard.Parse(const T: IANTLRInterface;
4093*16467b97STreehugger Robot   const Pattern: String): Boolean;
4094*16467b97STreehugger Robot begin
4095*16467b97STreehugger Robot   Result := Parse(T, Pattern, nil);
4096*16467b97STreehugger Robot end;
4097*16467b97STreehugger Robot 
Parsenull4098*16467b97STreehugger Robot function TTreeWizard.Parse(const T: IANTLRInterface; const Pattern: String;
4099*16467b97STreehugger Robot   const Labels: IDictionary<String, IANTLRInterface>): Boolean;
4100*16467b97STreehugger Robot var
4101*16467b97STreehugger Robot   Tokenizer: ITreePatternLexer;
4102*16467b97STreehugger Robot   Parser: ITreePatternParser;
4103*16467b97STreehugger Robot   TreePattern: ITreePattern;
4104*16467b97STreehugger Robot begin
4105*16467b97STreehugger Robot   Tokenizer := TTreePatternLexer.Create(Pattern);
4106*16467b97STreehugger Robot   Parser := TTreePatternParser.Create(Tokenizer, Self, TTreePatternTreeAdaptor.Create);
4107*16467b97STreehugger Robot   TreePattern := Parser.Pattern as ITreePattern;
4108*16467b97STreehugger Robot   Result := _Parse(T, TreePattern, Labels);
4109*16467b97STreehugger Robot end;
4110*16467b97STreehugger Robot 
4111*16467b97STreehugger Robot procedure TTreeWizard.Visit(const T: IANTLRInterface; const Pattern: String;
4112*16467b97STreehugger Robot   const Visitor: IContextVisitor);
4113*16467b97STreehugger Robot var
4114*16467b97STreehugger Robot   Tokenizer: ITreePatternLexer;
4115*16467b97STreehugger Robot   Parser: ITreePatternParser;
4116*16467b97STreehugger Robot   TreePattern: ITreePattern;
4117*16467b97STreehugger Robot   RootTokenType: Integer;
4118*16467b97STreehugger Robot   PatternVisitor: IContextVisitor;
4119*16467b97STreehugger Robot begin
4120*16467b97STreehugger Robot   // Create a TreePattern from the pattern
4121*16467b97STreehugger Robot   Tokenizer := TTreePatternLexer.Create(Pattern);
4122*16467b97STreehugger Robot   Parser := TTreePatternParser.Create(Tokenizer, Self, TTreePatternTreeAdaptor.Create);
4123*16467b97STreehugger Robot   TreePattern := Parser.Pattern as ITreePattern;
4124*16467b97STreehugger Robot   if (TreePattern = nil) or (TreePattern.IsNil)
4125*16467b97STreehugger Robot     or Supports(TreePattern, IWildcardTreePattern)
4126*16467b97STreehugger Robot   then
4127*16467b97STreehugger Robot     Exit;
4128*16467b97STreehugger Robot   RootTokenType := TreePattern.TokenType;
4129*16467b97STreehugger Robot   PatternVisitor := TInvokeVisitorOnPatternMatchContextVisitor.Create(Self, TreePattern, Visitor);
4130*16467b97STreehugger Robot   Visit(T, RootTokenType, PatternVisitor);
4131*16467b97STreehugger Robot end;
4132*16467b97STreehugger Robot 
TTreeWizard._Equals(const T1, T2: IANTLRInterface;4133*16467b97STreehugger Robot class function TTreeWizard._Equals(const T1, T2: IANTLRInterface;
4134*16467b97STreehugger Robot   const Adaptor: ITreeAdaptor): Boolean;
4135*16467b97STreehugger Robot var
4136*16467b97STreehugger Robot   I, N1, N2: Integer;
4137*16467b97STreehugger Robot   Child1, Child2: IANTLRInterface;
4138*16467b97STreehugger Robot begin
4139*16467b97STreehugger Robot   // make sure both are non-null
4140*16467b97STreehugger Robot   if (T1 = nil) or (T2 = nil) then
4141*16467b97STreehugger Robot     Exit(False);
4142*16467b97STreehugger Robot 
4143*16467b97STreehugger Robot   // check roots
4144*16467b97STreehugger Robot   if (Adaptor.GetNodeType(T1) <> Adaptor.GetNodeType(T2)) then
4145*16467b97STreehugger Robot     Exit(False);
4146*16467b97STreehugger Robot   if (Adaptor.GetNodeText(T1) <> Adaptor.GetNodeText(T2)) then
4147*16467b97STreehugger Robot     Exit(False);
4148*16467b97STreehugger Robot 
4149*16467b97STreehugger Robot   // check children
4150*16467b97STreehugger Robot   N1 := Adaptor.GetChildCount(T1);
4151*16467b97STreehugger Robot   N2 := Adaptor.GetChildCount(T2);
4152*16467b97STreehugger Robot   if (N1 <> N2) then
4153*16467b97STreehugger Robot     Exit(False);
4154*16467b97STreehugger Robot   for I := 0 to N1 - 1 do
4155*16467b97STreehugger Robot   begin
4156*16467b97STreehugger Robot     Child1 := Adaptor.GetChild(T1, I);
4157*16467b97STreehugger Robot     Child2 := Adaptor.GetChild(T2, I);
4158*16467b97STreehugger Robot     if (not _Equals(Child1, Child2, Adaptor)) then
4159*16467b97STreehugger Robot       Exit(False);
4160*16467b97STreehugger Robot   end;
4161*16467b97STreehugger Robot 
4162*16467b97STreehugger Robot   Result := True;
4163*16467b97STreehugger Robot end;
4164*16467b97STreehugger Robot 
4165*16467b97STreehugger Robot procedure TTreeWizard._Index(const T: IANTLRInterface;
4166*16467b97STreehugger Robot   const M: IDictionary<Integer, IList<IANTLRInterface>>);
4167*16467b97STreehugger Robot var
4168*16467b97STreehugger Robot   I, N, TType: Integer;
4169*16467b97STreehugger Robot   Elements: IList<IANTLRInterface>;
4170*16467b97STreehugger Robot begin
4171*16467b97STreehugger Robot   if (T = nil) then
4172*16467b97STreehugger Robot     Exit;
4173*16467b97STreehugger Robot   TType := FAdaptor.GetNodeType(T);
4174*16467b97STreehugger Robot   if (not M.TryGetValue(TType, Elements)) then
4175*16467b97STreehugger Robot     Elements := nil;
4176*16467b97STreehugger Robot   if (Elements = nil) then
4177*16467b97STreehugger Robot   begin
4178*16467b97STreehugger Robot     Elements := TList<IANTLRInterface>.Create;
4179*16467b97STreehugger Robot     M.Add(TType, Elements);
4180*16467b97STreehugger Robot   end;
4181*16467b97STreehugger Robot   Elements.Add(T);
4182*16467b97STreehugger Robot   N := FAdaptor.GetChildCount(T);
4183*16467b97STreehugger Robot   for I := 0 to N - 1 do
4184*16467b97STreehugger Robot     _Index(FAdaptor.GetChild(T, I), M);
4185*16467b97STreehugger Robot end;
4186*16467b97STreehugger Robot 
TTreeWizard._Parse(const T1: IANTLRInterface; const T2: ITreePattern;4187*16467b97STreehugger Robot function TTreeWizard._Parse(const T1: IANTLRInterface; const T2: ITreePattern;
4188*16467b97STreehugger Robot   const Labels: IDictionary<String, IANTLRInterface>): Boolean;
4189*16467b97STreehugger Robot var
4190*16467b97STreehugger Robot   I, N1, N2: Integer;
4191*16467b97STreehugger Robot   Child1: IANTLRInterface;
4192*16467b97STreehugger Robot   Child2: ITreePattern;
4193*16467b97STreehugger Robot begin
4194*16467b97STreehugger Robot   // make sure both are non-null
4195*16467b97STreehugger Robot   if (T1 = nil) or (T2 = nil) then
4196*16467b97STreehugger Robot     Exit(False);
4197*16467b97STreehugger Robot 
4198*16467b97STreehugger Robot   // check roots (wildcard matches anything)
4199*16467b97STreehugger Robot   if (not Supports(T2, IWildcardTreePattern)) then
4200*16467b97STreehugger Robot   begin
4201*16467b97STreehugger Robot     if (FAdaptor.GetNodeType(T1) <> T2.TokenType) then
4202*16467b97STreehugger Robot       Exit(False);
4203*16467b97STreehugger Robot     if (T2.HasTextArg) and (FAdaptor.GetNodeText(T1) <> T2.Text) then
4204*16467b97STreehugger Robot       Exit(False);
4205*16467b97STreehugger Robot   end;
4206*16467b97STreehugger Robot 
4207*16467b97STreehugger Robot   if (T2.TokenLabel <> '') and Assigned(Labels) then
4208*16467b97STreehugger Robot     // map label in pattern to node in t1
4209*16467b97STreehugger Robot     Labels.AddOrSetValue(T2.TokenLabel, T1);
4210*16467b97STreehugger Robot 
4211*16467b97STreehugger Robot   // check children
4212*16467b97STreehugger Robot   N1 := FAdaptor.GetChildCount(T1);
4213*16467b97STreehugger Robot   N2 := T2.ChildCount;
4214*16467b97STreehugger Robot   if (N1 <> N2) then
4215*16467b97STreehugger Robot     Exit(False);
4216*16467b97STreehugger Robot 
4217*16467b97STreehugger Robot   for I := 0 to N1 - 1 do
4218*16467b97STreehugger Robot   begin
4219*16467b97STreehugger Robot     Child1 := FAdaptor.GetChild(T1, I);
4220*16467b97STreehugger Robot     Child2 := T2.GetChild(I) as ITreePattern;
4221*16467b97STreehugger Robot     if (not _Parse(Child1, Child2, Labels)) then
4222*16467b97STreehugger Robot       Exit(False);
4223*16467b97STreehugger Robot   end;
4224*16467b97STreehugger Robot 
4225*16467b97STreehugger Robot   Result := True;
4226*16467b97STreehugger Robot end;
4227*16467b97STreehugger Robot 
4228*16467b97STreehugger Robot procedure TTreeWizard._Visit(const T, Parent: IANTLRInterface; const ChildIndex,
4229*16467b97STreehugger Robot   TokenType: Integer; const Visitor: IContextVisitor);
4230*16467b97STreehugger Robot var
4231*16467b97STreehugger Robot   I, N: Integer;
4232*16467b97STreehugger Robot begin
4233*16467b97STreehugger Robot   if (T = nil) then
4234*16467b97STreehugger Robot     Exit;
4235*16467b97STreehugger Robot   if (FAdaptor.GetNodeType(T) = TokenType) then
4236*16467b97STreehugger Robot     Visitor.Visit(T, Parent, ChildIndex, nil);
4237*16467b97STreehugger Robot 
4238*16467b97STreehugger Robot   N := FAdaptor.GetChildCount(T);
4239*16467b97STreehugger Robot   for I := 0 to N - 1 do
4240*16467b97STreehugger Robot     _Visit(FAdaptor.GetChild(T, I), T, I, TokenType, Visitor);
4241*16467b97STreehugger Robot end;
4242*16467b97STreehugger Robot 
4243*16467b97STreehugger Robot procedure TTreeWizard.Visit(const T: IANTLRInterface; const TokenType: Integer;
4244*16467b97STreehugger Robot   const Visitor: IContextVisitor);
4245*16467b97STreehugger Robot begin
4246*16467b97STreehugger Robot   _Visit(T, nil, 0, TokenType, Visitor);
4247*16467b97STreehugger Robot end;
4248*16467b97STreehugger Robot 
4249*16467b97STreehugger Robot constructor TTreeWizard.Create(const TokenNames: TStringArray);
4250*16467b97STreehugger Robot begin
4251*16467b97STreehugger Robot   Create(nil, TokenNames);
4252*16467b97STreehugger Robot end;
4253*16467b97STreehugger Robot 
4254*16467b97STreehugger Robot { TTreePatternParser }
4255*16467b97STreehugger Robot 
4256*16467b97STreehugger Robot constructor TTreePatternParser.Create(const ATokenizer: ITreePatternLexer;
4257*16467b97STreehugger Robot   const AWizard: ITreeWizard; const AAdaptor: ITreeAdaptor);
4258*16467b97STreehugger Robot begin
4259*16467b97STreehugger Robot   inherited Create;
4260*16467b97STreehugger Robot   FTokenizer := ATokenizer;
4261*16467b97STreehugger Robot   FWizard := AWizard;
4262*16467b97STreehugger Robot   FAdaptor := AAdaptor;
4263*16467b97STreehugger Robot   FTokenType := FTokenizer.NextToken; // kickstart
4264*16467b97STreehugger Robot end;
4265*16467b97STreehugger Robot 
TTreePatternParser.ParseNode()4266*16467b97STreehugger Robot function TTreePatternParser.ParseNode: IANTLRInterface;
4267*16467b97STreehugger Robot var
4268*16467b97STreehugger Robot   Lbl, TokenName, Text, Arg: String;
4269*16467b97STreehugger Robot   WildcardPayload: IToken;
4270*16467b97STreehugger Robot   Node: TTreeWizard.ITreePattern;
4271*16467b97STreehugger Robot   TreeNodeType: Integer;
4272*16467b97STreehugger Robot begin
4273*16467b97STreehugger Robot   // "%label:" prefix
4274*16467b97STreehugger Robot   Lbl := '';
4275*16467b97STreehugger Robot   if (FTokenType = TTreePatternLexer.PERCENT) then
4276*16467b97STreehugger Robot   begin
4277*16467b97STreehugger Robot     FTokenType := FTokenizer.NextToken;
4278*16467b97STreehugger Robot     if (FTokenType <> TTreePatternLexer.ID) then
4279*16467b97STreehugger Robot       Exit(nil);
4280*16467b97STreehugger Robot     Lbl := FTokenizer.SVal;
4281*16467b97STreehugger Robot     FTokenType := FTokenizer.NextToken;
4282*16467b97STreehugger Robot     if (FTokenType <> TTreePatternLexer.COLON) then
4283*16467b97STreehugger Robot       Exit(nil);
4284*16467b97STreehugger Robot     FTokenType := FTokenizer.NextToken; // move to ID following colon
4285*16467b97STreehugger Robot   end;
4286*16467b97STreehugger Robot 
4287*16467b97STreehugger Robot   // Wildcard?
4288*16467b97STreehugger Robot   if (FTokenType = TTreePatternLexer.DOT) then
4289*16467b97STreehugger Robot   begin
4290*16467b97STreehugger Robot     FTokenType := FTokenizer.NextToken;
4291*16467b97STreehugger Robot     WildcardPayload := TCommonToken.Create(0, '.');
4292*16467b97STreehugger Robot     Node := TTreeWizard.TWildcardTreePattern.Create(WildcardPayload);
4293*16467b97STreehugger Robot     if (Lbl <> '') then
4294*16467b97STreehugger Robot       Node.TokenLabel := Lbl;
4295*16467b97STreehugger Robot     Exit(Node);
4296*16467b97STreehugger Robot   end;
4297*16467b97STreehugger Robot 
4298*16467b97STreehugger Robot   // "ID" or "ID[arg]"
4299*16467b97STreehugger Robot   if (FTokenType <> TTreePatternLexer.ID) then
4300*16467b97STreehugger Robot     Exit(nil);
4301*16467b97STreehugger Robot   TokenName := FTokenizer.SVal;
4302*16467b97STreehugger Robot   FTokenType := FTokenizer.NextToken;
4303*16467b97STreehugger Robot   if (TokenName = 'nil') then
4304*16467b97STreehugger Robot     Exit(FAdaptor.GetNilNode);
4305*16467b97STreehugger Robot   Text := TokenName;
4306*16467b97STreehugger Robot 
4307*16467b97STreehugger Robot   // check for arg
4308*16467b97STreehugger Robot   Arg := '';
4309*16467b97STreehugger Robot   if (FTokenType = TTreePatternLexer.ARG) then
4310*16467b97STreehugger Robot   begin
4311*16467b97STreehugger Robot     Arg := FTokenizer.SVal;
4312*16467b97STreehugger Robot     Text := Arg;
4313*16467b97STreehugger Robot     FTokenType := FTokenizer.NextToken;
4314*16467b97STreehugger Robot   end;
4315*16467b97STreehugger Robot 
4316*16467b97STreehugger Robot   // create node
4317*16467b97STreehugger Robot   TreeNodeType := FWizard.GetTokenType(TokenName);
4318*16467b97STreehugger Robot   if (TreeNodeType = TToken.INVALID_TOKEN_TYPE) then
4319*16467b97STreehugger Robot     Exit(nil);
4320*16467b97STreehugger Robot 
4321*16467b97STreehugger Robot   Result := FAdaptor.CreateNode(TreeNodeType, Text);
4322*16467b97STreehugger Robot   if (Lbl <> '') and Supports(Result, TTreeWizard.ITreePattern, Node) then
4323*16467b97STreehugger Robot     Node.TokenLabel := Lbl;
4324*16467b97STreehugger Robot   if (Arg <> '') and Supports(Result, TTreeWizard.ITreePattern, Node) then
4325*16467b97STreehugger Robot     Node.HasTextArg := True;
4326*16467b97STreehugger Robot end;
4327*16467b97STreehugger Robot 
TTreePatternParser.ParseTree()4328*16467b97STreehugger Robot function TTreePatternParser.ParseTree: IANTLRInterface;
4329*16467b97STreehugger Robot var
4330*16467b97STreehugger Robot   Subtree, Child: IANTLRInterface;
4331*16467b97STreehugger Robot begin
4332*16467b97STreehugger Robot   if (FTokenType <> TTreePatternLexer.START) then
4333*16467b97STreehugger Robot   begin
4334*16467b97STreehugger Robot     WriteLn('no BEGIN');
4335*16467b97STreehugger Robot     Exit(nil);
4336*16467b97STreehugger Robot   end;
4337*16467b97STreehugger Robot 
4338*16467b97STreehugger Robot   FTokenType := FTokenizer.NextToken;
4339*16467b97STreehugger Robot   Result := ParseNode;
4340*16467b97STreehugger Robot   if (Result = nil) then
4341*16467b97STreehugger Robot     Exit;
4342*16467b97STreehugger Robot 
4343*16467b97STreehugger Robot   while (FTokenType in [TTreePatternLexer.START, TTreePatternLexer.ID,
4344*16467b97STreehugger Robot     TTreePatternLexer.PERCENT, TTreePatternLexer.DOT]) do
4345*16467b97STreehugger Robot   begin
4346*16467b97STreehugger Robot     if (FTokenType = TTreePatternLexer.START) then
4347*16467b97STreehugger Robot     begin
4348*16467b97STreehugger Robot       Subtree := ParseTree;
4349*16467b97STreehugger Robot       FAdaptor.AddChild(Result, Subtree);
4350*16467b97STreehugger Robot     end
4351*16467b97STreehugger Robot     else
4352*16467b97STreehugger Robot     begin
4353*16467b97STreehugger Robot       Child := ParseNode;
4354*16467b97STreehugger Robot       if (Child = nil) then
4355*16467b97STreehugger Robot         Exit(nil);
4356*16467b97STreehugger Robot       FAdaptor.AddChild(Result, Child);
4357*16467b97STreehugger Robot     end;
4358*16467b97STreehugger Robot   end;
4359*16467b97STreehugger Robot 
4360*16467b97STreehugger Robot   if (FTokenType <> TTreePatternLexer.STOP) then
4361*16467b97STreehugger Robot   begin
4362*16467b97STreehugger Robot     WriteLn('no END');
4363*16467b97STreehugger Robot     Exit(nil);
4364*16467b97STreehugger Robot   end;
4365*16467b97STreehugger Robot 
4366*16467b97STreehugger Robot   FTokenType := FTokenizer.NextToken;
4367*16467b97STreehugger Robot end;
4368*16467b97STreehugger Robot 
Patternnull4369*16467b97STreehugger Robot function TTreePatternParser.Pattern: IANTLRInterface;
4370*16467b97STreehugger Robot var
4371*16467b97STreehugger Robot   Node: IANTLRInterface;
4372*16467b97STreehugger Robot begin
4373*16467b97STreehugger Robot   if (FTokenType = TTreePatternLexer.START) then
4374*16467b97STreehugger Robot     Exit(ParseTree);
4375*16467b97STreehugger Robot 
4376*16467b97STreehugger Robot   if (FTokenType = TTreePatternLexer.ID) then
4377*16467b97STreehugger Robot   begin
4378*16467b97STreehugger Robot     Node := ParseNode;
4379*16467b97STreehugger Robot     if (FTokenType = TTreePatternLexer.EOF) then
4380*16467b97STreehugger Robot       Result := Node
4381*16467b97STreehugger Robot     else
4382*16467b97STreehugger Robot       Result := nil; // extra junk on end
4383*16467b97STreehugger Robot   end
4384*16467b97STreehugger Robot   else
4385*16467b97STreehugger Robot     Result := nil;
4386*16467b97STreehugger Robot end;
4387*16467b97STreehugger Robot 
4388*16467b97STreehugger Robot { TTreeWizard.TVisitor }
4389*16467b97STreehugger Robot 
4390*16467b97STreehugger Robot procedure TTreeWizard.TVisitor.Visit(const T, Parent: IANTLRInterface;
4391*16467b97STreehugger Robot   const ChildIndex: Integer;
4392*16467b97STreehugger Robot   const Labels: IDictionary<String, IANTLRInterface>);
4393*16467b97STreehugger Robot begin
4394*16467b97STreehugger Robot   Visit(T);
4395*16467b97STreehugger Robot end;
4396*16467b97STreehugger Robot 
4397*16467b97STreehugger Robot { TTreeWizard.TRecordAllElementsVisitor }
4398*16467b97STreehugger Robot 
4399*16467b97STreehugger Robot constructor TTreeWizard.TRecordAllElementsVisitor.Create(
4400*16467b97STreehugger Robot   const AList: IList<IANTLRInterface>);
4401*16467b97STreehugger Robot begin
4402*16467b97STreehugger Robot   inherited Create;
4403*16467b97STreehugger Robot   FList := AList;
4404*16467b97STreehugger Robot end;
4405*16467b97STreehugger Robot 
4406*16467b97STreehugger Robot procedure TTreeWizard.TRecordAllElementsVisitor.Visit(const T: IANTLRInterface);
4407*16467b97STreehugger Robot begin
4408*16467b97STreehugger Robot   FList.Add(T);
4409*16467b97STreehugger Robot end;
4410*16467b97STreehugger Robot 
4411*16467b97STreehugger Robot { TTreeWizard.TPatternMatchingContextVisitor }
4412*16467b97STreehugger Robot 
4413*16467b97STreehugger Robot constructor TTreeWizard.TPatternMatchingContextVisitor.Create(
4414*16467b97STreehugger Robot   const AOwner: TTreeWizard; const APattern: ITreePattern;
4415*16467b97STreehugger Robot   const AList: IList<IANTLRInterface>);
4416*16467b97STreehugger Robot begin
4417*16467b97STreehugger Robot   inherited Create;
4418*16467b97STreehugger Robot   FOwner := AOwner;
4419*16467b97STreehugger Robot   FPattern := APattern;
4420*16467b97STreehugger Robot   FList := AList;
4421*16467b97STreehugger Robot end;
4422*16467b97STreehugger Robot 
4423*16467b97STreehugger Robot procedure TTreeWizard.TPatternMatchingContextVisitor.Visit(const T,
4424*16467b97STreehugger Robot   Parent: IANTLRInterface; const ChildIndex: Integer;
4425*16467b97STreehugger Robot   const Labels: IDictionary<String, IANTLRInterface>);
4426*16467b97STreehugger Robot begin
4427*16467b97STreehugger Robot   if (FOwner._Parse(T, FPattern, nil)) then
4428*16467b97STreehugger Robot     FList.Add(T);
4429*16467b97STreehugger Robot end;
4430*16467b97STreehugger Robot 
4431*16467b97STreehugger Robot { TTreeWizard.TInvokeVisitorOnPatternMatchContextVisitor }
4432*16467b97STreehugger Robot 
4433*16467b97STreehugger Robot constructor TTreeWizard.TInvokeVisitorOnPatternMatchContextVisitor.Create(
4434*16467b97STreehugger Robot   const AOwner: TTreeWizard; const APattern: ITreePattern;
4435*16467b97STreehugger Robot   const AVisitor: IContextVisitor);
4436*16467b97STreehugger Robot begin
4437*16467b97STreehugger Robot   inherited Create;
4438*16467b97STreehugger Robot   FOwner := AOwner;
4439*16467b97STreehugger Robot   FPattern := APattern;
4440*16467b97STreehugger Robot   FVisitor := AVisitor;
4441*16467b97STreehugger Robot   FLabels := TDictionary<String, IANTLRInterface>.Create;
4442*16467b97STreehugger Robot end;
4443*16467b97STreehugger Robot 
4444*16467b97STreehugger Robot procedure TTreeWizard.TInvokeVisitorOnPatternMatchContextVisitor.Visit(const T,
4445*16467b97STreehugger Robot   Parent: IANTLRInterface; const ChildIndex: Integer;
4446*16467b97STreehugger Robot   const UnusedLabels: IDictionary<String, IANTLRInterface>);
4447*16467b97STreehugger Robot begin
4448*16467b97STreehugger Robot   // the unusedlabels arg is null as visit on token type doesn't set.
4449*16467b97STreehugger Robot   FLabels.Clear;
4450*16467b97STreehugger Robot   if (FOwner._Parse(T, FPattern, FLabels)) then
4451*16467b97STreehugger Robot     FVisitor.Visit(T, Parent, ChildIndex, FLabels);
4452*16467b97STreehugger Robot end;
4453*16467b97STreehugger Robot 
4454*16467b97STreehugger Robot { TTreeWizard.TTreePattern }
4455*16467b97STreehugger Robot 
TTreeWizard.TTreePattern.GetHasTextArg()4456*16467b97STreehugger Robot function TTreeWizard.TTreePattern.GetHasTextArg: Boolean;
4457*16467b97STreehugger Robot begin
4458*16467b97STreehugger Robot   Result := FHasTextArg;
4459*16467b97STreehugger Robot end;
4460*16467b97STreehugger Robot 
TTreeWizard.TTreePattern.GetTokenLabel()4461*16467b97STreehugger Robot function TTreeWizard.TTreePattern.GetTokenLabel: String;
4462*16467b97STreehugger Robot begin
4463*16467b97STreehugger Robot   Result := FLabel;
4464*16467b97STreehugger Robot end;
4465*16467b97STreehugger Robot 
4466*16467b97STreehugger Robot procedure TTreeWizard.TTreePattern.SetHasTextArg(const Value: Boolean);
4467*16467b97STreehugger Robot begin
4468*16467b97STreehugger Robot   FHasTextArg := Value;
4469*16467b97STreehugger Robot end;
4470*16467b97STreehugger Robot 
4471*16467b97STreehugger Robot procedure TTreeWizard.TTreePattern.SetTokenLabel(const Value: String);
4472*16467b97STreehugger Robot begin
4473*16467b97STreehugger Robot   FLabel := Value;
4474*16467b97STreehugger Robot end;
4475*16467b97STreehugger Robot 
TTreeWizard.TTreePattern.ToString()4476*16467b97STreehugger Robot function TTreeWizard.TTreePattern.ToString: String;
4477*16467b97STreehugger Robot begin
4478*16467b97STreehugger Robot   if (FLabel <> '') then
4479*16467b97STreehugger Robot     Result := '%' + FLabel + ':' + inherited ToString
4480*16467b97STreehugger Robot   else
4481*16467b97STreehugger Robot     Result := inherited ToString;
4482*16467b97STreehugger Robot end;
4483*16467b97STreehugger Robot 
4484*16467b97STreehugger Robot { TTreeWizard.TTreePatternTreeAdaptor }
4485*16467b97STreehugger Robot 
TTreePatternTreeAdaptornull4486*16467b97STreehugger Robot function TTreeWizard.TTreePatternTreeAdaptor.CreateNode(
4487*16467b97STreehugger Robot   const Payload: IToken): IANTLRInterface;
4488*16467b97STreehugger Robot begin
4489*16467b97STreehugger Robot   Result := TTreePattern.Create(Payload);
4490*16467b97STreehugger Robot end;
4491*16467b97STreehugger Robot 
4492*16467b97STreehugger Robot { TTreeRuleReturnScope }
4493*16467b97STreehugger Robot 
GetStartnull4494*16467b97STreehugger Robot function TTreeRuleReturnScope.GetStart: IANTLRInterface;
4495*16467b97STreehugger Robot begin
4496*16467b97STreehugger Robot   Result := FStart;
4497*16467b97STreehugger Robot end;
4498*16467b97STreehugger Robot 
4499*16467b97STreehugger Robot procedure TTreeRuleReturnScope.SetStart(const Value: IANTLRInterface);
4500*16467b97STreehugger Robot begin
4501*16467b97STreehugger Robot   FStart := Value;
4502*16467b97STreehugger Robot end;
4503*16467b97STreehugger Robot 
4504*16467b97STreehugger Robot { TUnBufferedTreeNodeStream }
4505*16467b97STreehugger Robot 
4506*16467b97STreehugger Robot procedure TUnBufferedTreeNodeStream.AddLookahead(const Node: IANTLRInterface);
4507*16467b97STreehugger Robot var
4508*16467b97STreehugger Robot   Bigger: TANTLRInterfaceArray;
4509*16467b97STreehugger Robot   I, RemainderHeadToEnd: Integer;
4510*16467b97STreehugger Robot begin
4511*16467b97STreehugger Robot   FLookahead[FTail] := Node;
4512*16467b97STreehugger Robot   FTail := (FTail + 1) mod Length(FLookahead);
4513*16467b97STreehugger Robot   if (FTail = FHead) then
4514*16467b97STreehugger Robot   begin
4515*16467b97STreehugger Robot     // buffer overflow: tail caught up with head
4516*16467b97STreehugger Robot     // allocate a buffer 2x as big
4517*16467b97STreehugger Robot     SetLength(Bigger,2 * Length(FLookahead));
4518*16467b97STreehugger Robot     // copy head to end of buffer to beginning of bigger buffer
4519*16467b97STreehugger Robot     RemainderHeadToEnd := Length(FLookahead) - FHead;
4520*16467b97STreehugger Robot     for I := 0 to RemainderHeadToEnd - 1 do
4521*16467b97STreehugger Robot       Bigger[I] := FLookahead[FHead + I];
4522*16467b97STreehugger Robot     // copy 0..tail to after that
4523*16467b97STreehugger Robot     for I := 0 to FTail - 1 do
4524*16467b97STreehugger Robot       Bigger[RemainderHeadToEnd + I] := FLookahead[I];
4525*16467b97STreehugger Robot     FLookahead := Bigger; // reset to bigger buffer
4526*16467b97STreehugger Robot     FHead := 0;
4527*16467b97STreehugger Robot     Inc(FTail,RemainderHeadToEnd);
4528*16467b97STreehugger Robot   end;
4529*16467b97STreehugger Robot end;
4530*16467b97STreehugger Robot 
4531*16467b97STreehugger Robot procedure TUnBufferedTreeNodeStream.AddNavigationNode(const TokenType: Integer);
4532*16467b97STreehugger Robot var
4533*16467b97STreehugger Robot   NavNode: IANTLRInterface;
4534*16467b97STreehugger Robot begin
4535*16467b97STreehugger Robot   if (TokenType = TToken.DOWN) then
4536*16467b97STreehugger Robot   begin
4537*16467b97STreehugger Robot     if (GetHasUniqueNavigationNodes) then
4538*16467b97STreehugger Robot       NavNode := FAdaptor.CreateNode(TToken.DOWN,'DOWN')
4539*16467b97STreehugger Robot     else
4540*16467b97STreehugger Robot       NavNode := FDown;
4541*16467b97STreehugger Robot   end
4542*16467b97STreehugger Robot   else
4543*16467b97STreehugger Robot   begin
4544*16467b97STreehugger Robot     if (GetHasUniqueNavigationNodes) then
4545*16467b97STreehugger Robot       NavNode := FAdaptor.CreateNode(TToken.UP,'UP')
4546*16467b97STreehugger Robot     else
4547*16467b97STreehugger Robot       NavNode := FUp;
4548*16467b97STreehugger Robot   end;
4549*16467b97STreehugger Robot   AddLookahead(NavNode);
4550*16467b97STreehugger Robot end;
4551*16467b97STreehugger Robot 
4552*16467b97STreehugger Robot procedure TUnBufferedTreeNodeStream.Consume;
4553*16467b97STreehugger Robot begin
4554*16467b97STreehugger Robot   // make sure there is something in lookahead buf, which might call next()
4555*16467b97STreehugger Robot   Fill(1);
4556*16467b97STreehugger Robot   Inc(FAbsoluteNodeIndex);
4557*16467b97STreehugger Robot   FPreviousNode := FLookahead[FHead]; // track previous node before moving on
4558*16467b97STreehugger Robot   FHead := (FHead + 1) mod Length(FLookahead);
4559*16467b97STreehugger Robot end;
4560*16467b97STreehugger Robot 
4561*16467b97STreehugger Robot constructor TUnBufferedTreeNodeStream.Create;
4562*16467b97STreehugger Robot begin
4563*16467b97STreehugger Robot   inherited;
4564*16467b97STreehugger Robot   SetLength(FLookAhead,INITIAL_LOOKAHEAD_BUFFER_SIZE);
4565*16467b97STreehugger Robot   FNodeStack := TStackList<IANTLRInterface>.Create;
4566*16467b97STreehugger Robot   FIndexStack := TStackList<Integer>.Create;
4567*16467b97STreehugger Robot end;
4568*16467b97STreehugger Robot 
4569*16467b97STreehugger Robot constructor TUnBufferedTreeNodeStream.Create(const ATree: IANTLRInterface);
4570*16467b97STreehugger Robot begin
4571*16467b97STreehugger Robot   Create(TCommonTreeAdaptor.Create, ATree);
4572*16467b97STreehugger Robot end;
4573*16467b97STreehugger Robot 
4574*16467b97STreehugger Robot constructor TUnBufferedTreeNodeStream.Create(const AAdaptor: ITreeAdaptor;
4575*16467b97STreehugger Robot   const ATree: IANTLRInterface);
4576*16467b97STreehugger Robot begin
4577*16467b97STreehugger Robot   Create;
4578*16467b97STreehugger Robot   FRoot := ATree;
4579*16467b97STreehugger Robot   FAdaptor := AAdaptor;
4580*16467b97STreehugger Robot   Reset;
4581*16467b97STreehugger Robot   FDown := FAdaptor.CreateNode(TToken.DOWN, 'DOWN');
4582*16467b97STreehugger Robot   FUp := FAdaptor.CreateNode(TToken.UP, 'UP');
4583*16467b97STreehugger Robot   FEof := FAdaptor.CreateNode(TToken.EOF, 'EOF');
4584*16467b97STreehugger Robot end;
4585*16467b97STreehugger Robot 
4586*16467b97STreehugger Robot procedure TUnBufferedTreeNodeStream.Fill(const K: Integer);
4587*16467b97STreehugger Robot var
4588*16467b97STreehugger Robot   I, N: Integer;
4589*16467b97STreehugger Robot begin
4590*16467b97STreehugger Robot   N := LookaheadSize;
4591*16467b97STreehugger Robot   for I := 1 to K - N do
4592*16467b97STreehugger Robot     MoveNext; // get at least k-depth lookahead nodes
4593*16467b97STreehugger Robot end;
4594*16467b97STreehugger Robot 
TUnBufferedTreeNodeStream.Get(const I: Integer)4595*16467b97STreehugger Robot function TUnBufferedTreeNodeStream.Get(const I: Integer): IANTLRInterface;
4596*16467b97STreehugger Robot begin
4597*16467b97STreehugger Robot   raise EInvalidOperation.Create('stream is unbuffered');
4598*16467b97STreehugger Robot end;
4599*16467b97STreehugger Robot 
GetCurrentnull4600*16467b97STreehugger Robot function TUnBufferedTreeNodeStream.GetCurrent: IANTLRInterface;
4601*16467b97STreehugger Robot begin
4602*16467b97STreehugger Robot   Result := FCurrentEnumerationNode;
4603*16467b97STreehugger Robot end;
4604*16467b97STreehugger Robot 
TUnBufferedTreeNodeStream.GetHasUniqueNavigationNodes()4605*16467b97STreehugger Robot function TUnBufferedTreeNodeStream.GetHasUniqueNavigationNodes: Boolean;
4606*16467b97STreehugger Robot begin
4607*16467b97STreehugger Robot   Result := FUniqueNavigationNodes;
4608*16467b97STreehugger Robot end;
4609*16467b97STreehugger Robot 
TUnBufferedTreeNodeStream.GetSourceName()4610*16467b97STreehugger Robot function TUnBufferedTreeNodeStream.GetSourceName: String;
4611*16467b97STreehugger Robot begin
4612*16467b97STreehugger Robot   Result := GetTokenStream.SourceName;
4613*16467b97STreehugger Robot end;
4614*16467b97STreehugger Robot 
TUnBufferedTreeNodeStream.GetTokenStream()4615*16467b97STreehugger Robot function TUnBufferedTreeNodeStream.GetTokenStream: ITokenStream;
4616*16467b97STreehugger Robot begin
4617*16467b97STreehugger Robot   Result := FTokens;
4618*16467b97STreehugger Robot end;
4619*16467b97STreehugger Robot 
TUnBufferedTreeNodeStream.GetTreeAdaptor()4620*16467b97STreehugger Robot function TUnBufferedTreeNodeStream.GetTreeAdaptor: ITreeAdaptor;
4621*16467b97STreehugger Robot begin
4622*16467b97STreehugger Robot   Result := FAdaptor;
4623*16467b97STreehugger Robot end;
4624*16467b97STreehugger Robot 
TUnBufferedTreeNodeStream.GetTreeSource()4625*16467b97STreehugger Robot function TUnBufferedTreeNodeStream.GetTreeSource: IANTLRInterface;
4626*16467b97STreehugger Robot begin
4627*16467b97STreehugger Robot   Result := FRoot;
4628*16467b97STreehugger Robot end;
4629*16467b97STreehugger Robot 
TUnBufferedTreeNodeStream.HandleRootNode()4630*16467b97STreehugger Robot function TUnBufferedTreeNodeStream.HandleRootNode: IANTLRInterface;
4631*16467b97STreehugger Robot begin
4632*16467b97STreehugger Robot   Result := FCurrentNode;
4633*16467b97STreehugger Robot   // point to first child in prep for subsequent next()
4634*16467b97STreehugger Robot   FCurrentChildIndex := 0;
4635*16467b97STreehugger Robot   if (FAdaptor.IsNil(Result)) then
4636*16467b97STreehugger Robot     // don't count this root nil node
4637*16467b97STreehugger Robot     Result := VisitChild(FCurrentChildIndex)
4638*16467b97STreehugger Robot   else
4639*16467b97STreehugger Robot   begin
4640*16467b97STreehugger Robot     AddLookahead(Result);
4641*16467b97STreehugger Robot     if (FAdaptor.GetChildCount(FCurrentNode) = 0) then
4642*16467b97STreehugger Robot       // single node case
4643*16467b97STreehugger Robot       Result := nil; // say we're done
4644*16467b97STreehugger Robot   end;
4645*16467b97STreehugger Robot end;
4646*16467b97STreehugger Robot 
Indexnull4647*16467b97STreehugger Robot function TUnBufferedTreeNodeStream.Index: Integer;
4648*16467b97STreehugger Robot begin
4649*16467b97STreehugger Robot   Result := FAbsoluteNodeIndex + 1;
4650*16467b97STreehugger Robot end;
4651*16467b97STreehugger Robot 
LAnull4652*16467b97STreehugger Robot function TUnBufferedTreeNodeStream.LA(I: Integer): Integer;
4653*16467b97STreehugger Robot var
4654*16467b97STreehugger Robot   T: IANTLRInterface;
4655*16467b97STreehugger Robot begin
4656*16467b97STreehugger Robot   T := LT(I);
4657*16467b97STreehugger Robot   if (T = nil) then
4658*16467b97STreehugger Robot     Result := TToken.INVALID_TOKEN_TYPE
4659*16467b97STreehugger Robot   else
4660*16467b97STreehugger Robot     Result := FAdaptor.GetNodeType(T);
4661*16467b97STreehugger Robot end;
4662*16467b97STreehugger Robot 
TUnBufferedTreeNodeStream.LAChar(I: Integer)4663*16467b97STreehugger Robot function TUnBufferedTreeNodeStream.LAChar(I: Integer): Char;
4664*16467b97STreehugger Robot begin
4665*16467b97STreehugger Robot   Result := Char(LA(I));
4666*16467b97STreehugger Robot end;
4667*16467b97STreehugger Robot 
TUnBufferedTreeNodeStream.LookaheadSize()4668*16467b97STreehugger Robot function TUnBufferedTreeNodeStream.LookaheadSize: Integer;
4669*16467b97STreehugger Robot begin
4670*16467b97STreehugger Robot   if (FTail < FHead) then
4671*16467b97STreehugger Robot     Result := Length(FLookahead) - FHead + FTail
4672*16467b97STreehugger Robot   else
4673*16467b97STreehugger Robot     Result := FTail - FHead;
4674*16467b97STreehugger Robot end;
4675*16467b97STreehugger Robot 
TUnBufferedTreeNodeStream.LT(const K: Integer)4676*16467b97STreehugger Robot function TUnBufferedTreeNodeStream.LT(const K: Integer): IANTLRInterface;
4677*16467b97STreehugger Robot begin
4678*16467b97STreehugger Robot   if (K = -1) then
4679*16467b97STreehugger Robot     Exit(FPreviousNode);
4680*16467b97STreehugger Robot 
4681*16467b97STreehugger Robot   if (K < 0) then
4682*16467b97STreehugger Robot     raise EArgumentException.Create('tree node streams cannot look backwards more than 1 node');
4683*16467b97STreehugger Robot 
4684*16467b97STreehugger Robot   if (K = 0) then
4685*16467b97STreehugger Robot     Exit(TTree.INVALID_NODE);
4686*16467b97STreehugger Robot 
4687*16467b97STreehugger Robot   Fill(K);
4688*16467b97STreehugger Robot   Result := FLookahead[(FHead + K - 1) mod Length(FLookahead)];
4689*16467b97STreehugger Robot end;
4690*16467b97STreehugger Robot 
Marknull4691*16467b97STreehugger Robot function TUnBufferedTreeNodeStream.Mark: Integer;
4692*16467b97STreehugger Robot var
4693*16467b97STreehugger Robot   State: ITreeWalkState;
4694*16467b97STreehugger Robot   I, N, K: Integer;
4695*16467b97STreehugger Robot   LA: TANTLRInterfaceArray;
4696*16467b97STreehugger Robot begin
4697*16467b97STreehugger Robot   if (FMarkers = nil) then
4698*16467b97STreehugger Robot   begin
4699*16467b97STreehugger Robot     FMarkers := TList<ITreeWalkState>.Create;
4700*16467b97STreehugger Robot     FMarkers.Add(nil); // depth 0 means no backtracking, leave blank
4701*16467b97STreehugger Robot   end;
4702*16467b97STreehugger Robot 
4703*16467b97STreehugger Robot   Inc(FMarkDepth);
4704*16467b97STreehugger Robot   State := nil;
4705*16467b97STreehugger Robot   if (FMarkDepth >= FMarkers.Count) then
4706*16467b97STreehugger Robot   begin
4707*16467b97STreehugger Robot     State := TTreeWalkState.Create;
4708*16467b97STreehugger Robot     FMarkers.Add(State);
4709*16467b97STreehugger Robot   end
4710*16467b97STreehugger Robot   else
4711*16467b97STreehugger Robot     State := FMarkers[FMarkDepth];
4712*16467b97STreehugger Robot 
4713*16467b97STreehugger Robot   State.AbsoluteNodeIndex := FAbsoluteNodeIndex;
4714*16467b97STreehugger Robot   State.CurrentChildIndex := FCurrentChildIndex;
4715*16467b97STreehugger Robot   State.CurrentNode := FCurrentNode;
4716*16467b97STreehugger Robot   State.PreviousNode := FPreviousNode;
4717*16467b97STreehugger Robot   State.NodeStackSize := FNodeStack.Count;
4718*16467b97STreehugger Robot   State.IndexStackSize := FIndexStack.Count;
4719*16467b97STreehugger Robot 
4720*16467b97STreehugger Robot   // take snapshot of lookahead buffer
4721*16467b97STreehugger Robot   N := LookaheadSize;
4722*16467b97STreehugger Robot   I := 0;
4723*16467b97STreehugger Robot   SetLength(LA,N);
4724*16467b97STreehugger Robot   for K := 1 to N do
4725*16467b97STreehugger Robot   begin
4726*16467b97STreehugger Robot     LA[I] := LT(K);
4727*16467b97STreehugger Robot     Inc(I);
4728*16467b97STreehugger Robot   end;
4729*16467b97STreehugger Robot   State.LookAhead := LA;
4730*16467b97STreehugger Robot   FLastMarker := FMarkDepth;
4731*16467b97STreehugger Robot   Result := FMarkDepth;
4732*16467b97STreehugger Robot end;
4733*16467b97STreehugger Robot 
TUnBufferedTreeNodeStream.MoveNext()4734*16467b97STreehugger Robot function TUnBufferedTreeNodeStream.MoveNext: Boolean;
4735*16467b97STreehugger Robot begin
4736*16467b97STreehugger Robot   // already walked entire tree; nothing to return
4737*16467b97STreehugger Robot   if (FCurrentNode = nil) then
4738*16467b97STreehugger Robot   begin
4739*16467b97STreehugger Robot     AddLookahead(FEof);
4740*16467b97STreehugger Robot     FCurrentEnumerationNode := nil;
4741*16467b97STreehugger Robot     // this is infinite stream returning EOF at end forever
4742*16467b97STreehugger Robot     // so don't throw NoSuchElementException
4743*16467b97STreehugger Robot     Exit(False);
4744*16467b97STreehugger Robot   end;
4745*16467b97STreehugger Robot 
4746*16467b97STreehugger Robot   // initial condition (first time method is called)
4747*16467b97STreehugger Robot   if (FCurrentChildIndex = -1) then
4748*16467b97STreehugger Robot   begin
4749*16467b97STreehugger Robot     FCurrentEnumerationNode := HandleRootNode as ITree;
4750*16467b97STreehugger Robot     Exit(True);
4751*16467b97STreehugger Robot   end;
4752*16467b97STreehugger Robot 
4753*16467b97STreehugger Robot   // index is in the child list?
4754*16467b97STreehugger Robot   if (FCurrentChildIndex < FAdaptor.GetChildCount(FCurrentNode)) then
4755*16467b97STreehugger Robot   begin
4756*16467b97STreehugger Robot     FCurrentEnumerationNode := VisitChild(FCurrentChildIndex) as ITree;
4757*16467b97STreehugger Robot     Exit(True);
4758*16467b97STreehugger Robot   end;
4759*16467b97STreehugger Robot 
4760*16467b97STreehugger Robot   // hit end of child list, return to parent node or its parent ...
4761*16467b97STreehugger Robot   WalkBackToMostRecentNodeWithUnvisitedChildren;
4762*16467b97STreehugger Robot   if (FCurrentNode <> nil) then
4763*16467b97STreehugger Robot   begin
4764*16467b97STreehugger Robot     FCurrentEnumerationNode := VisitChild(FCurrentChildIndex) as ITree;
4765*16467b97STreehugger Robot     Result := True;
4766*16467b97STreehugger Robot   end
4767*16467b97STreehugger Robot   else
4768*16467b97STreehugger Robot     Result := False;
4769*16467b97STreehugger Robot end;
4770*16467b97STreehugger Robot 
4771*16467b97STreehugger Robot procedure TUnBufferedTreeNodeStream.Release(const Marker: Integer);
4772*16467b97STreehugger Robot begin
4773*16467b97STreehugger Robot   // unwind any other markers made after marker and release marker
4774*16467b97STreehugger Robot   FMarkDepth := Marker;
4775*16467b97STreehugger Robot   // release this marker
4776*16467b97STreehugger Robot   Dec(FMarkDepth);
4777*16467b97STreehugger Robot end;
4778*16467b97STreehugger Robot 
4779*16467b97STreehugger Robot procedure TUnBufferedTreeNodeStream.ReplaceChildren(
4780*16467b97STreehugger Robot   const Parent: IANTLRInterface; const StartChildIndex, StopChildIndex: Integer;
4781*16467b97STreehugger Robot   const T: IANTLRInterface);
4782*16467b97STreehugger Robot begin
4783*16467b97STreehugger Robot   raise EInvalidOperation.Create('can''t do stream rewrites yet');
4784*16467b97STreehugger Robot end;
4785*16467b97STreehugger Robot 
4786*16467b97STreehugger Robot procedure TUnBufferedTreeNodeStream.Reset;
4787*16467b97STreehugger Robot begin
4788*16467b97STreehugger Robot   FCurrentNode := FRoot;
4789*16467b97STreehugger Robot   FPreviousNode := nil;
4790*16467b97STreehugger Robot   FCurrentChildIndex := -1;
4791*16467b97STreehugger Robot   FAbsoluteNodeIndex := -1;
4792*16467b97STreehugger Robot   FHead := 0;
4793*16467b97STreehugger Robot   FTail := 0;
4794*16467b97STreehugger Robot end;
4795*16467b97STreehugger Robot 
4796*16467b97STreehugger Robot procedure TUnBufferedTreeNodeStream.Rewind(const Marker: Integer);
4797*16467b97STreehugger Robot var
4798*16467b97STreehugger Robot   State: ITreeWalkState;
4799*16467b97STreehugger Robot begin
4800*16467b97STreehugger Robot   if (FMarkers = nil) then
4801*16467b97STreehugger Robot     Exit;
4802*16467b97STreehugger Robot   State := FMarkers[Marker];
4803*16467b97STreehugger Robot   FAbsoluteNodeIndex := State.AbsoluteNodeIndex;
4804*16467b97STreehugger Robot   FCurrentChildIndex := State.CurrentChildIndex;
4805*16467b97STreehugger Robot   FCurrentNode := State.CurrentNode;
4806*16467b97STreehugger Robot   FPreviousNode := State.PreviousNode;
4807*16467b97STreehugger Robot   // drop node and index stacks back to old size
4808*16467b97STreehugger Robot   FNodeStack.Capacity := State.NodeStackSize;
4809*16467b97STreehugger Robot   FIndexStack.Capacity := State.IndexStackSize;
4810*16467b97STreehugger Robot   FHead := 0; // wack lookahead buffer and then refill
4811*16467b97STreehugger Robot   FTail := 0;
4812*16467b97STreehugger Robot   while (FTail < Length(State.LookAhead)) do
4813*16467b97STreehugger Robot   begin
4814*16467b97STreehugger Robot     FLookahead[FTail] := State.LookAhead[FTail];
4815*16467b97STreehugger Robot     Inc(FTail);
4816*16467b97STreehugger Robot   end;
4817*16467b97STreehugger Robot   Release(Marker);
4818*16467b97STreehugger Robot end;
4819*16467b97STreehugger Robot 
4820*16467b97STreehugger Robot procedure TUnBufferedTreeNodeStream.Rewind;
4821*16467b97STreehugger Robot begin
4822*16467b97STreehugger Robot   Rewind(FLastMarker);
4823*16467b97STreehugger Robot end;
4824*16467b97STreehugger Robot 
4825*16467b97STreehugger Robot procedure TUnBufferedTreeNodeStream.Seek(const Index: Integer);
4826*16467b97STreehugger Robot begin
4827*16467b97STreehugger Robot   if (Index < Self.Index) then
4828*16467b97STreehugger Robot     raise EArgumentOutOfRangeException.Create('can''t seek backwards in node stream');
4829*16467b97STreehugger Robot 
4830*16467b97STreehugger Robot   // seek forward, consume until we hit index
4831*16467b97STreehugger Robot   while (Self.Index < Index) do
4832*16467b97STreehugger Robot     Consume;
4833*16467b97STreehugger Robot end;
4834*16467b97STreehugger Robot 
4835*16467b97STreehugger Robot procedure TUnBufferedTreeNodeStream.SetHasUniqueNavigationNodes(
4836*16467b97STreehugger Robot   const Value: Boolean);
4837*16467b97STreehugger Robot begin
4838*16467b97STreehugger Robot   FUniqueNavigationNodes := Value;
4839*16467b97STreehugger Robot end;
4840*16467b97STreehugger Robot 
4841*16467b97STreehugger Robot procedure TUnBufferedTreeNodeStream.SetTokenStream(const Value: ITokenStream);
4842*16467b97STreehugger Robot begin
4843*16467b97STreehugger Robot   FTokens := Value;
4844*16467b97STreehugger Robot end;
4845*16467b97STreehugger Robot 
Sizenull4846*16467b97STreehugger Robot function TUnBufferedTreeNodeStream.Size: Integer;
4847*16467b97STreehugger Robot var
4848*16467b97STreehugger Robot   S: ICommonTreeNodeStream;
4849*16467b97STreehugger Robot begin
4850*16467b97STreehugger Robot   S := TCommonTreeNodeStream.Create(FRoot);
4851*16467b97STreehugger Robot   Result := S.Size;
4852*16467b97STreehugger Robot end;
4853*16467b97STreehugger Robot 
TUnBufferedTreeNodeStream.ToString()4854*16467b97STreehugger Robot function TUnBufferedTreeNodeStream.ToString: String;
4855*16467b97STreehugger Robot begin
4856*16467b97STreehugger Robot   Result := ToString(FRoot, nil);
4857*16467b97STreehugger Robot end;
4858*16467b97STreehugger Robot 
4859*16467b97STreehugger Robot procedure TUnBufferedTreeNodeStream.ToStringWork(const P, Stop: IANTLRInterface;
4860*16467b97STreehugger Robot   const Buf: TStringBuilder);
4861*16467b97STreehugger Robot var
4862*16467b97STreehugger Robot   Text: String;
4863*16467b97STreehugger Robot   C, N: Integer;
4864*16467b97STreehugger Robot begin
4865*16467b97STreehugger Robot   if (not FAdaptor.IsNil(P)) then
4866*16467b97STreehugger Robot   begin
4867*16467b97STreehugger Robot     Text := FAdaptor.GetNodeText(P);
4868*16467b97STreehugger Robot     if (Text = '') then
4869*16467b97STreehugger Robot       Text := ' ' + IntToStr(FAdaptor.GetNodeType(P));
4870*16467b97STreehugger Robot     Buf.Append(Text); // ask the node to go to string
4871*16467b97STreehugger Robot   end;
4872*16467b97STreehugger Robot 
4873*16467b97STreehugger Robot   if SameObj(P, Stop) then
4874*16467b97STreehugger Robot     Exit;
4875*16467b97STreehugger Robot 
4876*16467b97STreehugger Robot   N := FAdaptor.GetChildCount(P);
4877*16467b97STreehugger Robot   if (N > 0) and (not FAdaptor.IsNil(P)) then
4878*16467b97STreehugger Robot   begin
4879*16467b97STreehugger Robot     Buf.Append(' ');
4880*16467b97STreehugger Robot     Buf.Append(TToken.DOWN);
4881*16467b97STreehugger Robot   end;
4882*16467b97STreehugger Robot 
4883*16467b97STreehugger Robot   for C := 0 to N - 1 do
4884*16467b97STreehugger Robot     ToStringWork(FAdaptor.GetChild(P, C), Stop, Buf);
4885*16467b97STreehugger Robot 
4886*16467b97STreehugger Robot   if (N > 0) and (not FAdaptor.IsNil(P)) then
4887*16467b97STreehugger Robot   begin
4888*16467b97STreehugger Robot     Buf.Append(' ');
4889*16467b97STreehugger Robot     Buf.Append(TToken.UP);
4890*16467b97STreehugger Robot   end;
4891*16467b97STreehugger Robot end;
4892*16467b97STreehugger Robot 
VisitChildnull4893*16467b97STreehugger Robot function TUnBufferedTreeNodeStream.VisitChild(
4894*16467b97STreehugger Robot   const Child: Integer): IANTLRInterface;
4895*16467b97STreehugger Robot begin
4896*16467b97STreehugger Robot   Result := nil;
4897*16467b97STreehugger Robot   // save state
4898*16467b97STreehugger Robot   FNodeStack.Push(FCurrentNode);
4899*16467b97STreehugger Robot   FIndexStack.Push(Child);
4900*16467b97STreehugger Robot   if (Child = 0) and (not FAdaptor.IsNil(FCurrentNode)) then
4901*16467b97STreehugger Robot     AddNavigationNode(TToken.DOWN);
4902*16467b97STreehugger Robot   // visit child
4903*16467b97STreehugger Robot   FCurrentNode := FAdaptor.GetChild(FCurrentNode, Child);
4904*16467b97STreehugger Robot   FCurrentChildIndex := 0;
4905*16467b97STreehugger Robot   Result := FCurrentNode;
4906*16467b97STreehugger Robot   AddLookahead(Result);
4907*16467b97STreehugger Robot   WalkBackToMostRecentNodeWithUnvisitedChildren;
4908*16467b97STreehugger Robot end;
4909*16467b97STreehugger Robot 
4910*16467b97STreehugger Robot procedure TUnBufferedTreeNodeStream.WalkBackToMostRecentNodeWithUnvisitedChildren;
4911*16467b97STreehugger Robot begin
4912*16467b97STreehugger Robot   while (FCurrentNode <> nil) and (FCurrentChildIndex >= FAdaptor.GetChildCount(FCurrentNode)) do
4913*16467b97STreehugger Robot   begin
4914*16467b97STreehugger Robot     FCurrentNode := FNodeStack.Pop;
4915*16467b97STreehugger Robot     if (FCurrentNode = nil) then
4916*16467b97STreehugger Robot       // hit the root?
4917*16467b97STreehugger Robot       Exit;
4918*16467b97STreehugger Robot 
4919*16467b97STreehugger Robot     FCurrentChildIndex := FIndexStack.Pop;
4920*16467b97STreehugger Robot     Inc(FCurrentChildIndex); // move to next child
4921*16467b97STreehugger Robot     if (FCurrentChildIndex >= FAdaptor.GetChildCount(FCurrentNode)) then
4922*16467b97STreehugger Robot     begin
4923*16467b97STreehugger Robot       if (not FAdaptor.IsNil(FCurrentNode)) then
4924*16467b97STreehugger Robot         AddNavigationNode(TToken.UP);
4925*16467b97STreehugger Robot       if SameObj(FCurrentNode, FRoot) then
4926*16467b97STreehugger Robot         // we done yet?
4927*16467b97STreehugger Robot         FCurrentNode := nil;
4928*16467b97STreehugger Robot     end;
4929*16467b97STreehugger Robot   end;
4930*16467b97STreehugger Robot end;
4931*16467b97STreehugger Robot 
TUnBufferedTreeNodeStream.ToString(const Start,4932*16467b97STreehugger Robot function TUnBufferedTreeNodeStream.ToString(const Start,
4933*16467b97STreehugger Robot   Stop: IANTLRInterface): String;
4934*16467b97STreehugger Robot var
4935*16467b97STreehugger Robot   BeginTokenIndex, EndTokenIndex: Integer;
4936*16467b97STreehugger Robot   Buf: TStringBuilder;
4937*16467b97STreehugger Robot begin
4938*16467b97STreehugger Robot   if (Start = nil) then
4939*16467b97STreehugger Robot     Exit('');
4940*16467b97STreehugger Robot 
4941*16467b97STreehugger Robot   // if we have the token stream, use that to dump text in order
4942*16467b97STreehugger Robot   if (FTokens <> nil) then
4943*16467b97STreehugger Robot   begin
4944*16467b97STreehugger Robot     // don't trust stop node as it's often an UP node etc...
4945*16467b97STreehugger Robot     // walk backwards until you find a non-UP, non-DOWN node
4946*16467b97STreehugger Robot     // and ask for it's token index.
4947*16467b97STreehugger Robot     BeginTokenIndex := FAdaptor.GetTokenStartIndex(Start);
4948*16467b97STreehugger Robot     if (Stop <> nil) and (FAdaptor.GetNodeType(Stop) = TToken.UP) then
4949*16467b97STreehugger Robot       EndTokenIndex := FAdaptor.GetTokenStopIndex(Start)
4950*16467b97STreehugger Robot     else
4951*16467b97STreehugger Robot       EndTokenIndex := Size - 1;
4952*16467b97STreehugger Robot     Exit(FTokens.ToString(BeginTokenIndex, EndTokenIndex));
4953*16467b97STreehugger Robot   end;
4954*16467b97STreehugger Robot 
4955*16467b97STreehugger Robot   Buf := TStringBuilder.Create;
4956*16467b97STreehugger Robot   try
4957*16467b97STreehugger Robot     ToStringWork(Start, Stop, Buf);
4958*16467b97STreehugger Robot     Result := Buf.ToString;
4959*16467b97STreehugger Robot   finally
4960*16467b97STreehugger Robot     Buf.Free;
4961*16467b97STreehugger Robot   end;
4962*16467b97STreehugger Robot end;
4963*16467b97STreehugger Robot 
4964*16467b97STreehugger Robot { TUnBufferedTreeNodeStream.TTreeWalkState }
4965*16467b97STreehugger Robot 
TTreeWalkStatenull4966*16467b97STreehugger Robot function TUnBufferedTreeNodeStream.TTreeWalkState.GetAbsoluteNodeIndex: Integer;
4967*16467b97STreehugger Robot begin
4968*16467b97STreehugger Robot   Result := FAbsoluteNodeIndex;
4969*16467b97STreehugger Robot end;
4970*16467b97STreehugger Robot 
TTreeWalkStatenull4971*16467b97STreehugger Robot function TUnBufferedTreeNodeStream.TTreeWalkState.GetCurrentChildIndex: Integer;
4972*16467b97STreehugger Robot begin
4973*16467b97STreehugger Robot   Result := FCurrentChildIndex;
4974*16467b97STreehugger Robot end;
4975*16467b97STreehugger Robot 
TTreeWalkStatenull4976*16467b97STreehugger Robot function TUnBufferedTreeNodeStream.TTreeWalkState.GetCurrentNode: IANTLRInterface;
4977*16467b97STreehugger Robot begin
4978*16467b97STreehugger Robot   Result := FCurrentNode;
4979*16467b97STreehugger Robot end;
4980*16467b97STreehugger Robot 
TTreeWalkStatenull4981*16467b97STreehugger Robot function TUnBufferedTreeNodeStream.TTreeWalkState.GetIndexStackSize: integer;
4982*16467b97STreehugger Robot begin
4983*16467b97STreehugger Robot   Result := FIndexStackSize;
4984*16467b97STreehugger Robot end;
4985*16467b97STreehugger Robot 
TTreeWalkStatenull4986*16467b97STreehugger Robot function TUnBufferedTreeNodeStream.TTreeWalkState.GetLookAhead: TANTLRInterfaceArray;
4987*16467b97STreehugger Robot begin
4988*16467b97STreehugger Robot   Result := FLookAhead;
4989*16467b97STreehugger Robot end;
4990*16467b97STreehugger Robot 
TTreeWalkStatenull4991*16467b97STreehugger Robot function TUnBufferedTreeNodeStream.TTreeWalkState.GetNodeStackSize: Integer;
4992*16467b97STreehugger Robot begin
4993*16467b97STreehugger Robot   Result := FNodeStackSize;
4994*16467b97STreehugger Robot end;
4995*16467b97STreehugger Robot 
TTreeWalkStatenull4996*16467b97STreehugger Robot function TUnBufferedTreeNodeStream.TTreeWalkState.GetPreviousNode: IANTLRInterface;
4997*16467b97STreehugger Robot begin
4998*16467b97STreehugger Robot   Result := FPreviousNode;
4999*16467b97STreehugger Robot end;
5000*16467b97STreehugger Robot 
5001*16467b97STreehugger Robot procedure TUnBufferedTreeNodeStream.TTreeWalkState.SetAbsoluteNodeIndex(
5002*16467b97STreehugger Robot   const Value: Integer);
5003*16467b97STreehugger Robot begin
5004*16467b97STreehugger Robot   FAbsoluteNodeIndex := Value;
5005*16467b97STreehugger Robot end;
5006*16467b97STreehugger Robot 
5007*16467b97STreehugger Robot procedure TUnBufferedTreeNodeStream.TTreeWalkState.SetCurrentChildIndex(
5008*16467b97STreehugger Robot   const Value: Integer);
5009*16467b97STreehugger Robot begin
5010*16467b97STreehugger Robot   FCurrentChildIndex := Value;
5011*16467b97STreehugger Robot end;
5012*16467b97STreehugger Robot 
5013*16467b97STreehugger Robot procedure TUnBufferedTreeNodeStream.TTreeWalkState.SetCurrentNode(
5014*16467b97STreehugger Robot   const Value: IANTLRInterface);
5015*16467b97STreehugger Robot begin
5016*16467b97STreehugger Robot   FCurrentNode := Value;
5017*16467b97STreehugger Robot end;
5018*16467b97STreehugger Robot 
5019*16467b97STreehugger Robot procedure TUnBufferedTreeNodeStream.TTreeWalkState.SetIndexStackSize(
5020*16467b97STreehugger Robot   const Value: integer);
5021*16467b97STreehugger Robot begin
5022*16467b97STreehugger Robot   FIndexStackSize := Value;
5023*16467b97STreehugger Robot end;
5024*16467b97STreehugger Robot 
5025*16467b97STreehugger Robot procedure TUnBufferedTreeNodeStream.TTreeWalkState.SetLookAhead(
5026*16467b97STreehugger Robot   const Value: TANTLRInterfaceArray);
5027*16467b97STreehugger Robot begin
5028*16467b97STreehugger Robot   FLookAhead := Value;
5029*16467b97STreehugger Robot end;
5030*16467b97STreehugger Robot 
5031*16467b97STreehugger Robot procedure TUnBufferedTreeNodeStream.TTreeWalkState.SetNodeStackSize(
5032*16467b97STreehugger Robot   const Value: Integer);
5033*16467b97STreehugger Robot begin
5034*16467b97STreehugger Robot   FNodeStackSize := Value;
5035*16467b97STreehugger Robot end;
5036*16467b97STreehugger Robot 
5037*16467b97STreehugger Robot procedure TUnBufferedTreeNodeStream.TTreeWalkState.SetPreviousNode(
5038*16467b97STreehugger Robot   const Value: IANTLRInterface);
5039*16467b97STreehugger Robot begin
5040*16467b97STreehugger Robot   FPreviousNode := Value;
5041*16467b97STreehugger Robot end;
5042*16467b97STreehugger Robot 
5043*16467b97STreehugger Robot { Utilities }
5044*16467b97STreehugger Robot 
5045*16467b97STreehugger Robot var
5046*16467b97STreehugger Robot   EmptyCommonTree: ICommonTree = nil;
5047*16467b97STreehugger Robot 
Def(const X: ICommonTree)5048*16467b97STreehugger Robot function Def(const X: ICommonTree): ICommonTree; overload;
5049*16467b97STreehugger Robot begin
5050*16467b97STreehugger Robot   if Assigned(X) then
5051*16467b97STreehugger Robot     Result := X
5052*16467b97STreehugger Robot   else
5053*16467b97STreehugger Robot   begin
5054*16467b97STreehugger Robot     if (EmptyCommonTree = nil) then
5055*16467b97STreehugger Robot       EmptyCommonTree := TCommonTree.Create;
5056*16467b97STreehugger Robot     Result := EmptyCommonTree;
5057*16467b97STreehugger Robot   end;
5058*16467b97STreehugger Robot end;
5059*16467b97STreehugger Robot 
5060*16467b97STreehugger Robot initialization
5061*16467b97STreehugger Robot   TTree.Initialize;
5062*16467b97STreehugger Robot 
5063*16467b97STreehugger Robot end.
5064