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