1unit Antlr.Runtime.Tree; 2(* 3[The "BSD licence"] 4Copyright (c) 2008 Erik van Bilsen 5Copyright (c) 2005-2007 Kunle Odutola 6All rights reserved. 7 8Redistribution and use in source and binary forms, with or without 9modification, are permitted provided that the following conditions 10are met: 111. Redistributions of source code MUST RETAIN the above copyright 12 notice, this list of conditions and the following disclaimer. 132. 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. 173. The name of the author may not be used to endorse or promote products 18 derived from this software without specific prior WRITTEN permission. 194. 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 24THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 25IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 26OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 27IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 28INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 29NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 30DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 31THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 33THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34*) 35 36interface 37 38{$IF CompilerVersion < 20} 39{$MESSAGE ERROR 'You need Delphi 2009 or higher to use the Antlr runtime'} 40{$IFEND} 41 42uses 43 Classes, 44 SysUtils, 45 Antlr.Runtime, 46 Antlr.Runtime.Tools, 47 Antlr.Runtime.Collections; 48 49type 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> 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> 77 function DupNode(const TreeNode: IANTLRInterface): IANTLRInterface; 78 79 /// <summary>Duplicate tree recursively, using DupNode() for each node </summary> 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> 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> 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> 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> 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> 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> 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> 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> 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> 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> 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> 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 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> 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> 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> 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> 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> 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> 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> 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> 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 } 335 function GetTreeSource: IANTLRInterface; 336 function GetTokenStream: ITokenStream; 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> 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> 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> 369 function ToString(const Start, Stop: IANTLRInterface): String; overload; 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 } 441 function GetChildCount: Integer; 442 function GetParent: ITree; 443 procedure SetParent(const Value: ITree); 444 function GetChildIndex: Integer; 445 procedure SetChildIndex(const Value: Integer); 446 function GetIsNil: Boolean; 447 function GetTokenType: Integer; 448 function GetText: String; 449 function GetLine: Integer; 450 function GetCharPositionInLine: Integer; 451 function GetTokenStartIndex: Integer; 452 procedure SetTokenStartIndex(const Value: Integer); 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 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 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 484 function DupNode: ITree; 485 486 function ToStringTree: String; 487 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 } 538 function GetChildren: IList<IBaseTree>; 539 function GetChildIndex: Integer; 540 procedure SetChildIndex(const Value: Integer); 541 function GetParent: ITree; 542 procedure SetParent(const Value: ITree); 543 function GetTokenType: Integer; 544 function GetTokenStartIndex: Integer; 545 procedure SetTokenStartIndex(const Value: Integer); 546 function GetTokenStopIndex: Integer; 547 procedure SetTokenStopIndex(const Value: Integer); 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> 568 function ToStringTree: String; 569 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 } 614 function GetToken: IToken; 615 function GetStartIndex: Integer; 616 procedure SetStartIndex(const Value: Integer); 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> 641 function DupTree(const Tree: IANTLRInterface): IANTLRInterface; overload; 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> 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> 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 } 709 function GetCurrentSymbol: IANTLRInterface; 710 function GetTreeSource: IANTLRInterface; 711 function GetSourceName: String; 712 function GetTokenStream: ITokenStream; 713 procedure SetTokenStream(const Value: ITokenStream); 714 function GetTreeAdaptor: ITreeAdaptor; 715 procedure SetTreeAdaptor(const Value: ITreeAdaptor); 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 726 function Get(const I: Integer): IANTLRInterface; 727 728 function LT(const K: Integer): IANTLRInterface; 729 730 /// <summary> 731 /// Look backwards k nodes 732 /// </summary> 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> 745 function Pop: Integer; 746 747 procedure Reset; 748 749 // Debugging 750 function ToTokenString(const Start, Stop: Integer): String; 751 function ToString(const Start, Stop: IANTLRInterface): String; overload; 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. 781 function ToStringWithHiddenTokens: String; 782 783 // Print out the leaves of this tree, which means printing original 784 // input back out. 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 } 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 822 function HasNext: Boolean; 823 824 /// <summary> 825 /// Return the next element in the stream. 826 /// </summary> 827 function NextTree: IANTLRInterface; 828 function NextNode: IANTLRInterface; 829 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 } 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> 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> 873 function NextNode: IANTLRInterface; 874 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 } 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 } 900 function NextToken: Integer; 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> 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> 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> 953 function Index(const T: IANTLRInterface): IDictionary<Integer, IList<IANTLRInterface>>; 954 955 /// <summary>Return a List of tree nodes with token type ttype</summary> 956 function Find(const T: IANTLRInterface; const TokenType: Integer): IList<IANTLRInterface>; overload; 957 958 /// <summary>Return a List of subtrees matching pattern</summary> 959 function Find(const T: IANTLRInterface; const Pattern: String): IList<IANTLRInterface>; overload; 960 961 function FindFirst(const T: IANTLRInterface; const TokenType: Integer): IANTLRInterface; overload; 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> 1000 function Parse(const T: IANTLRInterface; const Pattern: String; 1001 const Labels: IDictionary<String, IANTLRInterface>): Boolean; overload; 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> 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> 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> 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 } 1046 function Pattern: IANTLRInterface; 1047 function ParseTree: IANTLRInterface; 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 } 1080 function GetHasUniqueNavigationNodes: Boolean; 1081 procedure SetHasUniqueNavigationNodes(const Value: Boolean); 1082 function GetCurrent: IANTLRInterface; 1083 function GetTokenStream: ITokenStream; 1084 procedure SetTokenStream(const Value: ITokenStream); 1085 1086 { Methods } 1087 procedure Reset; 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 1124type 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 } 1138 function GetParent: ITree; virtual; 1139 procedure SetParent(const Value: ITree); virtual; 1140 function GetChildIndex: Integer; virtual; 1141 procedure SetChildIndex(const Value: Integer); virtual; 1142 function GetTokenType: Integer; virtual; abstract; 1143 function GetText: String; virtual; abstract; 1144 function GetTokenStartIndex: Integer; virtual; abstract; 1145 procedure SetTokenStartIndex(const Value: Integer); virtual; abstract; 1146 function GetTokenStopIndex: Integer; virtual; abstract; 1147 procedure SetTokenStopIndex(const Value: Integer); virtual; abstract; 1148 function DupNode: ITree; virtual; abstract; 1149 function ToStringTree: String; virtual; 1150 function GetChildCount: Integer; virtual; 1151 function GetIsNil: Boolean; virtual; 1152 function GetLine: Integer; virtual; 1153 function GetCharPositionInLine: Integer; virtual; 1154 function GetChild(const I: Integer): ITree; virtual; 1155 procedure AddChild(const T: ITree); 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 } 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> 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 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 } 1214 function GetIsNil: Boolean; override; 1215 function GetTokenType: Integer; override; 1216 function GetText: String; override; 1217 function GetLine: Integer; override; 1218 function GetCharPositionInLine: Integer; override; 1219 function GetTokenStartIndex: Integer; override; 1220 procedure SetTokenStartIndex(const Value: Integer); override; 1221 function GetTokenStopIndex: Integer; override; 1222 procedure SetTokenStopIndex(const Value: Integer); override; 1223 function GetChildIndex: Integer; override; 1224 procedure SetChildIndex(const Value: Integer); override; 1225 function GetParent: ITree; override; 1226 procedure SetParent(const Value: ITree); override; 1227 function DupNode: ITree; override; 1228 protected 1229 { ICommonTree } 1230 function GetToken: IToken; 1231 function GetStartIndex: Integer; 1232 procedure SetStartIndex(const Value: Integer); 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 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 } 1251 function GetIsNil: Boolean; override; 1252 function GetTokenType: Integer; override; 1253 function GetText: String; override; 1254 public 1255 constructor Create(const AInput: ITokenStream; const AStart, AStop: IToken; 1256 const AException: ERecognitionException); 1257 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 } 1270 function CreateNode(const Payload: IToken): IANTLRInterface; overload; virtual; abstract; 1271 function DupNode(const TreeNode: IANTLRInterface): IANTLRInterface; virtual; abstract; 1272 function DupTree(const Tree: IANTLRInterface): IANTLRInterface; overload; virtual; 1273 function GetNilNode: IANTLRInterface; virtual; 1274 function ErrorNode(const Input: ITokenStream; const Start, Stop: IToken; 1275 const E: ERecognitionException): IANTLRInterface; virtual; 1276 function IsNil(const Tree: IANTLRInterface): Boolean; virtual; 1277 procedure AddChild(const T, Child: IANTLRInterface); virtual; 1278 function BecomeRoot(const NewRoot, OldRoot: IANTLRInterface): IANTLRInterface; overload; virtual; 1279 function RulePostProcessing(const Root: IANTLRInterface): IANTLRInterface; virtual; 1280 function GetUniqueID(const Node: IANTLRInterface): Integer; 1281 function BecomeRoot(const NewRoot: IToken; const OldRoot: IANTLRInterface): IANTLRInterface; overload; virtual; 1282 function CreateNode(const TokenType: Integer; const FromToken: IToken): IANTLRInterface; overload; virtual; 1283 function CreateNode(const TokenType: Integer; const FromToken: IToken; 1284 const Text: String): IANTLRInterface; overload; virtual; 1285 function CreateNode(const TokenType: Integer; const Text: String): IANTLRInterface; overload; virtual; 1286 function GetNodeType(const T: IANTLRInterface): Integer; virtual; 1287 procedure SetNodeType(const T: IANTLRInterface; const NodeType: Integer); virtual; 1288 function GetNodeText(const T: IANTLRInterface): String; virtual; 1289 procedure SetNodeText(const T: IANTLRInterface; const Text: String); virtual; 1290 function GetToken(const TreeNode: IANTLRInterface): IToken; virtual; abstract; 1291 procedure SetTokenBoundaries(const T: IANTLRInterface; const StartToken, 1292 StopToken: IToken); virtual; abstract; 1293 function GetTokenStartIndex(const T: IANTLRInterface): Integer; virtual; abstract; 1294 function GetTokenStopIndex(const T: IANTLRInterface): Integer; virtual; abstract; 1295 function GetChild(const T: IANTLRInterface; const I: Integer): IANTLRInterface; virtual; 1296 procedure SetChild(const T: IANTLRInterface; const I: Integer; const Child: IANTLRInterface); virtual; 1297 function DeleteChild(const T: IANTLRInterface; const I: Integer): IANTLRInterface; virtual; 1298 function GetChildCount(const T: IANTLRInterface): Integer; virtual; 1299 function GetParent(const T: IANTLRInterface): IANTLRInterface; virtual; abstract; 1300 procedure SetParent(const T, Parent: IANTLRInterface); virtual; abstract; 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 } 1307 function DupTree(const T, Parent: IANTLRInterface): IANTLRInterface; overload; virtual; 1308 function CreateToken(const TokenType: Integer; const Text: String): IToken; overload; virtual; abstract; 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 } 1317 function DupNode(const TreeNode: IANTLRInterface): IANTLRInterface; override; 1318 function CreateNode(const Payload: IToken): IANTLRInterface; overload; override; 1319 procedure SetTokenBoundaries(const T: IANTLRInterface; const StartToken, 1320 StopToken: IToken); override; 1321 function GetTokenStartIndex(const T: IANTLRInterface): Integer; override; 1322 function GetTokenStopIndex(const T: IANTLRInterface): Integer; override; 1323 function GetNodeText(const T: IANTLRInterface): String; override; 1324 function GetToken(const TreeNode: IANTLRInterface): IToken; override; 1325 function GetNodeType(const T: IANTLRInterface): Integer; override; 1326 function GetChild(const T: IANTLRInterface; const I: Integer): IANTLRInterface; override; 1327 function GetChildCount(const T: IANTLRInterface): Integer; override; 1328 function GetParent(const T: IANTLRInterface): IANTLRInterface; override; 1329 procedure SetParent(const T, Parent: IANTLRInterface); override; 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 } 1336 function CreateToken(const TokenType: Integer; const Text: String): IToken; overload; override; 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 } 1394 function GetSourceName: String; virtual; 1395 1396 procedure Consume; virtual; 1397 function LA(I: Integer): Integer; virtual; 1398 function LAChar(I: Integer): Char; 1399 function Mark: Integer; virtual; 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; 1405 function Size: Integer; virtual; 1406 protected 1407 { ITreeNodeStream } 1408 function GetTreeSource: IANTLRInterface; virtual; 1409 function GetTokenStream: ITokenStream; virtual; 1410 function GetTreeAdaptor: ITreeAdaptor; 1411 procedure SetHasUniqueNavigationNodes(const Value: Boolean); 1412 1413 function Get(const I: Integer): IANTLRInterface; 1414 function LT(const K: Integer): 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 } 1420 function GetCurrentSymbol: IANTLRInterface; virtual; 1421 procedure SetTokenStream(const Value: ITokenStream); virtual; 1422 procedure SetTreeAdaptor(const Value: ITreeAdaptor); 1423 function GetHasUniqueNavigationNodes: Boolean; 1424 1425 procedure FillBuffer(const T: IANTLRInterface); overload; 1426 function LB(const K: Integer): IANTLRInterface; 1427 procedure Push(const Index: Integer); 1428 function Pop: Integer; 1429 procedure Reset; 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> 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 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 } 1467 function GetTokenType: Integer; override; 1468 function GetText: String; override; 1469 function GetTokenStartIndex: Integer; override; 1470 procedure SetTokenStartIndex(const Value: Integer); override; 1471 function GetTokenStopIndex: Integer; override; 1472 procedure SetTokenStopIndex(const Value: Integer); override; 1473 function DupNode: ITree; override; 1474 protected 1475 { IParseTree } 1476 function ToStringWithHiddenTokens: String; 1477 function ToInputString: String; 1478 procedure _ToStringLeaves(const Buf: TStringBuilder); 1479 public 1480 constructor Create(const ALabel: IANTLRInterface); 1481 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 } 1523 function GetDescription: String; 1524 1525 procedure Add(const El: IANTLRInterface); 1526 procedure Reset; virtual; 1527 function HasNext: Boolean; 1528 function NextTree: IANTLRInterface; virtual; 1529 function NextNode: IANTLRInterface; virtual; abstract; 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> 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> 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 } 1568 function NextNode: IANTLRInterface; override; 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> 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> 1587 function FetchObject(const PH: TProcessHandler): 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> 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> 1602 function Dup(const O: IANTLRInterface): IANTLRInterface; 1603 protected 1604 { IRewriteRuleElementStream } 1605 function NextNode: IANTLRInterface; override; 1606 function NextTree: IANTLRInterface; override; 1607 end; 1608 1609 TRewriteRuleTokenStream = class(TRewriteRuleElementStream, IRewriteRuleTokenStream) 1610 protected 1611 { IRewriteRuleElementStream } 1612 function NextNode: IANTLRInterface; override; 1613 function NextToken: IToken; 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 } 1628 function GetSourceName: String; override; 1629 procedure Reset; override; 1630 procedure MatchAny(const Input: IIntStream); override; 1631 function GetInput: IIntStream; override; 1632 function GetErrorHeader(const E: ERecognitionException): String; override; 1633 function GetErrorMessage(const E: ERecognitionException; 1634 const TokenNames: TStringArray): String; override; 1635 protected 1636 { ITreeParser } 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 1643 function GetCurrentInputSymbol(const Input: IIntStream): IANTLRInterface; override; 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 } 1687 function NextToken: Integer; 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 } 1709 function GetHasTextArg: Boolean; 1710 procedure SetHasTextArg(const Value: Boolean); 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 } 1738 function GetHasTextArg: Boolean; 1739 procedure SetHasTextArg(const Value: Boolean); 1740 function GetTokenLabel: String; 1741 procedure SetTokenLabel(const Value: String); 1742 public 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 } 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 } 1801 function ComputeTokenTypes(const TokenNames: TStringArray): IDictionary<String, Integer>; 1802 function GetTokenType(const TokenName: String): Integer; 1803 function Index(const T: IANTLRInterface): IDictionary<Integer, IList<IANTLRInterface>>; 1804 function Find(const T: IANTLRInterface; const TokenType: Integer): IList<IANTLRInterface>; overload; 1805 function Find(const T: IANTLRInterface; const Pattern: String): IList<IANTLRInterface>; overload; 1806 function FindFirst(const T: IANTLRInterface; const TokenType: Integer): IANTLRInterface; overload; 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; 1812 function Parse(const T: IANTLRInterface; const Pattern: String; 1813 const Labels: IDictionary<String, IANTLRInterface>): Boolean; overload; 1814 function Parse(const T: IANTLRInterface; const Pattern: String): Boolean; overload; 1815 function CreateTreeOrNode(const Pattern: String): IANTLRInterface; 1816 function Equals(const T1, T2: IANTLRInterface): Boolean; reintroduce; overload; 1817 function Equals(const T1, T2: IANTLRInterface; 1818 const Adaptor: ITreeAdaptor): Boolean; reintroduce; overload; 1819 strict protected 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 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 } 1850 function Pattern: IANTLRInterface; 1851 function ParseTree: IANTLRInterface; 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 } 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 } 1883 function GetCurrentChildIndex: Integer; 1884 procedure SetCurrentChildIndex(const Value: Integer); 1885 function GetAbsoluteNodeIndex: Integer; 1886 procedure SetAbsoluteNodeIndex(const Value: Integer); 1887 function GetCurrentNode: IANTLRInterface; 1888 procedure SetCurrentNode(const Value: IANTLRInterface); 1889 function GetPreviousNode: IANTLRInterface; 1890 procedure SetPreviousNode(const Value: IANTLRInterface); 1891 function GetNodeStackSize: Integer; 1892 procedure SetNodeStackSize(const Value: Integer); 1893 function GetIndexStackSize: integer; 1894 procedure SetIndexStackSize(const Value: integer); 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 } 1923 function GetCurrentChildIndex: Integer; 1924 procedure SetCurrentChildIndex(const Value: Integer); 1925 function GetAbsoluteNodeIndex: Integer; 1926 procedure SetAbsoluteNodeIndex(const Value: Integer); 1927 function GetCurrentNode: IANTLRInterface; 1928 procedure SetCurrentNode(const Value: IANTLRInterface); 1929 function GetPreviousNode: IANTLRInterface; 1930 procedure SetPreviousNode(const Value: IANTLRInterface); 1931 function GetNodeStackSize: Integer; 1932 procedure SetNodeStackSize(const Value: Integer); 1933 function GetIndexStackSize: integer; 1934 procedure SetIndexStackSize(const Value: integer); 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 } 2024 function GetSourceName: String; 2025 2026 procedure Consume; virtual; 2027 function LA(I: Integer): Integer; virtual; 2028 function LAChar(I: Integer): Char; 2029 function Mark: Integer; virtual; 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; 2035 function Size: Integer; virtual; 2036 protected 2037 { ITreeNodeStream } 2038 function GetTreeSource: IANTLRInterface; virtual; 2039 function GetTokenStream: ITokenStream; 2040 function GetTreeAdaptor: ITreeAdaptor; 2041 2042 function Get(const I: Integer): IANTLRInterface; virtual; 2043 function LT(const K: Integer): IANTLRInterface; virtual; 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 } 2049 function GetHasUniqueNavigationNodes: Boolean; 2050 procedure SetHasUniqueNavigationNodes(const Value: Boolean); 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> 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; 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 2088 function HandleRootNode: IANTLRInterface; virtual; 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 2107 function ToString: String; overload; override; 2108 end; 2109 2110{ These functions return X or, if X = nil, an empty default instance } 2111function Def(const X: ICommonTree): ICommonTree; overload; 2112 2113implementation 2114 2115uses 2116 Math; 2117 2118{ TTree } 2119 2120class procedure TTree.Initialize; 2121begin 2122 FINVALID_NODE := TCommonTree.Create(TToken.INVALID_TOKEN); 2123end; 2124 2125{ TBaseTree } 2126 2127constructor TBaseTree.Create; 2128begin 2129 inherited; 2130end; 2131 2132procedure TBaseTree.AddChild(const T: ITree); 2133var 2134 ChildTree: IBaseTree; 2135 C: IBaseTree; 2136begin 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; 2178end; 2179 2180procedure TBaseTree.AddChildren(const Kids: IList<IBaseTree>); 2181var 2182 T: IBaseTree; 2183begin 2184 for T in Kids do 2185 AddChild(T); 2186end; 2187 2188constructor TBaseTree.Create(const ANode: ITree); 2189begin 2190 Create; 2191 // No default implementation 2192end; 2193 2194function TBaseTree.CreateChildrenList: IList<IBaseTree>; 2195begin 2196 Result := TList<IBaseTree>.Create; 2197end; 2198 2199function TBaseTree.DeleteChild(const I: Integer): IANTLRInterface; 2200begin 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; 2210end; 2211 2212procedure TBaseTree.FreshenParentAndChildIndexes(const Offset: Integer); 2213var 2214 N, C: Integer; 2215 Child: ITree; 2216begin 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; 2224end; 2225 2226procedure TBaseTree.FreshenParentAndChildIndexes; 2227begin 2228 FreshenParentAndChildIndexes(0); 2229end; 2230 2231function TBaseTree.GetCharPositionInLine: Integer; 2232begin 2233 Result := 0; 2234end; 2235 2236function TBaseTree.GetChild(const I: Integer): ITree; 2237begin 2238 if (FChildren = nil) or (I >= FChildren.Count) then 2239 Result := nil 2240 else 2241 Result := FChildren[I]; 2242end; 2243 2244function TBaseTree.GetChildCount: Integer; 2245begin 2246 if Assigned(FChildren) then 2247 Result := FChildren.Count 2248 else 2249 Result := 0; 2250end; 2251 2252function TBaseTree.GetChildIndex: Integer; 2253begin 2254 // No default implementation 2255 Result := 0; 2256end; 2257 2258function TBaseTree.GetChildren: IList<IBaseTree>; 2259begin 2260 Result := FChildren; 2261end; 2262 2263function TBaseTree.GetIsNil: Boolean; 2264begin 2265 Result := False; 2266end; 2267 2268function TBaseTree.GetLine: Integer; 2269begin 2270 Result := 0; 2271end; 2272 2273function TBaseTree.GetParent: ITree; 2274begin 2275 // No default implementation 2276 Result := nil; 2277end; 2278 2279procedure TBaseTree.ReplaceChildren(const StartChildIndex, 2280 StopChildIndex: Integer; const T: IANTLRInterface); 2281var 2282 ReplacingHowMany, ReplacingWithHowMany, NumNewChildren, Delta, I, J: Integer; 2283 IndexToDelete, C, ReplacedSoFar: Integer; 2284 NewTree, Killed: IBaseTree; 2285 NewChildren: IList<IBaseTree>; 2286 Child: IBaseTree; 2287begin 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; 2355end; 2356 2357procedure TBaseTree.SanityCheckParentAndChildIndexes; 2358begin 2359 SanityCheckParentAndChildIndexes(nil, -1); 2360end; 2361 2362procedure TBaseTree.SanityCheckParentAndChildIndexes(const Parent: ITree; 2363 const I: Integer); 2364var 2365 N, C: Integer; 2366 Child: ICommonTree; 2367begin 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; 2382end; 2383 2384procedure TBaseTree.SetChild(const I: Integer; const T: ITree); 2385begin 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; 2400end; 2401 2402procedure TBaseTree.SetChildIndex(const Value: Integer); 2403begin 2404 // No default implementation 2405end; 2406 2407procedure TBaseTree.SetParent(const Value: ITree); 2408begin 2409 // No default implementation 2410end; 2411 2412function TBaseTree.ToStringTree: String; 2413var 2414 Buf: TStringBuilder; 2415 I: Integer; 2416 T: IBaseTree; 2417begin 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; 2447end; 2448 2449{ TCommonTree } 2450 2451constructor TCommonTree.Create; 2452begin 2453 inherited; 2454 FStartIndex := -1; 2455 FStopIndex := -1; 2456 FChildIndex := -1; 2457end; 2458 2459constructor TCommonTree.Create(const ANode: ICommonTree); 2460begin 2461 inherited Create(ANode); 2462 FToken := ANode.Token; 2463 FStartIndex := ANode.StartIndex; 2464 FStopIndex := ANode.StopIndex; 2465 FChildIndex := -1; 2466end; 2467 2468constructor TCommonTree.Create(const AToken: IToken); 2469begin 2470 Create; 2471 FToken := AToken; 2472end; 2473 2474function TCommonTree.DupNode: ITree; 2475begin 2476 Result := TCommonTree.Create(Self) as ICommonTree; 2477end; 2478 2479function TCommonTree.GetCharPositionInLine: Integer; 2480begin 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; 2490end; 2491 2492function TCommonTree.GetChildIndex: Integer; 2493begin 2494 Result := FChildIndex; 2495end; 2496 2497function TCommonTree.GetIsNil: Boolean; 2498begin 2499 Result := (FToken = nil); 2500end; 2501 2502function TCommonTree.GetLine: Integer; 2503begin 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; 2513end; 2514 2515function TCommonTree.GetParent: ITree; 2516begin 2517 Result := ITree(FParent); 2518end; 2519 2520function TCommonTree.GetStartIndex: Integer; 2521begin 2522 Result := FStartIndex; 2523end; 2524 2525function TCommonTree.GetStopIndex: Integer; 2526begin 2527 Result := FStopIndex; 2528end; 2529 2530function TCommonTree.GetText: String; 2531begin 2532 if (FToken = nil) then 2533 Result := '' 2534 else 2535 Result := FToken.Text; 2536end; 2537 2538function TCommonTree.GetToken: IToken; 2539begin 2540 Result := FToken; 2541end; 2542 2543function TCommonTree.GetTokenStartIndex: Integer; 2544begin 2545 if (FStartIndex = -1) and (FToken <> nil) then 2546 Result := FToken.TokenIndex 2547 else 2548 Result := FStartIndex; 2549end; 2550 2551function TCommonTree.GetTokenStopIndex: Integer; 2552begin 2553 if (FStopIndex = -1) and (FToken <> nil) then 2554 Result := FToken.TokenIndex 2555 else 2556 Result := FStopIndex; 2557end; 2558 2559function TCommonTree.GetTokenType: Integer; 2560begin 2561 if (FToken = nil) then 2562 Result := TToken.INVALID_TOKEN_TYPE 2563 else 2564 Result := FToken.TokenType; 2565end; 2566 2567procedure TCommonTree.SetChildIndex(const Value: Integer); 2568begin 2569 FChildIndex := Value; 2570end; 2571 2572procedure TCommonTree.SetParent(const Value: ITree); 2573begin 2574 FParent := Pointer(Value as ICommonTree); 2575end; 2576 2577procedure TCommonTree.SetStartIndex(const Value: Integer); 2578begin 2579 FStartIndex := Value; 2580end; 2581 2582procedure TCommonTree.SetStopIndex(const Value: Integer); 2583begin 2584 FStopIndex := Value; 2585end; 2586 2587procedure TCommonTree.SetTokenStartIndex(const Value: Integer); 2588begin 2589 FStartIndex := Value; 2590end; 2591 2592procedure TCommonTree.SetTokenStopIndex(const Value: Integer); 2593begin 2594 FStopIndex := Value; 2595end; 2596 2597function TCommonTree.ToString: String; 2598begin 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; 2609end; 2610 2611{ TCommonErrorNode } 2612 2613constructor TCommonErrorNode.Create(const AInput: ITokenStream; const AStart, 2614 AStop: IToken; const AException: ERecognitionException); 2615begin 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; 2630end; 2631 2632function TCommonErrorNode.GetIsNil: Boolean; 2633begin 2634 Result := False; 2635end; 2636 2637function TCommonErrorNode.GetText: String; 2638var 2639 I, J: Integer; 2640begin 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); 2647end; 2648 2649function TCommonErrorNode.GetTokenType: Integer; 2650begin 2651 Result := TToken.INVALID_TOKEN_TYPE; 2652end; 2653 2654function TCommonErrorNode.ToString: String; 2655begin 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 + '>'; 2674end; 2675 2676{ TBaseTreeAdaptor } 2677 2678procedure TBaseTreeAdaptor.AddChild(const T, Child: IANTLRInterface); 2679begin 2680 if Assigned(T) and Assigned(Child) then 2681 (T as ITree).AddChild(Child as ITree); 2682end; 2683 2684function TBaseTreeAdaptor.BecomeRoot(const NewRoot, 2685 OldRoot: IANTLRInterface): IANTLRInterface; 2686var 2687 NewRootTree, OldRootTree: ITree; 2688 NC: Integer; 2689begin 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; 2712end; 2713 2714function TBaseTreeAdaptor.BecomeRoot(const NewRoot: IToken; 2715 const OldRoot: IANTLRInterface): IANTLRInterface; 2716begin 2717 Result := BecomeRoot(CreateNode(NewRoot), OldRoot); 2718end; 2719 2720function TBaseTreeAdaptor.CreateNode(const TokenType: Integer; 2721 const FromToken: IToken): IANTLRInterface; 2722var 2723 Token: IToken; 2724begin 2725 Token := CreateToken(FromToken); 2726 Token.TokenType := TokenType; 2727 Result := CreateNode(Token); 2728end; 2729 2730function TBaseTreeAdaptor.CreateNode(const TokenType: Integer; 2731 const Text: String): IANTLRInterface; 2732var 2733 Token: IToken; 2734begin 2735 Token := CreateToken(TokenType, Text); 2736 Result := CreateNode(Token); 2737end; 2738 2739function TBaseTreeAdaptor.CreateNode(const TokenType: Integer; 2740 const FromToken: IToken; const Text: String): IANTLRInterface; 2741var 2742 Token: IToken; 2743begin 2744 Token := CreateToken(FromToken); 2745 Token.TokenType := TokenType; 2746 Token.Text := Text; 2747 Result := CreateNode(Token); 2748end; 2749 2750constructor TBaseTreeAdaptor.Create; 2751begin 2752 inherited Create; 2753 FUniqueNodeID := 1; 2754end; 2755 2756function TBaseTreeAdaptor.DeleteChild(const T: IANTLRInterface; 2757 const I: Integer): IANTLRInterface; 2758begin 2759 Result := (T as ITree).DeleteChild(I); 2760end; 2761 2762function TBaseTreeAdaptor.DupTree(const T, 2763 Parent: IANTLRInterface): IANTLRInterface; 2764var 2765 I, N: Integer; 2766 Child, NewSubTree: IANTLRInterface; 2767begin 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; 2784end; 2785 2786function TBaseTreeAdaptor.DupTree(const Tree: IANTLRInterface): IANTLRInterface; 2787begin 2788 Result := DupTree(Tree, nil); 2789end; 2790 2791function TBaseTreeAdaptor.ErrorNode(const Input: ITokenStream; const Start, 2792 Stop: IToken; const E: ERecognitionException): IANTLRInterface; 2793begin 2794 Result := TCommonErrorNode.Create(Input, Start, Stop, E); 2795end; 2796 2797function TBaseTreeAdaptor.GetChild(const T: IANTLRInterface; 2798 const I: Integer): IANTLRInterface; 2799begin 2800 Result := (T as ITree).GetChild(I); 2801end; 2802 2803function TBaseTreeAdaptor.GetChildCount(const T: IANTLRInterface): Integer; 2804begin 2805 Result := (T as ITree).ChildCount; 2806end; 2807 2808function TBaseTreeAdaptor.GetNilNode: IANTLRInterface; 2809begin 2810 Result := CreateNode(nil); 2811end; 2812 2813function TBaseTreeAdaptor.GetNodeText(const T: IANTLRInterface): String; 2814begin 2815 Result := (T as ITree).Text; 2816end; 2817 2818function TBaseTreeAdaptor.GetNodeType(const T: IANTLRInterface): Integer; 2819begin 2820 Result := 0; 2821end; 2822 2823function TBaseTreeAdaptor.GetUniqueID(const Node: IANTLRInterface): Integer; 2824begin 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; 2833end; 2834 2835function TBaseTreeAdaptor.IsNil(const Tree: IANTLRInterface): Boolean; 2836begin 2837 Result := (Tree as ITree).IsNil; 2838end; 2839 2840function TBaseTreeAdaptor.RulePostProcessing( 2841 const Root: IANTLRInterface): IANTLRInterface; 2842var 2843 R: ITree; 2844begin 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; 2860end; 2861 2862procedure TBaseTreeAdaptor.SetChild(const T: IANTLRInterface; const I: Integer; 2863 const Child: IANTLRInterface); 2864begin 2865 (T as ITree).SetChild(I, Child as ITree); 2866end; 2867 2868procedure TBaseTreeAdaptor.SetNodeText(const T: IANTLRInterface; 2869 const Text: String); 2870begin 2871 raise EInvalidOperation.Create('don''t know enough about Tree node'); 2872end; 2873 2874procedure TBaseTreeAdaptor.SetNodeType(const T: IANTLRInterface; 2875 const NodeType: Integer); 2876begin 2877 raise EInvalidOperation.Create('don''t know enough about Tree node'); 2878end; 2879 2880{ TCommonTreeAdaptor } 2881 2882function TCommonTreeAdaptor.CreateNode(const Payload: IToken): IANTLRInterface; 2883begin 2884 Result := TCommonTree.Create(Payload); 2885end; 2886 2887function TCommonTreeAdaptor.CreateToken(const TokenType: Integer; 2888 const Text: String): IToken; 2889begin 2890 Result := TCommonToken.Create(TokenType, Text); 2891end; 2892 2893function TCommonTreeAdaptor.CreateToken(const FromToken: IToken): IToken; 2894begin 2895 Result := TCommonToken.Create(FromToken); 2896end; 2897 2898function TCommonTreeAdaptor.DupNode( 2899 const TreeNode: IANTLRInterface): IANTLRInterface; 2900begin 2901 if (TreeNode = nil) then 2902 Result := nil 2903 else 2904 Result := (TreeNode as ITree).DupNode; 2905end; 2906 2907function TCommonTreeAdaptor.GetChild(const T: IANTLRInterface; 2908 const I: Integer): IANTLRInterface; 2909begin 2910 if (T = nil) then 2911 Result := nil 2912 else 2913 Result := (T as ITree).GetChild(I); 2914end; 2915 2916function TCommonTreeAdaptor.GetChildCount(const T: IANTLRInterface): Integer; 2917begin 2918 if (T = nil) then 2919 Result := 0 2920 else 2921 Result := (T as ITree).ChildCount; 2922end; 2923 2924function TCommonTreeAdaptor.GetChildIndex(const T: IANTLRInterface): Integer; 2925begin 2926 Result := (T as ITree).ChildIndex; 2927end; 2928 2929function TCommonTreeAdaptor.GetNodeText(const T: IANTLRInterface): String; 2930begin 2931 if (T = nil) then 2932 Result := '' 2933 else 2934 Result := (T as ITree).Text; 2935end; 2936 2937function TCommonTreeAdaptor.GetNodeType(const T: IANTLRInterface): Integer; 2938begin 2939 if (T = nil) then 2940 Result := TToken.INVALID_TOKEN_TYPE 2941 else 2942 Result := (T as ITree).TokenType; 2943end; 2944 2945function TCommonTreeAdaptor.GetParent( 2946 const T: IANTLRInterface): IANTLRInterface; 2947begin 2948 Result := (T as ITree).Parent; 2949end; 2950 2951function TCommonTreeAdaptor.GetToken(const TreeNode: IANTLRInterface): IToken; 2952var 2953 CommonTree: ICommonTree; 2954begin 2955 if Supports(TreeNode, ICommonTree, CommonTree) then 2956 Result := CommonTree.Token 2957 else 2958 Result := nil; // no idea what to do 2959end; 2960 2961function TCommonTreeAdaptor.GetTokenStartIndex( 2962 const T: IANTLRInterface): Integer; 2963begin 2964 if (T = nil) then 2965 Result := -1 2966 else 2967 Result := (T as ITree).TokenStartIndex; 2968end; 2969 2970function TCommonTreeAdaptor.GetTokenStopIndex( 2971 const T: IANTLRInterface): Integer; 2972begin 2973 if (T = nil) then 2974 Result := -1 2975 else 2976 Result := (T as ITree).TokenStopIndex; 2977end; 2978 2979procedure TCommonTreeAdaptor.ReplaceChildren(const Parent: IANTLRInterface; 2980 const StartChildIndex, StopChildIndex: Integer; const T: IANTLRInterface); 2981begin 2982 if Assigned(Parent) then 2983 (Parent as ITree).ReplaceChildren(StartChildIndex, StopChildIndex, T); 2984end; 2985 2986procedure TCommonTreeAdaptor.SetChildIdex(const T: IANTLRInterface; 2987 const Index: Integer); 2988begin 2989 (T as ITree).ChildIndex := Index; 2990end; 2991 2992procedure TCommonTreeAdaptor.SetParent(const T, Parent: IANTLRInterface); 2993begin 2994 (T as ITree).Parent := (Parent as ITree); 2995end; 2996 2997procedure TCommonTreeAdaptor.SetTokenBoundaries(const T: IANTLRInterface; 2998 const StartToken, StopToken: IToken); 2999var 3000 Start, Stop: Integer; 3001begin 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; 3017end; 3018 3019{ TCommonTreeNodeStream } 3020 3021procedure TCommonTreeNodeStream.AddNavigationNode(const TokenType: Integer); 3022var 3023 NavNode: IANTLRInterface; 3024begin 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); 3040end; 3041 3042procedure TCommonTreeNodeStream.Consume; 3043begin 3044 if (FP = -1) then 3045 FillBuffer; 3046 Inc(FP); 3047end; 3048 3049constructor TCommonTreeNodeStream.Create; 3050begin 3051 inherited; 3052 FP := -1; 3053end; 3054 3055constructor TCommonTreeNodeStream.Create(const ATree: IANTLRInterface); 3056begin 3057 Create(TCommonTreeAdaptor.Create, ATree); 3058end; 3059 3060constructor TCommonTreeNodeStream.Create(const AAdaptor: ITreeAdaptor; 3061 const ATree: IANTLRInterface); 3062begin 3063 Create(AAdaptor, ATree, DEFAULT_INITIAL_BUFFER_SIZE); 3064end; 3065 3066constructor TCommonTreeNodeStream.Create(const AAdaptor: ITreeAdaptor; 3067 const ATree: IANTLRInterface; const AInitialBufferSize: Integer); 3068begin 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'); 3077end; 3078 3079procedure TCommonTreeNodeStream.FillBuffer; 3080begin 3081 FillBuffer(FRoot); 3082 FP := 0; // buffer of nodes intialized now 3083end; 3084 3085procedure TCommonTreeNodeStream.FillBuffer(const T: IANTLRInterface); 3086var 3087 IsNil: Boolean; 3088 C, N: Integer; 3089begin 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); 3106end; 3107 3108function TCommonTreeNodeStream.Get(const I: Integer): IANTLRInterface; 3109begin 3110 if (FP = -1) then 3111 FillBuffer; 3112 Result := FNodes[I]; 3113end; 3114 3115function TCommonTreeNodeStream.GetCurrentSymbol: IANTLRInterface; 3116begin 3117 Result := LT(1); 3118end; 3119 3120function TCommonTreeNodeStream.GetHasUniqueNavigationNodes: Boolean; 3121begin 3122 Result := FUniqueNavigationNodes; 3123end; 3124 3125function TCommonTreeNodeStream.GetNodeIndex( 3126 const Node: IANTLRInterface): Integer; 3127var 3128 T: IANTLRInterface; 3129begin 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; 3139end; 3140 3141function TCommonTreeNodeStream.GetSourceName: String; 3142begin 3143 Result := GetTokenStream.SourceName; 3144end; 3145 3146function TCommonTreeNodeStream.GetTokenStream: ITokenStream; 3147begin 3148 Result := FTokens; 3149end; 3150 3151function TCommonTreeNodeStream.GetTreeAdaptor: ITreeAdaptor; 3152begin 3153 Result := FAdaptor; 3154end; 3155 3156function TCommonTreeNodeStream.GetTreeSource: IANTLRInterface; 3157begin 3158 Result := FRoot; 3159end; 3160 3161function TCommonTreeNodeStream.Index: Integer; 3162begin 3163 Result := FP; 3164end; 3165 3166function TCommonTreeNodeStream.LA(I: Integer): Integer; 3167begin 3168 Result := FAdaptor.GetNodeType(LT(I)); 3169end; 3170 3171function TCommonTreeNodeStream.LAChar(I: Integer): Char; 3172begin 3173 Result := Char(LA(I)); 3174end; 3175 3176function TCommonTreeNodeStream.LB(const K: Integer): IANTLRInterface; 3177begin 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]; 3185end; 3186 3187function TCommonTreeNodeStream.LT(const K: Integer): IANTLRInterface; 3188begin 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]; 3201end; 3202 3203function TCommonTreeNodeStream.Mark: Integer; 3204begin 3205 if (FP = -1) then 3206 FillBuffer; 3207 FLastMarker := Index; 3208 Result := FLastMarker; 3209end; 3210 3211function TCommonTreeNodeStream.Pop: Integer; 3212begin 3213 Result := FCalls.Pop; 3214 Seek(Result); 3215end; 3216 3217procedure TCommonTreeNodeStream.Push(const Index: Integer); 3218begin 3219 if (FCalls = nil) then 3220 FCalls := TStackList<Integer>.Create; 3221 FCalls.Push(FP); // save current index 3222 Seek(Index); 3223end; 3224 3225procedure TCommonTreeNodeStream.Release(const Marker: Integer); 3226begin 3227 // no resources to release 3228end; 3229 3230procedure TCommonTreeNodeStream.ReplaceChildren(const Parent: IANTLRInterface; 3231 const StartChildIndex, StopChildIndex: Integer; const T: IANTLRInterface); 3232begin 3233 if Assigned(Parent) then 3234 FAdaptor.ReplaceChildren(Parent, StartChildIndex, StopChildIndex, T); 3235end; 3236 3237procedure TCommonTreeNodeStream.Reset; 3238begin 3239 FP := -1; 3240 FLastMarker := 0; 3241 if Assigned(FCalls) then 3242 FCalls.Clear; 3243end; 3244 3245procedure TCommonTreeNodeStream.Rewind(const Marker: Integer); 3246begin 3247 Seek(Marker); 3248end; 3249 3250procedure TCommonTreeNodeStream.Rewind; 3251begin 3252 Seek(FLastMarker); 3253end; 3254 3255procedure TCommonTreeNodeStream.Seek(const Index: Integer); 3256begin 3257 if (FP = -1) then 3258 FillBuffer; 3259 FP := Index; 3260end; 3261 3262procedure TCommonTreeNodeStream.SetHasUniqueNavigationNodes( 3263 const Value: Boolean); 3264begin 3265 FUniqueNavigationNodes := Value; 3266end; 3267 3268procedure TCommonTreeNodeStream.SetTokenStream(const Value: ITokenStream); 3269begin 3270 FTokens := Value; 3271end; 3272 3273procedure TCommonTreeNodeStream.SetTreeAdaptor(const Value: ITreeAdaptor); 3274begin 3275 FAdaptor := Value; 3276end; 3277 3278function TCommonTreeNodeStream.Size: Integer; 3279begin 3280 if (FP = -1) then 3281 FillBuffer; 3282 Result := FNodes.Count; 3283end; 3284 3285function TCommonTreeNodeStream.ToString(const Start, 3286 Stop: IANTLRInterface): String; 3287var 3288 CommonTree: ICommonTree; 3289 I, BeginTokenIndex, EndTokenIndex: Integer; 3290 T: IANTLRInterface; 3291 Buf: TStringBuilder; 3292 Text: String; 3293begin 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; 3360end; 3361 3362function TCommonTreeNodeStream.ToString: String; 3363var 3364 Buf: TStringBuilder; 3365 T: IANTLRInterface; 3366begin 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; 3380end; 3381 3382function TCommonTreeNodeStream.ToTokenString(const Start, 3383 Stop: Integer): String; 3384var 3385 I: Integer; 3386 T: IANTLRInterface; 3387 Buf: TStringBuilder; 3388begin 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; 3404end; 3405 3406{ TParseTree } 3407 3408constructor TParseTree.Create(const ALabel: IANTLRInterface); 3409begin 3410 inherited Create; 3411 FPayload := ALabel; 3412end; 3413 3414function TParseTree.DupNode: ITree; 3415begin 3416 Result := nil; 3417end; 3418 3419function TParseTree.GetText: String; 3420begin 3421 Result := ToString; 3422end; 3423 3424function TParseTree.GetTokenStartIndex: Integer; 3425begin 3426 Result := 0; 3427end; 3428 3429function TParseTree.GetTokenStopIndex: Integer; 3430begin 3431 Result := 0; 3432end; 3433 3434function TParseTree.GetTokenType: Integer; 3435begin 3436 Result := 0; 3437end; 3438 3439procedure TParseTree.SetTokenStartIndex(const Value: Integer); 3440begin 3441 // No implementation 3442end; 3443 3444procedure TParseTree.SetTokenStopIndex(const Value: Integer); 3445begin 3446 // No implementation 3447end; 3448 3449function TParseTree.ToInputString: String; 3450var 3451 Buf: TStringBuilder; 3452begin 3453 Buf := TStringBuilder.Create; 3454 try 3455 _ToStringLeaves(Buf); 3456 Result := Buf.ToString; 3457 finally 3458 Buf.Free; 3459 end; 3460end; 3461 3462function TParseTree.ToString: String; 3463var 3464 T: IToken; 3465begin 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; 3475end; 3476 3477function TParseTree.ToStringWithHiddenTokens: String; 3478var 3479 Buf: TStringBuilder; 3480 Hidden: IToken; 3481 NodeText: String; 3482begin 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; 3497end; 3498 3499procedure TParseTree._ToStringLeaves(const Buf: TStringBuilder); 3500var 3501 T: IBaseTree; 3502begin 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); 3512end; 3513 3514{ ERewriteCardinalityException } 3515 3516constructor ERewriteCardinalityException.Create( 3517 const AElementDescription: String); 3518begin 3519 inherited Create(AElementDescription); 3520 FElementDescription := AElementDescription; 3521end; 3522 3523{ TRewriteRuleElementStream } 3524 3525procedure TRewriteRuleElementStream.Add(const El: IANTLRInterface); 3526begin 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; 3545end; 3546 3547constructor TRewriteRuleElementStream.Create(const AAdaptor: ITreeAdaptor; 3548 const AElementDescription: String); 3549begin 3550 inherited Create; 3551 FAdaptor := AAdaptor; 3552 FElementDescription := AElementDescription; 3553end; 3554 3555constructor TRewriteRuleElementStream.Create(const AAdaptor: ITreeAdaptor; 3556 const AElementDescription: String; const AOneElement: IANTLRInterface); 3557begin 3558 Create(AAdaptor, AElementDescription); 3559 Add(AOneElement); 3560end; 3561 3562constructor TRewriteRuleElementStream.Create(const AAdaptor: ITreeAdaptor; 3563 const AElementDescription: String; const AElements: IList<IANTLRInterface>); 3564begin 3565 Create(AAdaptor, AElementDescription); 3566 FElements := AElements; 3567end; 3568 3569function TRewriteRuleElementStream.GetDescription: String; 3570begin 3571 Result := FElementDescription; 3572end; 3573 3574function TRewriteRuleElementStream.HasNext: Boolean; 3575begin 3576 Result := ((FSingleElement <> nil) and (FCursor < 1)) 3577 or ((FElements <> nil) and (FCursor < FElements.Count)); 3578end; 3579 3580function TRewriteRuleElementStream.NextTree: IANTLRInterface; 3581begin 3582 Result := _Next; 3583end; 3584 3585procedure TRewriteRuleElementStream.Reset; 3586begin 3587 FCursor := 0; 3588 FDirty := True; 3589end; 3590 3591function TRewriteRuleElementStream.Size: Integer; 3592begin 3593 if Assigned(FSingleElement) then 3594 Result := 1 3595 else 3596 if Assigned(FElements) then 3597 Result := FElements.Count 3598 else 3599 Result := 0; 3600end; 3601 3602function TRewriteRuleElementStream.ToTree(const El: IANTLRInterface): IANTLRInterface; 3603begin 3604 Result := El; 3605end; 3606 3607function TRewriteRuleElementStream._Next: IANTLRInterface; 3608var 3609 Size: Integer; 3610begin 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; 3640end; 3641 3642{ TRewriteRuleNodeStream } 3643 3644function TRewriteRuleNodeStream.NextNode: IANTLRInterface; 3645begin 3646 Result := _Next; 3647end; 3648 3649function TRewriteRuleNodeStream.ToTree( 3650 const El: IANTLRInterface): IANTLRInterface; 3651begin 3652 Result := FAdaptor.DupNode(El); 3653end; 3654 3655{ TRewriteRuleSubtreeStream } 3656 3657function TRewriteRuleSubtreeStream.Dup( 3658 const O: IANTLRInterface): IANTLRInterface; 3659begin 3660 Result := FAdaptor.DupTree(O); 3661end; 3662 3663function TRewriteRuleSubtreeStream.DupNode( 3664 const O: IANTLRInterface): IANTLRInterface; 3665begin 3666 Result := FAdaptor.DupNode(O); 3667end; 3668 3669function TRewriteRuleSubtreeStream.FetchObject( 3670 const PH: TProcessHandler): IANTLRInterface; 3671begin 3672 if (RequiresDuplication) then 3673 // process the object 3674 Result := PH(_Next) 3675 else 3676 // test above then fetch 3677 Result := _Next; 3678end; 3679 3680function TRewriteRuleSubtreeStream.NextNode: IANTLRInterface; 3681begin 3682 // if necessary, dup (at most a single node since this is for making root nodes). 3683 Result := FetchObject(DupNode); 3684end; 3685 3686function TRewriteRuleSubtreeStream.NextTree: IANTLRInterface; 3687begin 3688 // if out of elements and size is 1, dup 3689 Result := FetchObject(Dup); 3690end; 3691 3692function TRewriteRuleSubtreeStream.RequiresDuplication: Boolean; 3693var 3694 Size: Integer; 3695begin 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)); 3699end; 3700 3701{ TRewriteRuleTokenStream } 3702 3703function TRewriteRuleTokenStream.NextNode: IANTLRInterface; 3704begin 3705 Result := FAdaptor.CreateNode(_Next as IToken) 3706end; 3707 3708function TRewriteRuleTokenStream.NextToken: IToken; 3709begin 3710 Result := _Next as IToken; 3711end; 3712 3713function TRewriteRuleTokenStream.ToTree( 3714 const El: IANTLRInterface): IANTLRInterface; 3715begin 3716 Result := El; 3717end; 3718 3719{ TTreeParser } 3720 3721constructor TTreeParser.Create(const AInput: ITreeNodeStream); 3722begin 3723 inherited Create; // highlight that we go to super to set state object 3724 SetTreeNodeStream(AInput); 3725end; 3726 3727constructor TTreeParser.Create(const AInput: ITreeNodeStream; 3728 const AState: IRecognizerSharedState); 3729begin 3730 inherited Create(AState); // share the state object with another parser 3731 SetTreeNodeStream(AInput); 3732end; 3733 3734function TTreeParser.GetCurrentInputSymbol( 3735 const Input: IIntStream): IANTLRInterface; 3736begin 3737 Result := FInput.LT(1); 3738end; 3739 3740function TTreeParser.GetErrorHeader(const E: ERecognitionException): String; 3741begin 3742 Result := GetGrammarFileName + ': node from '; 3743 if (E.ApproximateLineInfo) then 3744 Result := Result + 'after '; 3745 Result := Result + 'line ' + IntToStr(E.Line) + ':' + IntToStr(E.CharPositionInLine); 3746end; 3747 3748function TTreeParser.GetErrorMessage(const E: ERecognitionException; 3749 const TokenNames: TStringArray): String; 3750var 3751 Adaptor: ITreeAdaptor; 3752begin 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); 3763end; 3764 3765function TTreeParser.GetInput: IIntStream; 3766begin 3767 Result := FInput; 3768end; 3769 3770function TTreeParser.GetMissingSymbol(const Input: IIntStream; 3771 const E: ERecognitionException; const ExpectedTokenType: Integer; 3772 const Follow: IBitSet): IANTLRInterface; 3773var 3774 TokenText: String; 3775begin 3776 TokenText := '<missing ' + GetTokenNames[ExpectedTokenType] + '>'; 3777 Result := TCommonTree.Create(TCommonToken.Create(ExpectedTokenType, TokenText)); 3778end; 3779 3780function TTreeParser.GetSourceName: String; 3781begin 3782 Result := FInput.SourceName; 3783end; 3784 3785function TTreeParser.GetTreeNodeStream: ITreeNodeStream; 3786begin 3787 Result := FInput; 3788end; 3789 3790procedure TTreeParser.MatchAny(const Input: IIntStream); 3791var 3792 Look: IANTLRInterface; 3793 Level, TokenType: Integer; 3794begin 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 3820end; 3821 3822procedure TTreeParser.Mismatch(const Input: IIntStream; 3823 const TokenType: Integer; const Follow: IBitSet); 3824begin 3825 raise EMismatchedTreeNodeException.Create(TokenType, FInput); 3826end; 3827 3828procedure TTreeParser.Reset; 3829begin 3830 inherited; // reset all recognizer state variables 3831 if Assigned(FInput) then 3832 FInput.Seek(0); // rewind the input 3833end; 3834 3835procedure TTreeParser.SetTreeNodeStream(const Value: ITreeNodeStream); 3836begin 3837 FInput := Value; 3838end; 3839 3840procedure TTreeParser.TraceIn(const RuleName: String; const RuleIndex: Integer); 3841begin 3842 inherited TraceIn(RuleName, RuleIndex, FInput.LT(1).ToString); 3843end; 3844 3845procedure TTreeParser.TraceOut(const RuleName: String; 3846 const RuleIndex: Integer); 3847begin 3848 inherited TraceOut(RuleName, RuleIndex, FInput.LT(1).ToString); 3849end; 3850 3851{ TTreePatternLexer } 3852 3853constructor TTreePatternLexer.Create; 3854begin 3855 inherited; 3856 FSVal := TStringBuilder.Create; 3857end; 3858 3859procedure TTreePatternLexer.Consume; 3860begin 3861 Inc(FP); 3862 if (FP > FN) then 3863 FC := EOF 3864 else 3865 FC := Integer(FPattern[FP]); 3866end; 3867 3868constructor TTreePatternLexer.Create(const APattern: String); 3869begin 3870 Create; 3871 FPattern := APattern; 3872 FN := Length(FPattern); 3873 Consume; 3874end; 3875 3876destructor TTreePatternLexer.Destroy; 3877begin 3878 FSVal.Free; 3879 inherited; 3880end; 3881 3882function TTreePatternLexer.NextToken: Integer; 3883begin 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; 3966end; 3967 3968function TTreePatternLexer.SVal: String; 3969begin 3970 Result := FSVal.ToString; 3971end; 3972 3973{ TTreeWizard } 3974 3975function TTreeWizard.ComputeTokenTypes( 3976 const TokenNames: TStringArray): IDictionary<String, Integer>; 3977var 3978 TokenType: Integer; 3979begin 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; 3986end; 3987 3988constructor TTreeWizard.Create(const AAdaptor: ITreeAdaptor); 3989begin 3990 inherited Create; 3991 FAdaptor := AAdaptor; 3992end; 3993 3994constructor TTreeWizard.Create(const AAdaptor: ITreeAdaptor; 3995 const ATokenNameToTypeMap: IDictionary<String, Integer>); 3996begin 3997 inherited Create; 3998 FAdaptor := AAdaptor; 3999 FTokenNameToTypeMap := ATokenNameToTypeMap; 4000end; 4001 4002constructor TTreeWizard.Create(const AAdaptor: ITreeAdaptor; 4003 const TokenNames: TStringArray); 4004begin 4005 inherited Create; 4006 FAdaptor := AAdaptor; 4007 FTokenNameToTypeMap := ComputeTokenTypes(TokenNames); 4008end; 4009 4010function TTreeWizard.CreateTreeOrNode(const Pattern: String): IANTLRInterface; 4011var 4012 Tokenizer: ITreePatternLexer; 4013 Parser: ITreePatternParser; 4014begin 4015 Tokenizer := TTreePatternLexer.Create(Pattern); 4016 Parser := TTreePatternParser.Create(Tokenizer, Self, FAdaptor); 4017 Result := Parser.Pattern; 4018end; 4019 4020function TTreeWizard.Equals(const T1, T2: IANTLRInterface; 4021 const Adaptor: ITreeAdaptor): Boolean; 4022begin 4023 Result := _Equals(T1, T2, Adaptor); 4024end; 4025 4026function TTreeWizard.Equals(const T1, T2: IANTLRInterface): Boolean; 4027begin 4028 Result := _Equals(T1, T2, FAdaptor); 4029end; 4030 4031function TTreeWizard.Find(const T: IANTLRInterface; 4032 const Pattern: String): IList<IANTLRInterface>; 4033var 4034 Tokenizer: ITreePatternLexer; 4035 Parser: ITreePatternParser; 4036 TreePattern: ITreePattern; 4037 RootTokenType: Integer; 4038 Visitor: IContextVisitor; 4039begin 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); 4056end; 4057 4058function TTreeWizard.Find(const T: IANTLRInterface; 4059 const TokenType: Integer): IList<IANTLRInterface>; 4060begin 4061 Result := TList<IANTLRInterface>.Create; 4062 Visit(T, TokenType, TRecordAllElementsVisitor.Create(Result)); 4063end; 4064 4065function TTreeWizard.FindFirst(const T: IANTLRInterface; 4066 const TokenType: Integer): IANTLRInterface; 4067begin 4068 Result := nil; 4069end; 4070 4071function TTreeWizard.FindFirst(const T: IANTLRInterface; 4072 const Pattern: String): IANTLRInterface; 4073begin 4074 Result := nil; 4075end; 4076 4077function TTreeWizard.GetTokenType(const TokenName: String): Integer; 4078begin 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; 4083end; 4084 4085function TTreeWizard.Index( 4086 const T: IANTLRInterface): IDictionary<Integer, IList<IANTLRInterface>>; 4087begin 4088 Result := TDictionary<Integer, IList<IANTLRInterface>>.Create; 4089 _Index(T, Result); 4090end; 4091 4092function TTreeWizard.Parse(const T: IANTLRInterface; 4093 const Pattern: String): Boolean; 4094begin 4095 Result := Parse(T, Pattern, nil); 4096end; 4097 4098function TTreeWizard.Parse(const T: IANTLRInterface; const Pattern: String; 4099 const Labels: IDictionary<String, IANTLRInterface>): Boolean; 4100var 4101 Tokenizer: ITreePatternLexer; 4102 Parser: ITreePatternParser; 4103 TreePattern: ITreePattern; 4104begin 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); 4109end; 4110 4111procedure TTreeWizard.Visit(const T: IANTLRInterface; const Pattern: String; 4112 const Visitor: IContextVisitor); 4113var 4114 Tokenizer: ITreePatternLexer; 4115 Parser: ITreePatternParser; 4116 TreePattern: ITreePattern; 4117 RootTokenType: Integer; 4118 PatternVisitor: IContextVisitor; 4119begin 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); 4131end; 4132 4133class function TTreeWizard._Equals(const T1, T2: IANTLRInterface; 4134 const Adaptor: ITreeAdaptor): Boolean; 4135var 4136 I, N1, N2: Integer; 4137 Child1, Child2: IANTLRInterface; 4138begin 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; 4163end; 4164 4165procedure TTreeWizard._Index(const T: IANTLRInterface; 4166 const M: IDictionary<Integer, IList<IANTLRInterface>>); 4167var 4168 I, N, TType: Integer; 4169 Elements: IList<IANTLRInterface>; 4170begin 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); 4185end; 4186 4187function TTreeWizard._Parse(const T1: IANTLRInterface; const T2: ITreePattern; 4188 const Labels: IDictionary<String, IANTLRInterface>): Boolean; 4189var 4190 I, N1, N2: Integer; 4191 Child1: IANTLRInterface; 4192 Child2: ITreePattern; 4193begin 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; 4226end; 4227 4228procedure TTreeWizard._Visit(const T, Parent: IANTLRInterface; const ChildIndex, 4229 TokenType: Integer; const Visitor: IContextVisitor); 4230var 4231 I, N: Integer; 4232begin 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); 4241end; 4242 4243procedure TTreeWizard.Visit(const T: IANTLRInterface; const TokenType: Integer; 4244 const Visitor: IContextVisitor); 4245begin 4246 _Visit(T, nil, 0, TokenType, Visitor); 4247end; 4248 4249constructor TTreeWizard.Create(const TokenNames: TStringArray); 4250begin 4251 Create(nil, TokenNames); 4252end; 4253 4254{ TTreePatternParser } 4255 4256constructor TTreePatternParser.Create(const ATokenizer: ITreePatternLexer; 4257 const AWizard: ITreeWizard; const AAdaptor: ITreeAdaptor); 4258begin 4259 inherited Create; 4260 FTokenizer := ATokenizer; 4261 FWizard := AWizard; 4262 FAdaptor := AAdaptor; 4263 FTokenType := FTokenizer.NextToken; // kickstart 4264end; 4265 4266function TTreePatternParser.ParseNode: IANTLRInterface; 4267var 4268 Lbl, TokenName, Text, Arg: String; 4269 WildcardPayload: IToken; 4270 Node: TTreeWizard.ITreePattern; 4271 TreeNodeType: Integer; 4272begin 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; 4326end; 4327 4328function TTreePatternParser.ParseTree: IANTLRInterface; 4329var 4330 Subtree, Child: IANTLRInterface; 4331begin 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; 4367end; 4368 4369function TTreePatternParser.Pattern: IANTLRInterface; 4370var 4371 Node: IANTLRInterface; 4372begin 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; 4386end; 4387 4388{ TTreeWizard.TVisitor } 4389 4390procedure TTreeWizard.TVisitor.Visit(const T, Parent: IANTLRInterface; 4391 const ChildIndex: Integer; 4392 const Labels: IDictionary<String, IANTLRInterface>); 4393begin 4394 Visit(T); 4395end; 4396 4397{ TTreeWizard.TRecordAllElementsVisitor } 4398 4399constructor TTreeWizard.TRecordAllElementsVisitor.Create( 4400 const AList: IList<IANTLRInterface>); 4401begin 4402 inherited Create; 4403 FList := AList; 4404end; 4405 4406procedure TTreeWizard.TRecordAllElementsVisitor.Visit(const T: IANTLRInterface); 4407begin 4408 FList.Add(T); 4409end; 4410 4411{ TTreeWizard.TPatternMatchingContextVisitor } 4412 4413constructor TTreeWizard.TPatternMatchingContextVisitor.Create( 4414 const AOwner: TTreeWizard; const APattern: ITreePattern; 4415 const AList: IList<IANTLRInterface>); 4416begin 4417 inherited Create; 4418 FOwner := AOwner; 4419 FPattern := APattern; 4420 FList := AList; 4421end; 4422 4423procedure TTreeWizard.TPatternMatchingContextVisitor.Visit(const T, 4424 Parent: IANTLRInterface; const ChildIndex: Integer; 4425 const Labels: IDictionary<String, IANTLRInterface>); 4426begin 4427 if (FOwner._Parse(T, FPattern, nil)) then 4428 FList.Add(T); 4429end; 4430 4431{ TTreeWizard.TInvokeVisitorOnPatternMatchContextVisitor } 4432 4433constructor TTreeWizard.TInvokeVisitorOnPatternMatchContextVisitor.Create( 4434 const AOwner: TTreeWizard; const APattern: ITreePattern; 4435 const AVisitor: IContextVisitor); 4436begin 4437 inherited Create; 4438 FOwner := AOwner; 4439 FPattern := APattern; 4440 FVisitor := AVisitor; 4441 FLabels := TDictionary<String, IANTLRInterface>.Create; 4442end; 4443 4444procedure TTreeWizard.TInvokeVisitorOnPatternMatchContextVisitor.Visit(const T, 4445 Parent: IANTLRInterface; const ChildIndex: Integer; 4446 const UnusedLabels: IDictionary<String, IANTLRInterface>); 4447begin 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); 4452end; 4453 4454{ TTreeWizard.TTreePattern } 4455 4456function TTreeWizard.TTreePattern.GetHasTextArg: Boolean; 4457begin 4458 Result := FHasTextArg; 4459end; 4460 4461function TTreeWizard.TTreePattern.GetTokenLabel: String; 4462begin 4463 Result := FLabel; 4464end; 4465 4466procedure TTreeWizard.TTreePattern.SetHasTextArg(const Value: Boolean); 4467begin 4468 FHasTextArg := Value; 4469end; 4470 4471procedure TTreeWizard.TTreePattern.SetTokenLabel(const Value: String); 4472begin 4473 FLabel := Value; 4474end; 4475 4476function TTreeWizard.TTreePattern.ToString: String; 4477begin 4478 if (FLabel <> '') then 4479 Result := '%' + FLabel + ':' + inherited ToString 4480 else 4481 Result := inherited ToString; 4482end; 4483 4484{ TTreeWizard.TTreePatternTreeAdaptor } 4485 4486function TTreeWizard.TTreePatternTreeAdaptor.CreateNode( 4487 const Payload: IToken): IANTLRInterface; 4488begin 4489 Result := TTreePattern.Create(Payload); 4490end; 4491 4492{ TTreeRuleReturnScope } 4493 4494function TTreeRuleReturnScope.GetStart: IANTLRInterface; 4495begin 4496 Result := FStart; 4497end; 4498 4499procedure TTreeRuleReturnScope.SetStart(const Value: IANTLRInterface); 4500begin 4501 FStart := Value; 4502end; 4503 4504{ TUnBufferedTreeNodeStream } 4505 4506procedure TUnBufferedTreeNodeStream.AddLookahead(const Node: IANTLRInterface); 4507var 4508 Bigger: TANTLRInterfaceArray; 4509 I, RemainderHeadToEnd: Integer; 4510begin 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; 4529end; 4530 4531procedure TUnBufferedTreeNodeStream.AddNavigationNode(const TokenType: Integer); 4532var 4533 NavNode: IANTLRInterface; 4534begin 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); 4550end; 4551 4552procedure TUnBufferedTreeNodeStream.Consume; 4553begin 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); 4559end; 4560 4561constructor TUnBufferedTreeNodeStream.Create; 4562begin 4563 inherited; 4564 SetLength(FLookAhead,INITIAL_LOOKAHEAD_BUFFER_SIZE); 4565 FNodeStack := TStackList<IANTLRInterface>.Create; 4566 FIndexStack := TStackList<Integer>.Create; 4567end; 4568 4569constructor TUnBufferedTreeNodeStream.Create(const ATree: IANTLRInterface); 4570begin 4571 Create(TCommonTreeAdaptor.Create, ATree); 4572end; 4573 4574constructor TUnBufferedTreeNodeStream.Create(const AAdaptor: ITreeAdaptor; 4575 const ATree: IANTLRInterface); 4576begin 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'); 4584end; 4585 4586procedure TUnBufferedTreeNodeStream.Fill(const K: Integer); 4587var 4588 I, N: Integer; 4589begin 4590 N := LookaheadSize; 4591 for I := 1 to K - N do 4592 MoveNext; // get at least k-depth lookahead nodes 4593end; 4594 4595function TUnBufferedTreeNodeStream.Get(const I: Integer): IANTLRInterface; 4596begin 4597 raise EInvalidOperation.Create('stream is unbuffered'); 4598end; 4599 4600function TUnBufferedTreeNodeStream.GetCurrent: IANTLRInterface; 4601begin 4602 Result := FCurrentEnumerationNode; 4603end; 4604 4605function TUnBufferedTreeNodeStream.GetHasUniqueNavigationNodes: Boolean; 4606begin 4607 Result := FUniqueNavigationNodes; 4608end; 4609 4610function TUnBufferedTreeNodeStream.GetSourceName: String; 4611begin 4612 Result := GetTokenStream.SourceName; 4613end; 4614 4615function TUnBufferedTreeNodeStream.GetTokenStream: ITokenStream; 4616begin 4617 Result := FTokens; 4618end; 4619 4620function TUnBufferedTreeNodeStream.GetTreeAdaptor: ITreeAdaptor; 4621begin 4622 Result := FAdaptor; 4623end; 4624 4625function TUnBufferedTreeNodeStream.GetTreeSource: IANTLRInterface; 4626begin 4627 Result := FRoot; 4628end; 4629 4630function TUnBufferedTreeNodeStream.HandleRootNode: IANTLRInterface; 4631begin 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; 4645end; 4646 4647function TUnBufferedTreeNodeStream.Index: Integer; 4648begin 4649 Result := FAbsoluteNodeIndex + 1; 4650end; 4651 4652function TUnBufferedTreeNodeStream.LA(I: Integer): Integer; 4653var 4654 T: IANTLRInterface; 4655begin 4656 T := LT(I); 4657 if (T = nil) then 4658 Result := TToken.INVALID_TOKEN_TYPE 4659 else 4660 Result := FAdaptor.GetNodeType(T); 4661end; 4662 4663function TUnBufferedTreeNodeStream.LAChar(I: Integer): Char; 4664begin 4665 Result := Char(LA(I)); 4666end; 4667 4668function TUnBufferedTreeNodeStream.LookaheadSize: Integer; 4669begin 4670 if (FTail < FHead) then 4671 Result := Length(FLookahead) - FHead + FTail 4672 else 4673 Result := FTail - FHead; 4674end; 4675 4676function TUnBufferedTreeNodeStream.LT(const K: Integer): IANTLRInterface; 4677begin 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)]; 4689end; 4690 4691function TUnBufferedTreeNodeStream.Mark: Integer; 4692var 4693 State: ITreeWalkState; 4694 I, N, K: Integer; 4695 LA: TANTLRInterfaceArray; 4696begin 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; 4732end; 4733 4734function TUnBufferedTreeNodeStream.MoveNext: Boolean; 4735begin 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; 4769end; 4770 4771procedure TUnBufferedTreeNodeStream.Release(const Marker: Integer); 4772begin 4773 // unwind any other markers made after marker and release marker 4774 FMarkDepth := Marker; 4775 // release this marker 4776 Dec(FMarkDepth); 4777end; 4778 4779procedure TUnBufferedTreeNodeStream.ReplaceChildren( 4780 const Parent: IANTLRInterface; const StartChildIndex, StopChildIndex: Integer; 4781 const T: IANTLRInterface); 4782begin 4783 raise EInvalidOperation.Create('can''t do stream rewrites yet'); 4784end; 4785 4786procedure TUnBufferedTreeNodeStream.Reset; 4787begin 4788 FCurrentNode := FRoot; 4789 FPreviousNode := nil; 4790 FCurrentChildIndex := -1; 4791 FAbsoluteNodeIndex := -1; 4792 FHead := 0; 4793 FTail := 0; 4794end; 4795 4796procedure TUnBufferedTreeNodeStream.Rewind(const Marker: Integer); 4797var 4798 State: ITreeWalkState; 4799begin 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); 4818end; 4819 4820procedure TUnBufferedTreeNodeStream.Rewind; 4821begin 4822 Rewind(FLastMarker); 4823end; 4824 4825procedure TUnBufferedTreeNodeStream.Seek(const Index: Integer); 4826begin 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; 4833end; 4834 4835procedure TUnBufferedTreeNodeStream.SetHasUniqueNavigationNodes( 4836 const Value: Boolean); 4837begin 4838 FUniqueNavigationNodes := Value; 4839end; 4840 4841procedure TUnBufferedTreeNodeStream.SetTokenStream(const Value: ITokenStream); 4842begin 4843 FTokens := Value; 4844end; 4845 4846function TUnBufferedTreeNodeStream.Size: Integer; 4847var 4848 S: ICommonTreeNodeStream; 4849begin 4850 S := TCommonTreeNodeStream.Create(FRoot); 4851 Result := S.Size; 4852end; 4853 4854function TUnBufferedTreeNodeStream.ToString: String; 4855begin 4856 Result := ToString(FRoot, nil); 4857end; 4858 4859procedure TUnBufferedTreeNodeStream.ToStringWork(const P, Stop: IANTLRInterface; 4860 const Buf: TStringBuilder); 4861var 4862 Text: String; 4863 C, N: Integer; 4864begin 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; 4891end; 4892 4893function TUnBufferedTreeNodeStream.VisitChild( 4894 const Child: Integer): IANTLRInterface; 4895begin 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; 4908end; 4909 4910procedure TUnBufferedTreeNodeStream.WalkBackToMostRecentNodeWithUnvisitedChildren; 4911begin 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; 4930end; 4931 4932function TUnBufferedTreeNodeStream.ToString(const Start, 4933 Stop: IANTLRInterface): String; 4934var 4935 BeginTokenIndex, EndTokenIndex: Integer; 4936 Buf: TStringBuilder; 4937begin 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; 4962end; 4963 4964{ TUnBufferedTreeNodeStream.TTreeWalkState } 4965 4966function TUnBufferedTreeNodeStream.TTreeWalkState.GetAbsoluteNodeIndex: Integer; 4967begin 4968 Result := FAbsoluteNodeIndex; 4969end; 4970 4971function TUnBufferedTreeNodeStream.TTreeWalkState.GetCurrentChildIndex: Integer; 4972begin 4973 Result := FCurrentChildIndex; 4974end; 4975 4976function TUnBufferedTreeNodeStream.TTreeWalkState.GetCurrentNode: IANTLRInterface; 4977begin 4978 Result := FCurrentNode; 4979end; 4980 4981function TUnBufferedTreeNodeStream.TTreeWalkState.GetIndexStackSize: integer; 4982begin 4983 Result := FIndexStackSize; 4984end; 4985 4986function TUnBufferedTreeNodeStream.TTreeWalkState.GetLookAhead: TANTLRInterfaceArray; 4987begin 4988 Result := FLookAhead; 4989end; 4990 4991function TUnBufferedTreeNodeStream.TTreeWalkState.GetNodeStackSize: Integer; 4992begin 4993 Result := FNodeStackSize; 4994end; 4995 4996function TUnBufferedTreeNodeStream.TTreeWalkState.GetPreviousNode: IANTLRInterface; 4997begin 4998 Result := FPreviousNode; 4999end; 5000 5001procedure TUnBufferedTreeNodeStream.TTreeWalkState.SetAbsoluteNodeIndex( 5002 const Value: Integer); 5003begin 5004 FAbsoluteNodeIndex := Value; 5005end; 5006 5007procedure TUnBufferedTreeNodeStream.TTreeWalkState.SetCurrentChildIndex( 5008 const Value: Integer); 5009begin 5010 FCurrentChildIndex := Value; 5011end; 5012 5013procedure TUnBufferedTreeNodeStream.TTreeWalkState.SetCurrentNode( 5014 const Value: IANTLRInterface); 5015begin 5016 FCurrentNode := Value; 5017end; 5018 5019procedure TUnBufferedTreeNodeStream.TTreeWalkState.SetIndexStackSize( 5020 const Value: integer); 5021begin 5022 FIndexStackSize := Value; 5023end; 5024 5025procedure TUnBufferedTreeNodeStream.TTreeWalkState.SetLookAhead( 5026 const Value: TANTLRInterfaceArray); 5027begin 5028 FLookAhead := Value; 5029end; 5030 5031procedure TUnBufferedTreeNodeStream.TTreeWalkState.SetNodeStackSize( 5032 const Value: Integer); 5033begin 5034 FNodeStackSize := Value; 5035end; 5036 5037procedure TUnBufferedTreeNodeStream.TTreeWalkState.SetPreviousNode( 5038 const Value: IANTLRInterface); 5039begin 5040 FPreviousNode := Value; 5041end; 5042 5043{ Utilities } 5044 5045var 5046 EmptyCommonTree: ICommonTree = nil; 5047 5048function Def(const X: ICommonTree): ICommonTree; overload; 5049begin 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; 5058end; 5059 5060initialization 5061 TTree.Initialize; 5062 5063end. 5064