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<0 indicates nodes in the past. So LT(-1) is previous node, but
352 /// implementations are not required to provide results for k < -1.
353 /// LT(0) is undefined. For i>=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<String, Integer> 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<Integer, List> 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<TreeWalkState>.
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