1 unit Antlr.Runtime.Tree; 2 (* 3 [The "BSD licence"] 4 Copyright (c) 2008 Erik van Bilsen 5 Copyright (c) 2005-2007 Kunle Odutola 6 All rights reserved. 7 8 Redistribution and use in source and binary forms, with or without 9 modification, are permitted provided that the following conditions 10 are met: 11 1. Redistributions of source code MUST RETAIN the above copyright 12 notice, this list of conditions and the following disclaimer. 13 2. Redistributions in binary form MUST REPRODUCE the above copyright 14 notice, this list of conditions and the following disclaimer in 15 the documentation and/or other materials provided with the 16 distribution. 17 3. The name of the author may not be used to endorse or promote products 18 derived from this software without specific prior WRITTEN permission. 19 4. Unless explicitly state otherwise, any contribution intentionally 20 submitted for inclusion in this work to the copyright owner or licensor 21 shall be under the terms and conditions of this license, without any 22 additional terms or conditions. 23 24 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 25 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 26 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 27 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 28 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 29 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 30 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 31 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 32 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 33 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 *) 35 36 interface 37 38 {$IF CompilerVersion < 20} 39 {$MESSAGE ERROR 'You need Delphi 2009 or higher to use the Antlr runtime'} 40 {$IFEND} 41 42 uses 43 Classes, 44 SysUtils, 45 Antlr.Runtime, 46 Antlr.Runtime.Tools, 47 Antlr.Runtime.Collections; 48 49 type 50 /// <summary> 51 /// How to create and navigate trees. Rather than have a separate factory 52 /// and adaptor, I've merged them. Makes sense to encapsulate. 53 /// 54 /// This takes the place of the tree construction code generated in the 55 /// generated code in 2.x and the ASTFactory. 56 /// 57 /// I do not need to know the type of a tree at all so they are all 58 /// generic Objects. This may increase the amount of typecasting needed. :( 59 /// </summary> 60 ITreeAdaptor = interface(IANTLRInterface) 61 ['{F9DEB286-F555-4CC8-A51A-93F3F649B248}'] 62 { Methods } 63 64 // C o n s t r u c t i o n 65 66 /// <summary> 67 /// Create a tree node from Token object; for CommonTree type trees, 68 /// then the token just becomes the payload. 69 /// </summary> 70 /// <remarks> 71 /// This is the most common create call. Override if you want another kind of node to be built. 72 /// </remarks> 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 1124 type 1125 TTree = class sealed 1126 strict private 1127 class var 1128 FINVALID_NODE: ITree; 1129 private 1130 class procedure Initialize; static; 1131 public 1132 class property INVALID_NODE: ITree read FINVALID_NODE; 1133 end; 1134 1135 TBaseTree = class abstract(TANTLRObject, IBaseTree, ITree) 1136 protected 1137 { ITree / IBaseTree } 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 } 2111 function Def(const X: ICommonTree): ICommonTree; overload; 2112 2113 implementation 2114 2115 uses 2116 Math; 2117 2118 { TTree } 2119 2120 class procedure TTree.Initialize; 2121 begin 2122 FINVALID_NODE := TCommonTree.Create(TToken.INVALID_TOKEN); 2123 end; 2124 2125 { TBaseTree } 2126 2127 constructor TBaseTree.Create; 2128 begin 2129 inherited; 2130 end; 2131 2132 procedure TBaseTree.AddChild(const T: ITree); 2133 var 2134 ChildTree: IBaseTree; 2135 C: IBaseTree; 2136 begin 2137 if (T = nil) then 2138 Exit; 2139 2140 ChildTree := T as IBaseTree; 2141 if ChildTree.IsNil then // t is an empty node possibly with children 2142 begin 2143 if Assigned(FChildren) and SameObj(FChildren, ChildTree.Children) then 2144 raise EInvalidOperation.Create('Attempt to add child list to itself'); 2145 2146 // just add all of childTree's children to this 2147 if Assigned(ChildTree.Children) then 2148 begin 2149 if Assigned(FChildren) then // must copy, this has children already 2150 begin 2151 for C in ChildTree.Children do 2152 begin 2153 FChildren.Add(C); 2154 // handle double-link stuff for each child of nil root 2155 C.Parent := Self; 2156 C.ChildIndex := FChildren.Count - 1; 2157 end; 2158 end 2159 else begin 2160 // no children for this but t has children; just set pointer 2161 // call general freshener routine 2162 FChildren := ChildTree.Children; 2163 FreshenParentAndChildIndexes; 2164 end; 2165 end; 2166 end 2167 else 2168 begin 2169 // child is not nil (don't care about children) 2170 if (FChildren = nil) then 2171 begin 2172 FChildren := CreateChildrenList; // create children list on demand 2173 end; 2174 FChildren.Add(ChildTree); 2175 ChildTree.Parent := Self; 2176 ChildTree.ChildIndex := FChildren.Count - 1; 2177 end; 2178 end; 2179 2180 procedure TBaseTree.AddChildren(const Kids: IList<IBaseTree>); 2181 var 2182 T: IBaseTree; 2183 begin 2184 for T in Kids do 2185 AddChild(T); 2186 end; 2187 2188 constructor TBaseTree.Create(const ANode: ITree); 2189 begin 2190 Create; 2191 // No default implementation 2192 end; 2193 2194 function TBaseTree.CreateChildrenList: IList<IBaseTree>; 2195 begin 2196 Result := TList<IBaseTree>.Create; 2197 end; 2198 2199 function TBaseTree.DeleteChild(const I: Integer): IANTLRInterface; 2200 begin 2201 if (FChildren = nil) then 2202 Result := nil 2203 else 2204 begin 2205 Result := FChildren[I]; 2206 FChildren.Delete(I); 2207 // walk rest and decrement their child indexes 2208 FreshenParentAndChildIndexes(I); 2209 end; 2210 end; 2211 2212 procedure TBaseTree.FreshenParentAndChildIndexes(const Offset: Integer); 2213 var 2214 N, C: Integer; 2215 Child: ITree; 2216 begin 2217 N := GetChildCount; 2218 for C := Offset to N - 1 do 2219 begin 2220 Child := GetChild(C); 2221 Child.ChildIndex := C; 2222 Child.Parent := Self; 2223 end; 2224 end; 2225 2226 procedure TBaseTree.FreshenParentAndChildIndexes; 2227 begin 2228 FreshenParentAndChildIndexes(0); 2229 end; 2230 2231 function TBaseTree.GetCharPositionInLine: Integer; 2232 begin 2233 Result := 0; 2234 end; 2235 2236 function TBaseTree.GetChild(const I: Integer): ITree; 2237 begin 2238 if (FChildren = nil) or (I >= FChildren.Count) then 2239 Result := nil 2240 else 2241 Result := FChildren[I]; 2242 end; 2243 2244 function TBaseTree.GetChildCount: Integer; 2245 begin 2246 if Assigned(FChildren) then 2247 Result := FChildren.Count 2248 else 2249 Result := 0; 2250 end; 2251 2252 function TBaseTree.GetChildIndex: Integer; 2253 begin 2254 // No default implementation 2255 Result := 0; 2256 end; 2257 2258 function TBaseTree.GetChildren: IList<IBaseTree>; 2259 begin 2260 Result := FChildren; 2261 end; 2262 2263 function TBaseTree.GetIsNil: Boolean; 2264 begin 2265 Result := False; 2266 end; 2267 2268 function TBaseTree.GetLine: Integer; 2269 begin 2270 Result := 0; 2271 end; 2272 2273 function TBaseTree.GetParent: ITree; 2274 begin 2275 // No default implementation 2276 Result := nil; 2277 end; 2278 2279 procedure TBaseTree.ReplaceChildren(const StartChildIndex, 2280 StopChildIndex: Integer; const T: IANTLRInterface); 2281 var 2282 ReplacingHowMany, ReplacingWithHowMany, NumNewChildren, Delta, I, J: Integer; 2283 IndexToDelete, C, ReplacedSoFar: Integer; 2284 NewTree, Killed: IBaseTree; 2285 NewChildren: IList<IBaseTree>; 2286 Child: IBaseTree; 2287 begin 2288 if (FChildren = nil) then 2289 raise EArgumentException.Create('indexes invalid; no children in list'); 2290 ReplacingHowMany := StopChildIndex - StartChildIndex + 1; 2291 NewTree := T as IBaseTree; 2292 2293 // normalize to a list of children to add: newChildren 2294 if (NewTree.IsNil) then 2295 NewChildren := NewTree.Children 2296 else 2297 begin 2298 NewChildren := TList<IBaseTree>.Create; 2299 NewChildren.Add(NewTree); 2300 end; 2301 2302 ReplacingWithHowMany := NewChildren.Count; 2303 NumNewChildren := NewChildren.Count; 2304 Delta := ReplacingHowMany - ReplacingWithHowMany; 2305 2306 // if same number of nodes, do direct replace 2307 if (Delta = 0) then 2308 begin 2309 J := 0; // index into new children 2310 for I := StartChildIndex to StopChildIndex do 2311 begin 2312 Child := NewChildren[J]; 2313 FChildren[I] := Child; 2314 Child.Parent := Self; 2315 Child.ChildIndex := I; 2316 Inc(J); 2317 end; 2318 end 2319 else 2320 if (Delta > 0) then 2321 begin 2322 // fewer new nodes than there were 2323 // set children and then delete extra 2324 for J := 0 to NumNewChildren - 1 do 2325 FChildren[StartChildIndex + J] := NewChildren[J]; 2326 IndexToDelete := StartChildIndex + NumNewChildren; 2327 for C := IndexToDelete to StopChildIndex do 2328 begin 2329 // delete same index, shifting everybody down each time 2330 Killed := FChildren[IndexToDelete]; 2331 FChildren.Delete(IndexToDelete); 2332 end; 2333 FreshenParentAndChildIndexes(StartChildIndex); 2334 end 2335 else 2336 begin 2337 // more new nodes than were there before 2338 // fill in as many children as we can (replacingHowMany) w/o moving data 2339 ReplacedSoFar := 0; 2340 while (ReplacedSoFar < ReplacingHowMany) do 2341 begin 2342 FChildren[StartChildIndex + ReplacedSoFar] := NewChildren[ReplacedSoFar]; 2343 Inc(ReplacedSoFar); 2344 end; 2345 2346 // replacedSoFar has correct index for children to add 2347 while (ReplacedSoFar < ReplacingWithHowMany) do 2348 begin 2349 FChildren.Insert(StartChildIndex + ReplacedSoFar,NewChildren[ReplacedSoFar]); 2350 Inc(ReplacedSoFar); 2351 end; 2352 2353 FreshenParentAndChildIndexes(StartChildIndex); 2354 end; 2355 end; 2356 2357 procedure TBaseTree.SanityCheckParentAndChildIndexes; 2358 begin 2359 SanityCheckParentAndChildIndexes(nil, -1); 2360 end; 2361 2362 procedure TBaseTree.SanityCheckParentAndChildIndexes(const Parent: ITree; 2363 const I: Integer); 2364 var 2365 N, C: Integer; 2366 Child: ICommonTree; 2367 begin 2368 if not SameObj(Parent, GetParent) then 2369 raise EArgumentException.Create('parents don''t match; expected ' 2370 + Parent.ToString + ' found ' + GetParent.ToString); 2371 2372 if (I <> GetChildIndex) then 2373 raise EArgumentException.Create('child indexes don''t match; expected ' 2374 + IntToStr(I) + ' found ' + IntToStr(GetChildIndex)); 2375 2376 N := GetChildCount; 2377 for C := 0 to N - 1 do 2378 begin 2379 Child := GetChild(C) as ICommonTree; 2380 Child.SanityCheckParentAndChildIndexes(Self, C); 2381 end; 2382 end; 2383 2384 procedure TBaseTree.SetChild(const I: Integer; const T: ITree); 2385 begin 2386 if (T = nil) then 2387 Exit; 2388 2389 if T.IsNil then 2390 raise EArgumentException.Create('Cannot set single child to a list'); 2391 2392 if (FChildren = nil) then 2393 begin 2394 FChildren := CreateChildrenList; 2395 end; 2396 2397 FChildren[I] := T as IBaseTree; 2398 T.Parent := Self; 2399 T.ChildIndex := I; 2400 end; 2401 2402 procedure TBaseTree.SetChildIndex(const Value: Integer); 2403 begin 2404 // No default implementation 2405 end; 2406 2407 procedure TBaseTree.SetParent(const Value: ITree); 2408 begin 2409 // No default implementation 2410 end; 2411 2412 function TBaseTree.ToStringTree: String; 2413 var 2414 Buf: TStringBuilder; 2415 I: Integer; 2416 T: IBaseTree; 2417 begin 2418 if (FChildren = nil) or (FChildren.Count = 0) then 2419 Result := ToString 2420 else 2421 begin 2422 Buf := TStringBuilder.Create; 2423 try 2424 if (not GetIsNil) then 2425 begin 2426 Buf.Append('('); 2427 Buf.Append(ToString); 2428 Buf.Append(' '); 2429 end; 2430 2431 for I := 0 to FChildren.Count - 1 do 2432 begin 2433 T := FChildren[I]; 2434 if (I > 0) then 2435 Buf.Append(' '); 2436 Buf.Append(T.ToStringTree); 2437 end; 2438 2439 if (not GetIsNil) then 2440 Buf.Append(')'); 2441 2442 Result := Buf.ToString; 2443 finally 2444 Buf.Free; 2445 end; 2446 end; 2447 end; 2448 2449 { TCommonTree } 2450 2451 constructor TCommonTree.Create; 2452 begin 2453 inherited; 2454 FStartIndex := -1; 2455 FStopIndex := -1; 2456 FChildIndex := -1; 2457 end; 2458 2459 constructor TCommonTree.Create(const ANode: ICommonTree); 2460 begin 2461 inherited Create(ANode); 2462 FToken := ANode.Token; 2463 FStartIndex := ANode.StartIndex; 2464 FStopIndex := ANode.StopIndex; 2465 FChildIndex := -1; 2466 end; 2467 2468 constructor TCommonTree.Create(const AToken: IToken); 2469 begin 2470 Create; 2471 FToken := AToken; 2472 end; 2473 2474 function TCommonTree.DupNode: ITree; 2475 begin 2476 Result := TCommonTree.Create(Self) as ICommonTree; 2477 end; 2478 2479 function TCommonTree.GetCharPositionInLine: Integer; 2480 begin 2481 if (FToken = nil) or (FToken.CharPositionInLine = -1) then 2482 begin 2483 if (GetChildCount > 0) then 2484 Result := GetChild(0).CharPositionInLine 2485 else 2486 Result := 0; 2487 end 2488 else 2489 Result := FToken.CharPositionInLine; 2490 end; 2491 2492 function TCommonTree.GetChildIndex: Integer; 2493 begin 2494 Result := FChildIndex; 2495 end; 2496 2497 function TCommonTree.GetIsNil: Boolean; 2498 begin 2499 Result := (FToken = nil); 2500 end; 2501 2502 function TCommonTree.GetLine: Integer; 2503 begin 2504 if (FToken = nil) or (FToken.Line = 0) then 2505 begin 2506 if (GetChildCount > 0) then 2507 Result := GetChild(0).Line 2508 else 2509 Result := 0 2510 end 2511 else 2512 Result := FToken.Line; 2513 end; 2514 2515 function TCommonTree.GetParent: ITree; 2516 begin 2517 Result := ITree(FParent); 2518 end; 2519 2520 function TCommonTree.GetStartIndex: Integer; 2521 begin 2522 Result := FStartIndex; 2523 end; 2524 2525 function TCommonTree.GetStopIndex: Integer; 2526 begin 2527 Result := FStopIndex; 2528 end; 2529 2530 function TCommonTree.GetText: String; 2531 begin 2532 if (FToken = nil) then 2533 Result := '' 2534 else 2535 Result := FToken.Text; 2536 end; 2537 2538 function TCommonTree.GetToken: IToken; 2539 begin 2540 Result := FToken; 2541 end; 2542 2543 function TCommonTree.GetTokenStartIndex: Integer; 2544 begin 2545 if (FStartIndex = -1) and (FToken <> nil) then 2546 Result := FToken.TokenIndex 2547 else 2548 Result := FStartIndex; 2549 end; 2550 2551 function TCommonTree.GetTokenStopIndex: Integer; 2552 begin 2553 if (FStopIndex = -1) and (FToken <> nil) then 2554 Result := FToken.TokenIndex 2555 else 2556 Result := FStopIndex; 2557 end; 2558 2559 function TCommonTree.GetTokenType: Integer; 2560 begin 2561 if (FToken = nil) then 2562 Result := TToken.INVALID_TOKEN_TYPE 2563 else 2564 Result := FToken.TokenType; 2565 end; 2566 2567 procedure TCommonTree.SetChildIndex(const Value: Integer); 2568 begin 2569 FChildIndex := Value; 2570 end; 2571 2572 procedure TCommonTree.SetParent(const Value: ITree); 2573 begin 2574 FParent := Pointer(Value as ICommonTree); 2575 end; 2576 2577 procedure TCommonTree.SetStartIndex(const Value: Integer); 2578 begin 2579 FStartIndex := Value; 2580 end; 2581 2582 procedure TCommonTree.SetStopIndex(const Value: Integer); 2583 begin 2584 FStopIndex := Value; 2585 end; 2586 2587 procedure TCommonTree.SetTokenStartIndex(const Value: Integer); 2588 begin 2589 FStartIndex := Value; 2590 end; 2591 2592 procedure TCommonTree.SetTokenStopIndex(const Value: Integer); 2593 begin 2594 FStopIndex := Value; 2595 end; 2596 2597 function TCommonTree.ToString: String; 2598 begin 2599 if (GetIsNil) then 2600 Result := 'nil' 2601 else 2602 if (GetTokenType = TToken.INVALID_TOKEN_TYPE) then 2603 Result := '<errornode>' 2604 else 2605 if (FToken = nil) then 2606 Result := '' 2607 else 2608 Result := FToken.Text; 2609 end; 2610 2611 { TCommonErrorNode } 2612 2613 constructor TCommonErrorNode.Create(const AInput: ITokenStream; const AStart, 2614 AStop: IToken; const AException: ERecognitionException); 2615 begin 2616 inherited Create; 2617 if (AStop = nil) or ((AStop.TokenIndex < AStart.TokenIndex) 2618 and (AStop.TokenType <> TToken.EOF)) 2619 then 2620 // sometimes resync does not consume a token (when LT(1) is 2621 // in follow set). So, stop will be 1 to left to start. adjust. 2622 // Also handle case where start is the first token and no token 2623 // is consumed during recovery; LT(-1) will return null. 2624 FStop := AStart 2625 else 2626 FStop := AStop; 2627 FInput := AInput; 2628 FStart := AStart; 2629 FTrappedException := AException; 2630 end; 2631 2632 function TCommonErrorNode.GetIsNil: Boolean; 2633 begin 2634 Result := False; 2635 end; 2636 2637 function TCommonErrorNode.GetText: String; 2638 var 2639 I, J: Integer; 2640 begin 2641 I := FStart.TokenIndex; 2642 if (FStop.TokenType = TToken.EOF) then 2643 J := (FInput as ITokenStream).Size 2644 else 2645 J := FStop.TokenIndex; 2646 Result := (FInput as ITokenStream).ToString(I, J); 2647 end; 2648 2649 function TCommonErrorNode.GetTokenType: Integer; 2650 begin 2651 Result := TToken.INVALID_TOKEN_TYPE; 2652 end; 2653 2654 function TCommonErrorNode.ToString: String; 2655 begin 2656 if (FTrappedException is EMissingTokenException) then 2657 Result := '<missing type: ' 2658 + IntToStr(EMissingTokenException(FTrappedException).MissingType) + '>' 2659 else 2660 if (FTrappedException is EUnwantedTokenException) then 2661 Result := '<extraneous: ' 2662 + EUnwantedTokenException(FTrappedException).UnexpectedToken.ToString 2663 + ', resync=' + GetText + '>' 2664 else 2665 if (FTrappedException is EMismatchedTokenException) then 2666 Result := '<mismatched token: ' + FTrappedException.Token.ToString 2667 + ', resync=' + GetText + '>' 2668 else 2669 if (FTrappedException is ENoViableAltException) then 2670 Result := '<unexpected: ' + FTrappedException.Token.ToString 2671 + ', resync=' + GetText + '>' 2672 else 2673 Result := '<error: ' + GetText + '>'; 2674 end; 2675 2676 { TBaseTreeAdaptor } 2677 2678 procedure TBaseTreeAdaptor.AddChild(const T, Child: IANTLRInterface); 2679 begin 2680 if Assigned(T) and Assigned(Child) then 2681 (T as ITree).AddChild(Child as ITree); 2682 end; 2683 2684 function TBaseTreeAdaptor.BecomeRoot(const NewRoot, 2685 OldRoot: IANTLRInterface): IANTLRInterface; 2686 var 2687 NewRootTree, OldRootTree: ITree; 2688 NC: Integer; 2689 begin 2690 NewRootTree := NewRoot as ITree; 2691 OldRootTree := OldRoot as ITree; 2692 if (OldRoot = nil) then 2693 Result := NewRoot 2694 else 2695 begin 2696 // handle ^(nil real-node) 2697 if (NewRootTree.IsNil) then 2698 begin 2699 NC := NewRootTree.ChildCount; 2700 if (NC = 1) then 2701 NewRootTree := NewRootTree.GetChild(0) 2702 else 2703 if (NC > 1) then 2704 raise Exception.Create('more than one node as root'); 2705 end; 2706 // add oldRoot to newRoot; AddChild takes care of case where oldRoot 2707 // is a flat list (i.e., nil-rooted tree). All children of oldRoot 2708 // are added to newRoot. 2709 NewRootTree.AddChild(OldRootTree); 2710 Result := NewRootTree; 2711 end; 2712 end; 2713 2714 function TBaseTreeAdaptor.BecomeRoot(const NewRoot: IToken; 2715 const OldRoot: IANTLRInterface): IANTLRInterface; 2716 begin 2717 Result := BecomeRoot(CreateNode(NewRoot), OldRoot); 2718 end; 2719 2720 function TBaseTreeAdaptor.CreateNode(const TokenType: Integer; 2721 const FromToken: IToken): IANTLRInterface; 2722 var 2723 Token: IToken; 2724 begin 2725 Token := CreateToken(FromToken); 2726 Token.TokenType := TokenType; 2727 Result := CreateNode(Token); 2728 end; 2729 2730 function TBaseTreeAdaptor.CreateNode(const TokenType: Integer; 2731 const Text: String): IANTLRInterface; 2732 var 2733 Token: IToken; 2734 begin 2735 Token := CreateToken(TokenType, Text); 2736 Result := CreateNode(Token); 2737 end; 2738 2739 function TBaseTreeAdaptor.CreateNode(const TokenType: Integer; 2740 const FromToken: IToken; const Text: String): IANTLRInterface; 2741 var 2742 Token: IToken; 2743 begin 2744 Token := CreateToken(FromToken); 2745 Token.TokenType := TokenType; 2746 Token.Text := Text; 2747 Result := CreateNode(Token); 2748 end; 2749 2750 constructor TBaseTreeAdaptor.Create; 2751 begin 2752 inherited Create; 2753 FUniqueNodeID := 1; 2754 end; 2755 2756 function TBaseTreeAdaptor.DeleteChild(const T: IANTLRInterface; 2757 const I: Integer): IANTLRInterface; 2758 begin 2759 Result := (T as ITree).DeleteChild(I); 2760 end; 2761 2762 function TBaseTreeAdaptor.DupTree(const T, 2763 Parent: IANTLRInterface): IANTLRInterface; 2764 var 2765 I, N: Integer; 2766 Child, NewSubTree: IANTLRInterface; 2767 begin 2768 if (T = nil) then 2769 Result := nil 2770 else 2771 begin 2772 Result := DupNode(T); 2773 // ensure new subtree root has parent/child index set 2774 SetChildIdex(Result, GetChildIndex(T)); 2775 SetParent(Result, Parent); 2776 N := GetChildCount(T); 2777 for I := 0 to N - 1 do 2778 begin 2779 Child := GetChild(T, I); 2780 NewSubTree := DupTree(Child, T); 2781 AddChild(Result, NewSubTree); 2782 end; 2783 end; 2784 end; 2785 2786 function TBaseTreeAdaptor.DupTree(const Tree: IANTLRInterface): IANTLRInterface; 2787 begin 2788 Result := DupTree(Tree, nil); 2789 end; 2790 2791 function TBaseTreeAdaptor.ErrorNode(const Input: ITokenStream; const Start, 2792 Stop: IToken; const E: ERecognitionException): IANTLRInterface; 2793 begin 2794 Result := TCommonErrorNode.Create(Input, Start, Stop, E); 2795 end; 2796 2797 function TBaseTreeAdaptor.GetChild(const T: IANTLRInterface; 2798 const I: Integer): IANTLRInterface; 2799 begin 2800 Result := (T as ITree).GetChild(I); 2801 end; 2802 2803 function TBaseTreeAdaptor.GetChildCount(const T: IANTLRInterface): Integer; 2804 begin 2805 Result := (T as ITree).ChildCount; 2806 end; 2807 2808 function TBaseTreeAdaptor.GetNilNode: IANTLRInterface; 2809 begin 2810 Result := CreateNode(nil); 2811 end; 2812 2813 function TBaseTreeAdaptor.GetNodeText(const T: IANTLRInterface): String; 2814 begin 2815 Result := (T as ITree).Text; 2816 end; 2817 2818 function TBaseTreeAdaptor.GetNodeType(const T: IANTLRInterface): Integer; 2819 begin 2820 Result := 0; 2821 end; 2822 2823 function TBaseTreeAdaptor.GetUniqueID(const Node: IANTLRInterface): Integer; 2824 begin 2825 if (FTreeToUniqueIDMap = nil) then 2826 FTreeToUniqueIDMap := TDictionary<IANTLRInterface, Integer>.Create; 2827 if (not FTreeToUniqueIDMap.TryGetValue(Node, Result)) then 2828 begin 2829 Result := FUniqueNodeID; 2830 FTreeToUniqueIDMap[Node] := Result; 2831 Inc(FUniqueNodeID); 2832 end; 2833 end; 2834 2835 function TBaseTreeAdaptor.IsNil(const Tree: IANTLRInterface): Boolean; 2836 begin 2837 Result := (Tree as ITree).IsNil; 2838 end; 2839 2840 function TBaseTreeAdaptor.RulePostProcessing( 2841 const Root: IANTLRInterface): IANTLRInterface; 2842 var 2843 R: ITree; 2844 begin 2845 R := Root as ITree; 2846 if Assigned(R) and (R.IsNil) then 2847 begin 2848 if (R.ChildCount = 0) then 2849 R := nil 2850 else 2851 if (R.ChildCount = 1) then 2852 begin 2853 R := R.GetChild(0); 2854 // whoever invokes rule will set parent and child index 2855 R.Parent := nil; 2856 R.ChildIndex := -1; 2857 end; 2858 end; 2859 Result := R; 2860 end; 2861 2862 procedure TBaseTreeAdaptor.SetChild(const T: IANTLRInterface; const I: Integer; 2863 const Child: IANTLRInterface); 2864 begin 2865 (T as ITree).SetChild(I, Child as ITree); 2866 end; 2867 2868 procedure TBaseTreeAdaptor.SetNodeText(const T: IANTLRInterface; 2869 const Text: String); 2870 begin 2871 raise EInvalidOperation.Create('don''t know enough about Tree node'); 2872 end; 2873 2874 procedure TBaseTreeAdaptor.SetNodeType(const T: IANTLRInterface; 2875 const NodeType: Integer); 2876 begin 2877 raise EInvalidOperation.Create('don''t know enough about Tree node'); 2878 end; 2879 2880 { TCommonTreeAdaptor } 2881 2882 function TCommonTreeAdaptor.CreateNode(const Payload: IToken): IANTLRInterface; 2883 begin 2884 Result := TCommonTree.Create(Payload); 2885 end; 2886 2887 function TCommonTreeAdaptor.CreateToken(const TokenType: Integer; 2888 const Text: String): IToken; 2889 begin 2890 Result := TCommonToken.Create(TokenType, Text); 2891 end; 2892 2893 function TCommonTreeAdaptor.CreateToken(const FromToken: IToken): IToken; 2894 begin 2895 Result := TCommonToken.Create(FromToken); 2896 end; 2897 2898 function TCommonTreeAdaptor.DupNode( 2899 const TreeNode: IANTLRInterface): IANTLRInterface; 2900 begin 2901 if (TreeNode = nil) then 2902 Result := nil 2903 else 2904 Result := (TreeNode as ITree).DupNode; 2905 end; 2906 2907 function TCommonTreeAdaptor.GetChild(const T: IANTLRInterface; 2908 const I: Integer): IANTLRInterface; 2909 begin 2910 if (T = nil) then 2911 Result := nil 2912 else 2913 Result := (T as ITree).GetChild(I); 2914 end; 2915 2916 function TCommonTreeAdaptor.GetChildCount(const T: IANTLRInterface): Integer; 2917 begin 2918 if (T = nil) then 2919 Result := 0 2920 else 2921 Result := (T as ITree).ChildCount; 2922 end; 2923 2924 function TCommonTreeAdaptor.GetChildIndex(const T: IANTLRInterface): Integer; 2925 begin 2926 Result := (T as ITree).ChildIndex; 2927 end; 2928 2929 function TCommonTreeAdaptor.GetNodeText(const T: IANTLRInterface): String; 2930 begin 2931 if (T = nil) then 2932 Result := '' 2933 else 2934 Result := (T as ITree).Text; 2935 end; 2936 2937 function TCommonTreeAdaptor.GetNodeType(const T: IANTLRInterface): Integer; 2938 begin 2939 if (T = nil) then 2940 Result := TToken.INVALID_TOKEN_TYPE 2941 else 2942 Result := (T as ITree).TokenType; 2943 end; 2944 2945 function TCommonTreeAdaptor.GetParent( 2946 const T: IANTLRInterface): IANTLRInterface; 2947 begin 2948 Result := (T as ITree).Parent; 2949 end; 2950 2951 function TCommonTreeAdaptor.GetToken(const TreeNode: IANTLRInterface): IToken; 2952 var 2953 CommonTree: ICommonTree; 2954 begin 2955 if Supports(TreeNode, ICommonTree, CommonTree) then 2956 Result := CommonTree.Token 2957 else 2958 Result := nil; // no idea what to do 2959 end; 2960 2961 function TCommonTreeAdaptor.GetTokenStartIndex( 2962 const T: IANTLRInterface): Integer; 2963 begin 2964 if (T = nil) then 2965 Result := -1 2966 else 2967 Result := (T as ITree).TokenStartIndex; 2968 end; 2969 2970 function TCommonTreeAdaptor.GetTokenStopIndex( 2971 const T: IANTLRInterface): Integer; 2972 begin 2973 if (T = nil) then 2974 Result := -1 2975 else 2976 Result := (T as ITree).TokenStopIndex; 2977 end; 2978 2979 procedure TCommonTreeAdaptor.ReplaceChildren(const Parent: IANTLRInterface; 2980 const StartChildIndex, StopChildIndex: Integer; const T: IANTLRInterface); 2981 begin 2982 if Assigned(Parent) then 2983 (Parent as ITree).ReplaceChildren(StartChildIndex, StopChildIndex, T); 2984 end; 2985 2986 procedure TCommonTreeAdaptor.SetChildIdex(const T: IANTLRInterface; 2987 const Index: Integer); 2988 begin 2989 (T as ITree).ChildIndex := Index; 2990 end; 2991 2992 procedure TCommonTreeAdaptor.SetParent(const T, Parent: IANTLRInterface); 2993 begin 2994 (T as ITree).Parent := (Parent as ITree); 2995 end; 2996 2997 procedure TCommonTreeAdaptor.SetTokenBoundaries(const T: IANTLRInterface; 2998 const StartToken, StopToken: IToken); 2999 var 3000 Start, Stop: Integer; 3001 begin 3002 if Assigned(T) then 3003 begin 3004 if Assigned(StartToken) then 3005 Start := StartToken.TokenIndex 3006 else 3007 Start := 0; 3008 3009 if Assigned(StopToken) then 3010 Stop := StopToken.TokenIndex 3011 else 3012 Stop := 0; 3013 3014 (T as ITree).TokenStartIndex := Start; 3015 (T as ITree).TokenStopIndex := Stop; 3016 end; 3017 end; 3018 3019 { TCommonTreeNodeStream } 3020 3021 procedure TCommonTreeNodeStream.AddNavigationNode(const TokenType: Integer); 3022 var 3023 NavNode: IANTLRInterface; 3024 begin 3025 if (TokenType = TToken.DOWN) then 3026 begin 3027 if (GetHasUniqueNavigationNodes) then 3028 NavNode := FAdaptor.CreateNode(TToken.DOWN, 'DOWN') 3029 else 3030 NavNode := FDown; 3031 end 3032 else 3033 begin 3034 if (GetHasUniqueNavigationNodes) then 3035 NavNode := FAdaptor.CreateNode(TToken.UP, 'UP') 3036 else 3037 NavNode := FUp; 3038 end; 3039 FNodes.Add(NavNode); 3040 end; 3041 3042 procedure TCommonTreeNodeStream.Consume; 3043 begin 3044 if (FP = -1) then 3045 FillBuffer; 3046 Inc(FP); 3047 end; 3048 3049 constructor TCommonTreeNodeStream.Create; 3050 begin 3051 inherited; 3052 FP := -1; 3053 end; 3054 3055 constructor TCommonTreeNodeStream.Create(const ATree: IANTLRInterface); 3056 begin 3057 Create(TCommonTreeAdaptor.Create, ATree); 3058 end; 3059 3060 constructor TCommonTreeNodeStream.Create(const AAdaptor: ITreeAdaptor; 3061 const ATree: IANTLRInterface); 3062 begin 3063 Create(AAdaptor, ATree, DEFAULT_INITIAL_BUFFER_SIZE); 3064 end; 3065 3066 constructor TCommonTreeNodeStream.Create(const AAdaptor: ITreeAdaptor; 3067 const ATree: IANTLRInterface; const AInitialBufferSize: Integer); 3068 begin 3069 Create; 3070 FRoot := ATree; 3071 FAdaptor := AAdaptor; 3072 FNodes := TList<IANTLRInterface>.Create; 3073 FNodes.Capacity := AInitialBufferSize; 3074 FDown := FAdaptor.CreateNode(TToken.DOWN, 'DOWN'); 3075 FUp := FAdaptor.CreateNode(TToken.UP, 'UP'); 3076 FEof := FAdaptor.CreateNode(TToken.EOF, 'EOF'); 3077 end; 3078 3079 procedure TCommonTreeNodeStream.FillBuffer; 3080 begin 3081 FillBuffer(FRoot); 3082 FP := 0; // buffer of nodes intialized now 3083 end; 3084 3085 procedure TCommonTreeNodeStream.FillBuffer(const T: IANTLRInterface); 3086 var 3087 IsNil: Boolean; 3088 C, N: Integer; 3089 begin 3090 IsNil := FAdaptor.IsNil(T); 3091 if (not IsNil) then 3092 FNodes.Add(T); // add this node 3093 3094 // add DOWN node if t has children 3095 N := FAdaptor.GetChildCount(T); 3096 if (not IsNil) and (N > 0) then 3097 AddNavigationNode(TToken.DOWN); 3098 3099 // and now add all its children 3100 for C := 0 to N - 1 do 3101 FillBuffer(FAdaptor.GetChild(T, C)); 3102 3103 // add UP node if t has children 3104 if (not IsNil) and (N > 0) then 3105 AddNavigationNode(TToken.UP); 3106 end; 3107 3108 function TCommonTreeNodeStream.Get(const I: Integer): IANTLRInterface; 3109 begin 3110 if (FP = -1) then 3111 FillBuffer; 3112 Result := FNodes[I]; 3113 end; 3114 3115 function TCommonTreeNodeStream.GetCurrentSymbol: IANTLRInterface; 3116 begin 3117 Result := LT(1); 3118 end; 3119 3120 function TCommonTreeNodeStream.GetHasUniqueNavigationNodes: Boolean; 3121 begin 3122 Result := FUniqueNavigationNodes; 3123 end; 3124 3125 function TCommonTreeNodeStream.GetNodeIndex( 3126 const Node: IANTLRInterface): Integer; 3127 var 3128 T: IANTLRInterface; 3129 begin 3130 if (FP = -1) then 3131 FillBuffer; 3132 for Result := 0 to FNodes.Count - 1 do 3133 begin 3134 T := FNodes[Result]; 3135 if (T = Node) then 3136 Exit; 3137 end; 3138 Result := -1; 3139 end; 3140 3141 function TCommonTreeNodeStream.GetSourceName: String; 3142 begin 3143 Result := GetTokenStream.SourceName; 3144 end; 3145 3146 function TCommonTreeNodeStream.GetTokenStream: ITokenStream; 3147 begin 3148 Result := FTokens; 3149 end; 3150 3151 function TCommonTreeNodeStream.GetTreeAdaptor: ITreeAdaptor; 3152 begin 3153 Result := FAdaptor; 3154 end; 3155 3156 function TCommonTreeNodeStream.GetTreeSource: IANTLRInterface; 3157 begin 3158 Result := FRoot; 3159 end; 3160 3161 function TCommonTreeNodeStream.Index: Integer; 3162 begin 3163 Result := FP; 3164 end; 3165 3166 function TCommonTreeNodeStream.LA(I: Integer): Integer; 3167 begin 3168 Result := FAdaptor.GetNodeType(LT(I)); 3169 end; 3170 3171 function TCommonTreeNodeStream.LAChar(I: Integer): Char; 3172 begin 3173 Result := Char(LA(I)); 3174 end; 3175 3176 function TCommonTreeNodeStream.LB(const K: Integer): IANTLRInterface; 3177 begin 3178 if (K = 0) then 3179 Result := nil 3180 else 3181 if ((FP - K) < 0) then 3182 Result := nil 3183 else 3184 Result := FNodes[FP - K]; 3185 end; 3186 3187 function TCommonTreeNodeStream.LT(const K: Integer): IANTLRInterface; 3188 begin 3189 if (FP = -1) then 3190 FillBuffer; 3191 if (K = 0) then 3192 Result := nil 3193 else 3194 if (K < 0) then 3195 Result := LB(-K) 3196 else 3197 if ((FP + K - 1) >= FNodes.Count) then 3198 Result := FEof 3199 else 3200 Result := FNodes[FP + K - 1]; 3201 end; 3202 3203 function TCommonTreeNodeStream.Mark: Integer; 3204 begin 3205 if (FP = -1) then 3206 FillBuffer; 3207 FLastMarker := Index; 3208 Result := FLastMarker; 3209 end; 3210 3211 function TCommonTreeNodeStream.Pop: Integer; 3212 begin 3213 Result := FCalls.Pop; 3214 Seek(Result); 3215 end; 3216 3217 procedure TCommonTreeNodeStream.Push(const Index: Integer); 3218 begin 3219 if (FCalls = nil) then 3220 FCalls := TStackList<Integer>.Create; 3221 FCalls.Push(FP); // save current index 3222 Seek(Index); 3223 end; 3224 3225 procedure TCommonTreeNodeStream.Release(const Marker: Integer); 3226 begin 3227 // no resources to release 3228 end; 3229 3230 procedure TCommonTreeNodeStream.ReplaceChildren(const Parent: IANTLRInterface; 3231 const StartChildIndex, StopChildIndex: Integer; const T: IANTLRInterface); 3232 begin 3233 if Assigned(Parent) then 3234 FAdaptor.ReplaceChildren(Parent, StartChildIndex, StopChildIndex, T); 3235 end; 3236 3237 procedure TCommonTreeNodeStream.Reset; 3238 begin 3239 FP := -1; 3240 FLastMarker := 0; 3241 if Assigned(FCalls) then 3242 FCalls.Clear; 3243 end; 3244 3245 procedure TCommonTreeNodeStream.Rewind(const Marker: Integer); 3246 begin 3247 Seek(Marker); 3248 end; 3249 3250 procedure TCommonTreeNodeStream.Rewind; 3251 begin 3252 Seek(FLastMarker); 3253 end; 3254 3255 procedure TCommonTreeNodeStream.Seek(const Index: Integer); 3256 begin 3257 if (FP = -1) then 3258 FillBuffer; 3259 FP := Index; 3260 end; 3261 3262 procedure TCommonTreeNodeStream.SetHasUniqueNavigationNodes( 3263 const Value: Boolean); 3264 begin 3265 FUniqueNavigationNodes := Value; 3266 end; 3267 3268 procedure TCommonTreeNodeStream.SetTokenStream(const Value: ITokenStream); 3269 begin 3270 FTokens := Value; 3271 end; 3272 3273 procedure TCommonTreeNodeStream.SetTreeAdaptor(const Value: ITreeAdaptor); 3274 begin 3275 FAdaptor := Value; 3276 end; 3277 3278 function TCommonTreeNodeStream.Size: Integer; 3279 begin 3280 if (FP = -1) then 3281 FillBuffer; 3282 Result := FNodes.Count; 3283 end; 3284 3285 function TCommonTreeNodeStream.ToString(const Start, 3286 Stop: IANTLRInterface): String; 3287 var 3288 CommonTree: ICommonTree; 3289 I, BeginTokenIndex, EndTokenIndex: Integer; 3290 T: IANTLRInterface; 3291 Buf: TStringBuilder; 3292 Text: String; 3293 begin 3294 WriteLn('ToString'); 3295 if (Start = nil) or (Stop = nil) then 3296 Exit; 3297 if (FP = -1) then 3298 FillBuffer; 3299 3300 if Supports(Start, ICommonTree, CommonTree) then 3301 Write('ToString: ' + CommonTree.Token.ToString + ', ') 3302 else 3303 WriteLn(Start.ToString); 3304 3305 if Supports(Stop, ICommonTree, CommonTree) then 3306 WriteLn(CommonTree.Token.ToString) 3307 else 3308 WriteLn(Stop.ToString); 3309 3310 // if we have the token stream, use that to dump text in order 3311 if Assigned(FTokens) then 3312 begin 3313 BeginTokenIndex := FAdaptor.GetTokenStartIndex(Start); 3314 EndTokenIndex := FAdaptor.GetTokenStartIndex(Stop); 3315 // if it's a tree, use start/stop index from start node 3316 // else use token range from start/stop nodes 3317 if (FAdaptor.GetNodeType(Stop) = TToken.UP) then 3318 EndTokenIndex := FAdaptor.GetTokenStopIndex(Start) 3319 else 3320 if (FAdaptor.GetNodeType(Stop) = TToken.EOF) then 3321 EndTokenIndex := Size - 2; // don't use EOF 3322 Result := FTokens.ToString(BeginTokenIndex, EndTokenIndex); 3323 Exit; 3324 end; 3325 3326 // walk nodes looking for start 3327 T := nil; 3328 I := 0; 3329 while (I < FNodes.Count) do 3330 begin 3331 T := FNodes[I]; 3332 if SameObj(T, Start) then 3333 Break; 3334 Inc(I); 3335 end; 3336 3337 // now walk until we see stop, filling string buffer with text 3338 Buf := TStringBuilder.Create; 3339 try 3340 T := FNodes[I]; 3341 while (T <> Stop) do 3342 begin 3343 Text := FAdaptor.GetNodeText(T); 3344 if (Text = '') then 3345 Text := ' ' + IntToStr(FAdaptor.GetNodeType(T)); 3346 Buf.Append(Text); 3347 Inc(I); 3348 T := FNodes[I]; 3349 end; 3350 3351 // include stop node too 3352 Text := FAdaptor.GetNodeText(Stop); 3353 if (Text = '') then 3354 Text := ' ' + IntToStr(FAdaptor.GetNodeType(Stop)); 3355 Buf.Append(Text); 3356 Result := Buf.ToString; 3357 finally 3358 Buf.Free; 3359 end; 3360 end; 3361 3362 function TCommonTreeNodeStream.ToString: String; 3363 var 3364 Buf: TStringBuilder; 3365 T: IANTLRInterface; 3366 begin 3367 if (FP = -1) then 3368 FillBuffer; 3369 Buf := TStringBuilder.Create; 3370 try 3371 for T in FNodes do 3372 begin 3373 Buf.Append(' '); 3374 Buf.Append(FAdaptor.GetNodeType(T)); 3375 end; 3376 Result := Buf.ToString; 3377 finally 3378 Buf.Free; 3379 end; 3380 end; 3381 3382 function TCommonTreeNodeStream.ToTokenString(const Start, 3383 Stop: Integer): String; 3384 var 3385 I: Integer; 3386 T: IANTLRInterface; 3387 Buf: TStringBuilder; 3388 begin 3389 if (FP = -1) then 3390 FillBuffer; 3391 Buf := TStringBuilder.Create; 3392 try 3393 for I := Stop to Min(FNodes.Count - 1, Stop) do 3394 begin 3395 T := FNodes[I]; 3396 Buf.Append(' '); 3397 Buf.Append(FAdaptor.GetToken(T).ToString); 3398 end; 3399 3400 Result := Buf.ToString; 3401 finally 3402 Buf.Free; 3403 end; 3404 end; 3405 3406 { TParseTree } 3407 3408 constructor TParseTree.Create(const ALabel: IANTLRInterface); 3409 begin 3410 inherited Create; 3411 FPayload := ALabel; 3412 end; 3413 3414 function TParseTree.DupNode: ITree; 3415 begin 3416 Result := nil; 3417 end; 3418 3419 function TParseTree.GetText: String; 3420 begin 3421 Result := ToString; 3422 end; 3423 3424 function TParseTree.GetTokenStartIndex: Integer; 3425 begin 3426 Result := 0; 3427 end; 3428 3429 function TParseTree.GetTokenStopIndex: Integer; 3430 begin 3431 Result := 0; 3432 end; 3433 3434 function TParseTree.GetTokenType: Integer; 3435 begin 3436 Result := 0; 3437 end; 3438 3439 procedure TParseTree.SetTokenStartIndex(const Value: Integer); 3440 begin 3441 // No implementation 3442 end; 3443 3444 procedure TParseTree.SetTokenStopIndex(const Value: Integer); 3445 begin 3446 // No implementation 3447 end; 3448 3449 function TParseTree.ToInputString: String; 3450 var 3451 Buf: TStringBuilder; 3452 begin 3453 Buf := TStringBuilder.Create; 3454 try 3455 _ToStringLeaves(Buf); 3456 Result := Buf.ToString; 3457 finally 3458 Buf.Free; 3459 end; 3460 end; 3461 3462 function TParseTree.ToString: String; 3463 var 3464 T: IToken; 3465 begin 3466 if Supports(FPayload, IToken, T) then 3467 begin 3468 if (T.TokenType = TToken.EOF) then 3469 Result := '<EOF>' 3470 else 3471 Result := T.Text; 3472 end 3473 else 3474 Result := FPayload.ToString; 3475 end; 3476 3477 function TParseTree.ToStringWithHiddenTokens: String; 3478 var 3479 Buf: TStringBuilder; 3480 Hidden: IToken; 3481 NodeText: String; 3482 begin 3483 Buf := TStringBuilder.Create; 3484 try 3485 if Assigned(FHiddenTokens) then 3486 begin 3487 for Hidden in FHiddenTokens do 3488 Buf.Append(Hidden.Text); 3489 end; 3490 NodeText := ToString; 3491 if (NodeText <> '<EOF>') then 3492 Buf.Append(NodeText); 3493 Result := Buf.ToString; 3494 finally 3495 Buf.Free; 3496 end; 3497 end; 3498 3499 procedure TParseTree._ToStringLeaves(const Buf: TStringBuilder); 3500 var 3501 T: IBaseTree; 3502 begin 3503 if Supports(FPayload, IToken) then 3504 begin 3505 // leaf node token? 3506 Buf.Append(ToStringWithHiddenTokens); 3507 Exit; 3508 end; 3509 if Assigned(FChildren) then 3510 for T in FChildren do 3511 (T as IParseTree)._ToStringLeaves(Buf); 3512 end; 3513 3514 { ERewriteCardinalityException } 3515 3516 constructor ERewriteCardinalityException.Create( 3517 const AElementDescription: String); 3518 begin 3519 inherited Create(AElementDescription); 3520 FElementDescription := AElementDescription; 3521 end; 3522 3523 { TRewriteRuleElementStream } 3524 3525 procedure TRewriteRuleElementStream.Add(const El: IANTLRInterface); 3526 begin 3527 if (El = nil) then 3528 Exit; 3529 if Assigned(FElements) then 3530 // if in list, just add 3531 FElements.Add(El) 3532 else 3533 if (FSingleElement = nil) then 3534 // no elements yet, track w/o list 3535 FSingleElement := El 3536 else 3537 begin 3538 // adding 2nd element, move to list 3539 FElements := TList<IANTLRInterface>.Create; 3540 FElements.Capacity := 5; 3541 FElements.Add(FSingleElement); 3542 FSingleElement := nil; 3543 FElements.Add(El); 3544 end; 3545 end; 3546 3547 constructor TRewriteRuleElementStream.Create(const AAdaptor: ITreeAdaptor; 3548 const AElementDescription: String); 3549 begin 3550 inherited Create; 3551 FAdaptor := AAdaptor; 3552 FElementDescription := AElementDescription; 3553 end; 3554 3555 constructor TRewriteRuleElementStream.Create(const AAdaptor: ITreeAdaptor; 3556 const AElementDescription: String; const AOneElement: IANTLRInterface); 3557 begin 3558 Create(AAdaptor, AElementDescription); 3559 Add(AOneElement); 3560 end; 3561 3562 constructor TRewriteRuleElementStream.Create(const AAdaptor: ITreeAdaptor; 3563 const AElementDescription: String; const AElements: IList<IANTLRInterface>); 3564 begin 3565 Create(AAdaptor, AElementDescription); 3566 FElements := AElements; 3567 end; 3568 3569 function TRewriteRuleElementStream.GetDescription: String; 3570 begin 3571 Result := FElementDescription; 3572 end; 3573 3574 function TRewriteRuleElementStream.HasNext: Boolean; 3575 begin 3576 Result := ((FSingleElement <> nil) and (FCursor < 1)) 3577 or ((FElements <> nil) and (FCursor < FElements.Count)); 3578 end; 3579 3580 function TRewriteRuleElementStream.NextTree: IANTLRInterface; 3581 begin 3582 Result := _Next; 3583 end; 3584 3585 procedure TRewriteRuleElementStream.Reset; 3586 begin 3587 FCursor := 0; 3588 FDirty := True; 3589 end; 3590 3591 function TRewriteRuleElementStream.Size: Integer; 3592 begin 3593 if Assigned(FSingleElement) then 3594 Result := 1 3595 else 3596 if Assigned(FElements) then 3597 Result := FElements.Count 3598 else 3599 Result := 0; 3600 end; 3601 3602 function TRewriteRuleElementStream.ToTree(const El: IANTLRInterface): IANTLRInterface; 3603 begin 3604 Result := El; 3605 end; 3606 3607 function TRewriteRuleElementStream._Next: IANTLRInterface; 3608 var 3609 Size: Integer; 3610 begin 3611 Size := Self.Size; 3612 if (Size = 0) then 3613 raise ERewriteEmptyStreamException.Create(FElementDescription); 3614 3615 if (FCursor >= Size) then 3616 begin 3617 // out of elements? 3618 if (Size = 1) then 3619 // if size is 1, it's ok; return and we'll dup 3620 Result := ToTree(FSingleElement) 3621 else 3622 // out of elements and size was not 1, so we can't dup 3623 raise ERewriteCardinalityException.Create(FElementDescription); 3624 end 3625 else 3626 begin 3627 // we have elements 3628 if Assigned(FSingleElement) then 3629 begin 3630 Inc(FCursor); // move cursor even for single element list 3631 Result := ToTree(FSingleElement); 3632 end 3633 else 3634 begin 3635 // must have more than one in list, pull from elements 3636 Result := ToTree(FElements[FCursor]); 3637 Inc(FCursor); 3638 end; 3639 end; 3640 end; 3641 3642 { TRewriteRuleNodeStream } 3643 3644 function TRewriteRuleNodeStream.NextNode: IANTLRInterface; 3645 begin 3646 Result := _Next; 3647 end; 3648 3649 function TRewriteRuleNodeStream.ToTree( 3650 const El: IANTLRInterface): IANTLRInterface; 3651 begin 3652 Result := FAdaptor.DupNode(El); 3653 end; 3654 3655 { TRewriteRuleSubtreeStream } 3656 3657 function TRewriteRuleSubtreeStream.Dup( 3658 const O: IANTLRInterface): IANTLRInterface; 3659 begin 3660 Result := FAdaptor.DupTree(O); 3661 end; 3662 3663 function TRewriteRuleSubtreeStream.DupNode( 3664 const O: IANTLRInterface): IANTLRInterface; 3665 begin 3666 Result := FAdaptor.DupNode(O); 3667 end; 3668 3669 function TRewriteRuleSubtreeStream.FetchObject( 3670 const PH: TProcessHandler): IANTLRInterface; 3671 begin 3672 if (RequiresDuplication) then 3673 // process the object 3674 Result := PH(_Next) 3675 else 3676 // test above then fetch 3677 Result := _Next; 3678 end; 3679 3680 function TRewriteRuleSubtreeStream.NextNode: IANTLRInterface; 3681 begin 3682 // if necessary, dup (at most a single node since this is for making root nodes). 3683 Result := FetchObject(DupNode); 3684 end; 3685 3686 function TRewriteRuleSubtreeStream.NextTree: IANTLRInterface; 3687 begin 3688 // if out of elements and size is 1, dup 3689 Result := FetchObject(Dup); 3690 end; 3691 3692 function TRewriteRuleSubtreeStream.RequiresDuplication: Boolean; 3693 var 3694 Size: Integer; 3695 begin 3696 Size := Self.Size; 3697 // if dirty or if out of elements and size is 1 3698 Result := FDirty or ((FCursor >= Size) and (Size = 1)); 3699 end; 3700 3701 { TRewriteRuleTokenStream } 3702 3703 function TRewriteRuleTokenStream.NextNode: IANTLRInterface; 3704 begin 3705 Result := FAdaptor.CreateNode(_Next as IToken) 3706 end; 3707 3708 function TRewriteRuleTokenStream.NextToken: IToken; 3709 begin 3710 Result := _Next as IToken; 3711 end; 3712 3713 function TRewriteRuleTokenStream.ToTree( 3714 const El: IANTLRInterface): IANTLRInterface; 3715 begin 3716 Result := El; 3717 end; 3718 3719 { TTreeParser } 3720 3721 constructor TTreeParser.Create(const AInput: ITreeNodeStream); 3722 begin 3723 inherited Create; // highlight that we go to super to set state object 3724 SetTreeNodeStream(AInput); 3725 end; 3726 3727 constructor TTreeParser.Create(const AInput: ITreeNodeStream; 3728 const AState: IRecognizerSharedState); 3729 begin 3730 inherited Create(AState); // share the state object with another parser 3731 SetTreeNodeStream(AInput); 3732 end; 3733 3734 function TTreeParser.GetCurrentInputSymbol( 3735 const Input: IIntStream): IANTLRInterface; 3736 begin 3737 Result := FInput.LT(1); 3738 end; 3739 3740 function TTreeParser.GetErrorHeader(const E: ERecognitionException): String; 3741 begin 3742 Result := GetGrammarFileName + ': node from '; 3743 if (E.ApproximateLineInfo) then 3744 Result := Result + 'after '; 3745 Result := Result + 'line ' + IntToStr(E.Line) + ':' + IntToStr(E.CharPositionInLine); 3746 end; 3747 3748 function TTreeParser.GetErrorMessage(const E: ERecognitionException; 3749 const TokenNames: TStringArray): String; 3750 var 3751 Adaptor: ITreeAdaptor; 3752 begin 3753 if (Self is TTreeParser) then 3754 begin 3755 Adaptor := (E.Input as ITreeNodeStream).TreeAdaptor; 3756 E.Token := Adaptor.GetToken(E.Node); 3757 if (E.Token = nil) then 3758 // could be an UP/DOWN node 3759 E.Token := TCommonToken.Create(Adaptor.GetNodeType(E.Node), 3760 Adaptor.GetNodeText(E.Node)); 3761 end; 3762 Result := inherited GetErrorMessage(E, TokenNames); 3763 end; 3764 3765 function TTreeParser.GetInput: IIntStream; 3766 begin 3767 Result := FInput; 3768 end; 3769 3770 function TTreeParser.GetMissingSymbol(const Input: IIntStream; 3771 const E: ERecognitionException; const ExpectedTokenType: Integer; 3772 const Follow: IBitSet): IANTLRInterface; 3773 var 3774 TokenText: String; 3775 begin 3776 TokenText := '<missing ' + GetTokenNames[ExpectedTokenType] + '>'; 3777 Result := TCommonTree.Create(TCommonToken.Create(ExpectedTokenType, TokenText)); 3778 end; 3779 3780 function TTreeParser.GetSourceName: String; 3781 begin 3782 Result := FInput.SourceName; 3783 end; 3784 3785 function TTreeParser.GetTreeNodeStream: ITreeNodeStream; 3786 begin 3787 Result := FInput; 3788 end; 3789 3790 procedure TTreeParser.MatchAny(const Input: IIntStream); 3791 var 3792 Look: IANTLRInterface; 3793 Level, TokenType: Integer; 3794 begin 3795 FState.ErrorRecovery := False; 3796 FState.Failed := False; 3797 Look := FInput.LT(1); 3798 if (FInput.TreeAdaptor.GetChildCount(Look) = 0) then 3799 begin 3800 FInput.Consume; // not subtree, consume 1 node and return 3801 Exit; 3802 end; 3803 3804 // current node is a subtree, skip to corresponding UP. 3805 // must count nesting level to get right UP 3806 Level := 0; 3807 TokenType := FInput.TreeAdaptor.GetNodeType(Look); 3808 while (TokenType <> TToken.EOF) and not ((TokenType = UP) and (Level = 0)) do 3809 begin 3810 FInput.Consume; 3811 Look := FInput.LT(1); 3812 TokenType := FInput.TreeAdaptor.GetNodeType(Look); 3813 if (TokenType = DOWN) then 3814 Inc(Level) 3815 else 3816 if (TokenType = UP) then 3817 Dec(Level); 3818 end; 3819 FInput.Consume; // consume UP 3820 end; 3821 3822 procedure TTreeParser.Mismatch(const Input: IIntStream; 3823 const TokenType: Integer; const Follow: IBitSet); 3824 begin 3825 raise EMismatchedTreeNodeException.Create(TokenType, FInput); 3826 end; 3827 3828 procedure TTreeParser.Reset; 3829 begin 3830 inherited; // reset all recognizer state variables 3831 if Assigned(FInput) then 3832 FInput.Seek(0); // rewind the input 3833 end; 3834 3835 procedure TTreeParser.SetTreeNodeStream(const Value: ITreeNodeStream); 3836 begin 3837 FInput := Value; 3838 end; 3839 3840 procedure TTreeParser.TraceIn(const RuleName: String; const RuleIndex: Integer); 3841 begin 3842 inherited TraceIn(RuleName, RuleIndex, FInput.LT(1).ToString); 3843 end; 3844 3845 procedure TTreeParser.TraceOut(const RuleName: String; 3846 const RuleIndex: Integer); 3847 begin 3848 inherited TraceOut(RuleName, RuleIndex, FInput.LT(1).ToString); 3849 end; 3850 3851 { TTreePatternLexer } 3852 3853 constructor TTreePatternLexer.Create; 3854 begin 3855 inherited; 3856 FSVal := TStringBuilder.Create; 3857 end; 3858 3859 procedure TTreePatternLexer.Consume; 3860 begin 3861 Inc(FP); 3862 if (FP > FN) then 3863 FC := EOF 3864 else 3865 FC := Integer(FPattern[FP]); 3866 end; 3867 3868 constructor TTreePatternLexer.Create(const APattern: String); 3869 begin 3870 Create; 3871 FPattern := APattern; 3872 FN := Length(FPattern); 3873 Consume; 3874 end; 3875 3876 destructor TTreePatternLexer.Destroy; 3877 begin 3878 FSVal.Free; 3879 inherited; 3880 end; 3881 3882 function TTreePatternLexer.NextToken: Integer; 3883 begin 3884 FSVal.Length := 0; // reset, but reuse buffer 3885 while (FC <> EOF) do 3886 begin 3887 if (FC = 32) or (FC = 10) or (FC = 13) or (FC = 9) then 3888 begin 3889 Consume; 3890 Continue; 3891 end; 3892 3893 if ((FC >= Ord('a')) and (FC <= Ord('z'))) 3894 or ((FC >= Ord('A')) and (FC <= Ord('Z'))) 3895 or (FC = Ord('_')) 3896 then begin 3897 FSVal.Append(Char(FC)); 3898 Consume; 3899 while ((FC >= Ord('a')) and (FC <= Ord('z'))) 3900 or ((FC >= Ord('A')) and (FC <= Ord('Z'))) 3901 or ((FC >= Ord('0')) and (FC <= Ord('9'))) 3902 or (FC = Ord('_')) do 3903 begin 3904 FSVal.Append(Char(FC)); 3905 Consume; 3906 end; 3907 Exit(ID); 3908 end; 3909 3910 if (FC = Ord('(')) then 3911 begin 3912 Consume; 3913 Exit(START); 3914 end; 3915 3916 if (FC = Ord(')')) then 3917 begin 3918 Consume; 3919 Exit(STOP); 3920 end; 3921 3922 if (FC = Ord('%')) then 3923 begin 3924 Consume; 3925 Exit(PERCENT); 3926 end; 3927 3928 if (FC = Ord(':')) then 3929 begin 3930 Consume; 3931 Exit(COLON); 3932 end; 3933 3934 if (FC = Ord('.')) then 3935 begin 3936 Consume; 3937 Exit(DOT); 3938 end; 3939 3940 if (FC = Ord('[')) then 3941 begin 3942 // grab [x] as a string, returning x 3943 Consume; 3944 while (FC <> Ord(']')) do 3945 begin 3946 if (FC = Ord('\')) then 3947 begin 3948 Consume; 3949 if (FC <> Ord(']')) then 3950 FSVal.Append('\'); 3951 FSVal.Append(Char(FC)); 3952 end 3953 else 3954 FSVal.Append(Char(FC)); 3955 Consume; 3956 end; 3957 Consume; 3958 Exit(ARG); 3959 end; 3960 3961 Consume; 3962 FError := True; 3963 Exit(EOF); 3964 end; 3965 Result := EOF; 3966 end; 3967 3968 function TTreePatternLexer.SVal: String; 3969 begin 3970 Result := FSVal.ToString; 3971 end; 3972 3973 { TTreeWizard } 3974 3975 function TTreeWizard.ComputeTokenTypes( 3976 const TokenNames: TStringArray): IDictionary<String, Integer>; 3977 var 3978 TokenType: Integer; 3979 begin 3980 Result := TDictionary<String, Integer>.Create; 3981 if (Length(TokenNames) > 0)then 3982 begin 3983 for TokenType := TToken.MIN_TOKEN_TYPE to Length(TokenNames) - 1 do 3984 Result.Add(TokenNames[TokenType], TokenType); 3985 end; 3986 end; 3987 3988 constructor TTreeWizard.Create(const AAdaptor: ITreeAdaptor); 3989 begin 3990 inherited Create; 3991 FAdaptor := AAdaptor; 3992 end; 3993 3994 constructor TTreeWizard.Create(const AAdaptor: ITreeAdaptor; 3995 const ATokenNameToTypeMap: IDictionary<String, Integer>); 3996 begin 3997 inherited Create; 3998 FAdaptor := AAdaptor; 3999 FTokenNameToTypeMap := ATokenNameToTypeMap; 4000 end; 4001 4002 constructor TTreeWizard.Create(const AAdaptor: ITreeAdaptor; 4003 const TokenNames: TStringArray); 4004 begin 4005 inherited Create; 4006 FAdaptor := AAdaptor; 4007 FTokenNameToTypeMap := ComputeTokenTypes(TokenNames); 4008 end; 4009 4010 function TTreeWizard.CreateTreeOrNode(const Pattern: String): IANTLRInterface; 4011 var 4012 Tokenizer: ITreePatternLexer; 4013 Parser: ITreePatternParser; 4014 begin 4015 Tokenizer := TTreePatternLexer.Create(Pattern); 4016 Parser := TTreePatternParser.Create(Tokenizer, Self, FAdaptor); 4017 Result := Parser.Pattern; 4018 end; 4019 4020 function TTreeWizard.Equals(const T1, T2: IANTLRInterface; 4021 const Adaptor: ITreeAdaptor): Boolean; 4022 begin 4023 Result := _Equals(T1, T2, Adaptor); 4024 end; 4025 4026 function TTreeWizard.Equals(const T1, T2: IANTLRInterface): Boolean; 4027 begin 4028 Result := _Equals(T1, T2, FAdaptor); 4029 end; 4030 4031 function TTreeWizard.Find(const T: IANTLRInterface; 4032 const Pattern: String): IList<IANTLRInterface>; 4033 var 4034 Tokenizer: ITreePatternLexer; 4035 Parser: ITreePatternParser; 4036 TreePattern: ITreePattern; 4037 RootTokenType: Integer; 4038 Visitor: IContextVisitor; 4039 begin 4040 Result := TList<IANTLRInterface>.Create; 4041 4042 // Create a TreePattern from the pattern 4043 Tokenizer := TTreePatternLexer.Create(Pattern); 4044 Parser := TTreePatternParser.Create(Tokenizer, Self, TTreePatternTreeAdaptor.Create); 4045 TreePattern := Parser.Pattern as ITreePattern; 4046 4047 // don't allow invalid patterns 4048 if (TreePattern = nil) or (TreePattern.IsNil) 4049 or Supports(TreePattern, IWildcardTreePattern) 4050 then 4051 Exit(nil); 4052 4053 RootTokenType := TreePattern.TokenType; 4054 Visitor := TPatternMatchingContextVisitor.Create(Self, TreePattern, Result); 4055 Visit(T, RootTokenType, Visitor); 4056 end; 4057 4058 function TTreeWizard.Find(const T: IANTLRInterface; 4059 const TokenType: Integer): IList<IANTLRInterface>; 4060 begin 4061 Result := TList<IANTLRInterface>.Create; 4062 Visit(T, TokenType, TRecordAllElementsVisitor.Create(Result)); 4063 end; 4064 4065 function TTreeWizard.FindFirst(const T: IANTLRInterface; 4066 const TokenType: Integer): IANTLRInterface; 4067 begin 4068 Result := nil; 4069 end; 4070 4071 function TTreeWizard.FindFirst(const T: IANTLRInterface; 4072 const Pattern: String): IANTLRInterface; 4073 begin 4074 Result := nil; 4075 end; 4076 4077 function TTreeWizard.GetTokenType(const TokenName: String): Integer; 4078 begin 4079 if (FTokenNameToTypeMap = nil) then 4080 Exit(TToken.INVALID_TOKEN_TYPE); 4081 if (not FTokenNameToTypeMap.TryGetValue(TokenName, Result)) then 4082 Result := TToken.INVALID_TOKEN_TYPE; 4083 end; 4084 4085 function TTreeWizard.Index( 4086 const T: IANTLRInterface): IDictionary<Integer, IList<IANTLRInterface>>; 4087 begin 4088 Result := TDictionary<Integer, IList<IANTLRInterface>>.Create; 4089 _Index(T, Result); 4090 end; 4091 4092 function TTreeWizard.Parse(const T: IANTLRInterface; 4093 const Pattern: String): Boolean; 4094 begin 4095 Result := Parse(T, Pattern, nil); 4096 end; 4097 4098 function TTreeWizard.Parse(const T: IANTLRInterface; const Pattern: String; 4099 const Labels: IDictionary<String, IANTLRInterface>): Boolean; 4100 var 4101 Tokenizer: ITreePatternLexer; 4102 Parser: ITreePatternParser; 4103 TreePattern: ITreePattern; 4104 begin 4105 Tokenizer := TTreePatternLexer.Create(Pattern); 4106 Parser := TTreePatternParser.Create(Tokenizer, Self, TTreePatternTreeAdaptor.Create); 4107 TreePattern := Parser.Pattern as ITreePattern; 4108 Result := _Parse(T, TreePattern, Labels); 4109 end; 4110 4111 procedure TTreeWizard.Visit(const T: IANTLRInterface; const Pattern: String; 4112 const Visitor: IContextVisitor); 4113 var 4114 Tokenizer: ITreePatternLexer; 4115 Parser: ITreePatternParser; 4116 TreePattern: ITreePattern; 4117 RootTokenType: Integer; 4118 PatternVisitor: IContextVisitor; 4119 begin 4120 // Create a TreePattern from the pattern 4121 Tokenizer := TTreePatternLexer.Create(Pattern); 4122 Parser := TTreePatternParser.Create(Tokenizer, Self, TTreePatternTreeAdaptor.Create); 4123 TreePattern := Parser.Pattern as ITreePattern; 4124 if (TreePattern = nil) or (TreePattern.IsNil) 4125 or Supports(TreePattern, IWildcardTreePattern) 4126 then 4127 Exit; 4128 RootTokenType := TreePattern.TokenType; 4129 PatternVisitor := TInvokeVisitorOnPatternMatchContextVisitor.Create(Self, TreePattern, Visitor); 4130 Visit(T, RootTokenType, PatternVisitor); 4131 end; 4132 4133 class function TTreeWizard._Equals(const T1, T2: IANTLRInterface; 4134 const Adaptor: ITreeAdaptor): Boolean; 4135 var 4136 I, N1, N2: Integer; 4137 Child1, Child2: IANTLRInterface; 4138 begin 4139 // make sure both are non-null 4140 if (T1 = nil) or (T2 = nil) then 4141 Exit(False); 4142 4143 // check roots 4144 if (Adaptor.GetNodeType(T1) <> Adaptor.GetNodeType(T2)) then 4145 Exit(False); 4146 if (Adaptor.GetNodeText(T1) <> Adaptor.GetNodeText(T2)) then 4147 Exit(False); 4148 4149 // check children 4150 N1 := Adaptor.GetChildCount(T1); 4151 N2 := Adaptor.GetChildCount(T2); 4152 if (N1 <> N2) then 4153 Exit(False); 4154 for I := 0 to N1 - 1 do 4155 begin 4156 Child1 := Adaptor.GetChild(T1, I); 4157 Child2 := Adaptor.GetChild(T2, I); 4158 if (not _Equals(Child1, Child2, Adaptor)) then 4159 Exit(False); 4160 end; 4161 4162 Result := True; 4163 end; 4164 4165 procedure TTreeWizard._Index(const T: IANTLRInterface; 4166 const M: IDictionary<Integer, IList<IANTLRInterface>>); 4167 var 4168 I, N, TType: Integer; 4169 Elements: IList<IANTLRInterface>; 4170 begin 4171 if (T = nil) then 4172 Exit; 4173 TType := FAdaptor.GetNodeType(T); 4174 if (not M.TryGetValue(TType, Elements)) then 4175 Elements := nil; 4176 if (Elements = nil) then 4177 begin 4178 Elements := TList<IANTLRInterface>.Create; 4179 M.Add(TType, Elements); 4180 end; 4181 Elements.Add(T); 4182 N := FAdaptor.GetChildCount(T); 4183 for I := 0 to N - 1 do 4184 _Index(FAdaptor.GetChild(T, I), M); 4185 end; 4186 4187 function TTreeWizard._Parse(const T1: IANTLRInterface; const T2: ITreePattern; 4188 const Labels: IDictionary<String, IANTLRInterface>): Boolean; 4189 var 4190 I, N1, N2: Integer; 4191 Child1: IANTLRInterface; 4192 Child2: ITreePattern; 4193 begin 4194 // make sure both are non-null 4195 if (T1 = nil) or (T2 = nil) then 4196 Exit(False); 4197 4198 // check roots (wildcard matches anything) 4199 if (not Supports(T2, IWildcardTreePattern)) then 4200 begin 4201 if (FAdaptor.GetNodeType(T1) <> T2.TokenType) then 4202 Exit(False); 4203 if (T2.HasTextArg) and (FAdaptor.GetNodeText(T1) <> T2.Text) then 4204 Exit(False); 4205 end; 4206 4207 if (T2.TokenLabel <> '') and Assigned(Labels) then 4208 // map label in pattern to node in t1 4209 Labels.AddOrSetValue(T2.TokenLabel, T1); 4210 4211 // check children 4212 N1 := FAdaptor.GetChildCount(T1); 4213 N2 := T2.ChildCount; 4214 if (N1 <> N2) then 4215 Exit(False); 4216 4217 for I := 0 to N1 - 1 do 4218 begin 4219 Child1 := FAdaptor.GetChild(T1, I); 4220 Child2 := T2.GetChild(I) as ITreePattern; 4221 if (not _Parse(Child1, Child2, Labels)) then 4222 Exit(False); 4223 end; 4224 4225 Result := True; 4226 end; 4227 4228 procedure TTreeWizard._Visit(const T, Parent: IANTLRInterface; const ChildIndex, 4229 TokenType: Integer; const Visitor: IContextVisitor); 4230 var 4231 I, N: Integer; 4232 begin 4233 if (T = nil) then 4234 Exit; 4235 if (FAdaptor.GetNodeType(T) = TokenType) then 4236 Visitor.Visit(T, Parent, ChildIndex, nil); 4237 4238 N := FAdaptor.GetChildCount(T); 4239 for I := 0 to N - 1 do 4240 _Visit(FAdaptor.GetChild(T, I), T, I, TokenType, Visitor); 4241 end; 4242 4243 procedure TTreeWizard.Visit(const T: IANTLRInterface; const TokenType: Integer; 4244 const Visitor: IContextVisitor); 4245 begin 4246 _Visit(T, nil, 0, TokenType, Visitor); 4247 end; 4248 4249 constructor TTreeWizard.Create(const TokenNames: TStringArray); 4250 begin 4251 Create(nil, TokenNames); 4252 end; 4253 4254 { TTreePatternParser } 4255 4256 constructor TTreePatternParser.Create(const ATokenizer: ITreePatternLexer; 4257 const AWizard: ITreeWizard; const AAdaptor: ITreeAdaptor); 4258 begin 4259 inherited Create; 4260 FTokenizer := ATokenizer; 4261 FWizard := AWizard; 4262 FAdaptor := AAdaptor; 4263 FTokenType := FTokenizer.NextToken; // kickstart 4264 end; 4265 4266 function TTreePatternParser.ParseNode: IANTLRInterface; 4267 var 4268 Lbl, TokenName, Text, Arg: String; 4269 WildcardPayload: IToken; 4270 Node: TTreeWizard.ITreePattern; 4271 TreeNodeType: Integer; 4272 begin 4273 // "%label:" prefix 4274 Lbl := ''; 4275 if (FTokenType = TTreePatternLexer.PERCENT) then 4276 begin 4277 FTokenType := FTokenizer.NextToken; 4278 if (FTokenType <> TTreePatternLexer.ID) then 4279 Exit(nil); 4280 Lbl := FTokenizer.SVal; 4281 FTokenType := FTokenizer.NextToken; 4282 if (FTokenType <> TTreePatternLexer.COLON) then 4283 Exit(nil); 4284 FTokenType := FTokenizer.NextToken; // move to ID following colon 4285 end; 4286 4287 // Wildcard? 4288 if (FTokenType = TTreePatternLexer.DOT) then 4289 begin 4290 FTokenType := FTokenizer.NextToken; 4291 WildcardPayload := TCommonToken.Create(0, '.'); 4292 Node := TTreeWizard.TWildcardTreePattern.Create(WildcardPayload); 4293 if (Lbl <> '') then 4294 Node.TokenLabel := Lbl; 4295 Exit(Node); 4296 end; 4297 4298 // "ID" or "ID[arg]" 4299 if (FTokenType <> TTreePatternLexer.ID) then 4300 Exit(nil); 4301 TokenName := FTokenizer.SVal; 4302 FTokenType := FTokenizer.NextToken; 4303 if (TokenName = 'nil') then 4304 Exit(FAdaptor.GetNilNode); 4305 Text := TokenName; 4306 4307 // check for arg 4308 Arg := ''; 4309 if (FTokenType = TTreePatternLexer.ARG) then 4310 begin 4311 Arg := FTokenizer.SVal; 4312 Text := Arg; 4313 FTokenType := FTokenizer.NextToken; 4314 end; 4315 4316 // create node 4317 TreeNodeType := FWizard.GetTokenType(TokenName); 4318 if (TreeNodeType = TToken.INVALID_TOKEN_TYPE) then 4319 Exit(nil); 4320 4321 Result := FAdaptor.CreateNode(TreeNodeType, Text); 4322 if (Lbl <> '') and Supports(Result, TTreeWizard.ITreePattern, Node) then 4323 Node.TokenLabel := Lbl; 4324 if (Arg <> '') and Supports(Result, TTreeWizard.ITreePattern, Node) then 4325 Node.HasTextArg := True; 4326 end; 4327 4328 function TTreePatternParser.ParseTree: IANTLRInterface; 4329 var 4330 Subtree, Child: IANTLRInterface; 4331 begin 4332 if (FTokenType <> TTreePatternLexer.START) then 4333 begin 4334 WriteLn('no BEGIN'); 4335 Exit(nil); 4336 end; 4337 4338 FTokenType := FTokenizer.NextToken; 4339 Result := ParseNode; 4340 if (Result = nil) then 4341 Exit; 4342 4343 while (FTokenType in [TTreePatternLexer.START, TTreePatternLexer.ID, 4344 TTreePatternLexer.PERCENT, TTreePatternLexer.DOT]) do 4345 begin 4346 if (FTokenType = TTreePatternLexer.START) then 4347 begin 4348 Subtree := ParseTree; 4349 FAdaptor.AddChild(Result, Subtree); 4350 end 4351 else 4352 begin 4353 Child := ParseNode; 4354 if (Child = nil) then 4355 Exit(nil); 4356 FAdaptor.AddChild(Result, Child); 4357 end; 4358 end; 4359 4360 if (FTokenType <> TTreePatternLexer.STOP) then 4361 begin 4362 WriteLn('no END'); 4363 Exit(nil); 4364 end; 4365 4366 FTokenType := FTokenizer.NextToken; 4367 end; 4368 4369 function TTreePatternParser.Pattern: IANTLRInterface; 4370 var 4371 Node: IANTLRInterface; 4372 begin 4373 if (FTokenType = TTreePatternLexer.START) then 4374 Exit(ParseTree); 4375 4376 if (FTokenType = TTreePatternLexer.ID) then 4377 begin 4378 Node := ParseNode; 4379 if (FTokenType = TTreePatternLexer.EOF) then 4380 Result := Node 4381 else 4382 Result := nil; // extra junk on end 4383 end 4384 else 4385 Result := nil; 4386 end; 4387 4388 { TTreeWizard.TVisitor } 4389 4390 procedure TTreeWizard.TVisitor.Visit(const T, Parent: IANTLRInterface; 4391 const ChildIndex: Integer; 4392 const Labels: IDictionary<String, IANTLRInterface>); 4393 begin 4394 Visit(T); 4395 end; 4396 4397 { TTreeWizard.TRecordAllElementsVisitor } 4398 4399 constructor TTreeWizard.TRecordAllElementsVisitor.Create( 4400 const AList: IList<IANTLRInterface>); 4401 begin 4402 inherited Create; 4403 FList := AList; 4404 end; 4405 4406 procedure TTreeWizard.TRecordAllElementsVisitor.Visit(const T: IANTLRInterface); 4407 begin 4408 FList.Add(T); 4409 end; 4410 4411 { TTreeWizard.TPatternMatchingContextVisitor } 4412 4413 constructor TTreeWizard.TPatternMatchingContextVisitor.Create( 4414 const AOwner: TTreeWizard; const APattern: ITreePattern; 4415 const AList: IList<IANTLRInterface>); 4416 begin 4417 inherited Create; 4418 FOwner := AOwner; 4419 FPattern := APattern; 4420 FList := AList; 4421 end; 4422 4423 procedure TTreeWizard.TPatternMatchingContextVisitor.Visit(const T, 4424 Parent: IANTLRInterface; const ChildIndex: Integer; 4425 const Labels: IDictionary<String, IANTLRInterface>); 4426 begin 4427 if (FOwner._Parse(T, FPattern, nil)) then 4428 FList.Add(T); 4429 end; 4430 4431 { TTreeWizard.TInvokeVisitorOnPatternMatchContextVisitor } 4432 4433 constructor TTreeWizard.TInvokeVisitorOnPatternMatchContextVisitor.Create( 4434 const AOwner: TTreeWizard; const APattern: ITreePattern; 4435 const AVisitor: IContextVisitor); 4436 begin 4437 inherited Create; 4438 FOwner := AOwner; 4439 FPattern := APattern; 4440 FVisitor := AVisitor; 4441 FLabels := TDictionary<String, IANTLRInterface>.Create; 4442 end; 4443 4444 procedure TTreeWizard.TInvokeVisitorOnPatternMatchContextVisitor.Visit(const T, 4445 Parent: IANTLRInterface; const ChildIndex: Integer; 4446 const UnusedLabels: IDictionary<String, IANTLRInterface>); 4447 begin 4448 // the unusedlabels arg is null as visit on token type doesn't set. 4449 FLabels.Clear; 4450 if (FOwner._Parse(T, FPattern, FLabels)) then 4451 FVisitor.Visit(T, Parent, ChildIndex, FLabels); 4452 end; 4453 4454 { TTreeWizard.TTreePattern } 4455 4456 function TTreeWizard.TTreePattern.GetHasTextArg: Boolean; 4457 begin 4458 Result := FHasTextArg; 4459 end; 4460 4461 function TTreeWizard.TTreePattern.GetTokenLabel: String; 4462 begin 4463 Result := FLabel; 4464 end; 4465 4466 procedure TTreeWizard.TTreePattern.SetHasTextArg(const Value: Boolean); 4467 begin 4468 FHasTextArg := Value; 4469 end; 4470 4471 procedure TTreeWizard.TTreePattern.SetTokenLabel(const Value: String); 4472 begin 4473 FLabel := Value; 4474 end; 4475 4476 function TTreeWizard.TTreePattern.ToString: String; 4477 begin 4478 if (FLabel <> '') then 4479 Result := '%' + FLabel + ':' + inherited ToString 4480 else 4481 Result := inherited ToString; 4482 end; 4483 4484 { TTreeWizard.TTreePatternTreeAdaptor } 4485 4486 function TTreeWizard.TTreePatternTreeAdaptor.CreateNode( 4487 const Payload: IToken): IANTLRInterface; 4488 begin 4489 Result := TTreePattern.Create(Payload); 4490 end; 4491 4492 { TTreeRuleReturnScope } 4493 4494 function TTreeRuleReturnScope.GetStart: IANTLRInterface; 4495 begin 4496 Result := FStart; 4497 end; 4498 4499 procedure TTreeRuleReturnScope.SetStart(const Value: IANTLRInterface); 4500 begin 4501 FStart := Value; 4502 end; 4503 4504 { TUnBufferedTreeNodeStream } 4505 4506 procedure TUnBufferedTreeNodeStream.AddLookahead(const Node: IANTLRInterface); 4507 var 4508 Bigger: TANTLRInterfaceArray; 4509 I, RemainderHeadToEnd: Integer; 4510 begin 4511 FLookahead[FTail] := Node; 4512 FTail := (FTail + 1) mod Length(FLookahead); 4513 if (FTail = FHead) then 4514 begin 4515 // buffer overflow: tail caught up with head 4516 // allocate a buffer 2x as big 4517 SetLength(Bigger,2 * Length(FLookahead)); 4518 // copy head to end of buffer to beginning of bigger buffer 4519 RemainderHeadToEnd := Length(FLookahead) - FHead; 4520 for I := 0 to RemainderHeadToEnd - 1 do 4521 Bigger[I] := FLookahead[FHead + I]; 4522 // copy 0..tail to after that 4523 for I := 0 to FTail - 1 do 4524 Bigger[RemainderHeadToEnd + I] := FLookahead[I]; 4525 FLookahead := Bigger; // reset to bigger buffer 4526 FHead := 0; 4527 Inc(FTail,RemainderHeadToEnd); 4528 end; 4529 end; 4530 4531 procedure TUnBufferedTreeNodeStream.AddNavigationNode(const TokenType: Integer); 4532 var 4533 NavNode: IANTLRInterface; 4534 begin 4535 if (TokenType = TToken.DOWN) then 4536 begin 4537 if (GetHasUniqueNavigationNodes) then 4538 NavNode := FAdaptor.CreateNode(TToken.DOWN,'DOWN') 4539 else 4540 NavNode := FDown; 4541 end 4542 else 4543 begin 4544 if (GetHasUniqueNavigationNodes) then 4545 NavNode := FAdaptor.CreateNode(TToken.UP,'UP') 4546 else 4547 NavNode := FUp; 4548 end; 4549 AddLookahead(NavNode); 4550 end; 4551 4552 procedure TUnBufferedTreeNodeStream.Consume; 4553 begin 4554 // make sure there is something in lookahead buf, which might call next() 4555 Fill(1); 4556 Inc(FAbsoluteNodeIndex); 4557 FPreviousNode := FLookahead[FHead]; // track previous node before moving on 4558 FHead := (FHead + 1) mod Length(FLookahead); 4559 end; 4560 4561 constructor TUnBufferedTreeNodeStream.Create; 4562 begin 4563 inherited; 4564 SetLength(FLookAhead,INITIAL_LOOKAHEAD_BUFFER_SIZE); 4565 FNodeStack := TStackList<IANTLRInterface>.Create; 4566 FIndexStack := TStackList<Integer>.Create; 4567 end; 4568 4569 constructor TUnBufferedTreeNodeStream.Create(const ATree: IANTLRInterface); 4570 begin 4571 Create(TCommonTreeAdaptor.Create, ATree); 4572 end; 4573 4574 constructor TUnBufferedTreeNodeStream.Create(const AAdaptor: ITreeAdaptor; 4575 const ATree: IANTLRInterface); 4576 begin 4577 Create; 4578 FRoot := ATree; 4579 FAdaptor := AAdaptor; 4580 Reset; 4581 FDown := FAdaptor.CreateNode(TToken.DOWN, 'DOWN'); 4582 FUp := FAdaptor.CreateNode(TToken.UP, 'UP'); 4583 FEof := FAdaptor.CreateNode(TToken.EOF, 'EOF'); 4584 end; 4585 4586 procedure TUnBufferedTreeNodeStream.Fill(const K: Integer); 4587 var 4588 I, N: Integer; 4589 begin 4590 N := LookaheadSize; 4591 for I := 1 to K - N do 4592 MoveNext; // get at least k-depth lookahead nodes 4593 end; 4594 4595 function TUnBufferedTreeNodeStream.Get(const I: Integer): IANTLRInterface; 4596 begin 4597 raise EInvalidOperation.Create('stream is unbuffered'); 4598 end; 4599 4600 function TUnBufferedTreeNodeStream.GetCurrent: IANTLRInterface; 4601 begin 4602 Result := FCurrentEnumerationNode; 4603 end; 4604 4605 function TUnBufferedTreeNodeStream.GetHasUniqueNavigationNodes: Boolean; 4606 begin 4607 Result := FUniqueNavigationNodes; 4608 end; 4609 4610 function TUnBufferedTreeNodeStream.GetSourceName: String; 4611 begin 4612 Result := GetTokenStream.SourceName; 4613 end; 4614 4615 function TUnBufferedTreeNodeStream.GetTokenStream: ITokenStream; 4616 begin 4617 Result := FTokens; 4618 end; 4619 4620 function TUnBufferedTreeNodeStream.GetTreeAdaptor: ITreeAdaptor; 4621 begin 4622 Result := FAdaptor; 4623 end; 4624 4625 function TUnBufferedTreeNodeStream.GetTreeSource: IANTLRInterface; 4626 begin 4627 Result := FRoot; 4628 end; 4629 4630 function TUnBufferedTreeNodeStream.HandleRootNode: IANTLRInterface; 4631 begin 4632 Result := FCurrentNode; 4633 // point to first child in prep for subsequent next() 4634 FCurrentChildIndex := 0; 4635 if (FAdaptor.IsNil(Result)) then 4636 // don't count this root nil node 4637 Result := VisitChild(FCurrentChildIndex) 4638 else 4639 begin 4640 AddLookahead(Result); 4641 if (FAdaptor.GetChildCount(FCurrentNode) = 0) then 4642 // single node case 4643 Result := nil; // say we're done 4644 end; 4645 end; 4646 4647 function TUnBufferedTreeNodeStream.Index: Integer; 4648 begin 4649 Result := FAbsoluteNodeIndex + 1; 4650 end; 4651 4652 function TUnBufferedTreeNodeStream.LA(I: Integer): Integer; 4653 var 4654 T: IANTLRInterface; 4655 begin 4656 T := LT(I); 4657 if (T = nil) then 4658 Result := TToken.INVALID_TOKEN_TYPE 4659 else 4660 Result := FAdaptor.GetNodeType(T); 4661 end; 4662 4663 function TUnBufferedTreeNodeStream.LAChar(I: Integer): Char; 4664 begin 4665 Result := Char(LA(I)); 4666 end; 4667 4668 function TUnBufferedTreeNodeStream.LookaheadSize: Integer; 4669 begin 4670 if (FTail < FHead) then 4671 Result := Length(FLookahead) - FHead + FTail 4672 else 4673 Result := FTail - FHead; 4674 end; 4675 4676 function TUnBufferedTreeNodeStream.LT(const K: Integer): IANTLRInterface; 4677 begin 4678 if (K = -1) then 4679 Exit(FPreviousNode); 4680 4681 if (K < 0) then 4682 raise EArgumentException.Create('tree node streams cannot look backwards more than 1 node'); 4683 4684 if (K = 0) then 4685 Exit(TTree.INVALID_NODE); 4686 4687 Fill(K); 4688 Result := FLookahead[(FHead + K - 1) mod Length(FLookahead)]; 4689 end; 4690 4691 function TUnBufferedTreeNodeStream.Mark: Integer; 4692 var 4693 State: ITreeWalkState; 4694 I, N, K: Integer; 4695 LA: TANTLRInterfaceArray; 4696 begin 4697 if (FMarkers = nil) then 4698 begin 4699 FMarkers := TList<ITreeWalkState>.Create; 4700 FMarkers.Add(nil); // depth 0 means no backtracking, leave blank 4701 end; 4702 4703 Inc(FMarkDepth); 4704 State := nil; 4705 if (FMarkDepth >= FMarkers.Count) then 4706 begin 4707 State := TTreeWalkState.Create; 4708 FMarkers.Add(State); 4709 end 4710 else 4711 State := FMarkers[FMarkDepth]; 4712 4713 State.AbsoluteNodeIndex := FAbsoluteNodeIndex; 4714 State.CurrentChildIndex := FCurrentChildIndex; 4715 State.CurrentNode := FCurrentNode; 4716 State.PreviousNode := FPreviousNode; 4717 State.NodeStackSize := FNodeStack.Count; 4718 State.IndexStackSize := FIndexStack.Count; 4719 4720 // take snapshot of lookahead buffer 4721 N := LookaheadSize; 4722 I := 0; 4723 SetLength(LA,N); 4724 for K := 1 to N do 4725 begin 4726 LA[I] := LT(K); 4727 Inc(I); 4728 end; 4729 State.LookAhead := LA; 4730 FLastMarker := FMarkDepth; 4731 Result := FMarkDepth; 4732 end; 4733 4734 function TUnBufferedTreeNodeStream.MoveNext: Boolean; 4735 begin 4736 // already walked entire tree; nothing to return 4737 if (FCurrentNode = nil) then 4738 begin 4739 AddLookahead(FEof); 4740 FCurrentEnumerationNode := nil; 4741 // this is infinite stream returning EOF at end forever 4742 // so don't throw NoSuchElementException 4743 Exit(False); 4744 end; 4745 4746 // initial condition (first time method is called) 4747 if (FCurrentChildIndex = -1) then 4748 begin 4749 FCurrentEnumerationNode := HandleRootNode as ITree; 4750 Exit(True); 4751 end; 4752 4753 // index is in the child list? 4754 if (FCurrentChildIndex < FAdaptor.GetChildCount(FCurrentNode)) then 4755 begin 4756 FCurrentEnumerationNode := VisitChild(FCurrentChildIndex) as ITree; 4757 Exit(True); 4758 end; 4759 4760 // hit end of child list, return to parent node or its parent ... 4761 WalkBackToMostRecentNodeWithUnvisitedChildren; 4762 if (FCurrentNode <> nil) then 4763 begin 4764 FCurrentEnumerationNode := VisitChild(FCurrentChildIndex) as ITree; 4765 Result := True; 4766 end 4767 else 4768 Result := False; 4769 end; 4770 4771 procedure TUnBufferedTreeNodeStream.Release(const Marker: Integer); 4772 begin 4773 // unwind any other markers made after marker and release marker 4774 FMarkDepth := Marker; 4775 // release this marker 4776 Dec(FMarkDepth); 4777 end; 4778 4779 procedure TUnBufferedTreeNodeStream.ReplaceChildren( 4780 const Parent: IANTLRInterface; const StartChildIndex, StopChildIndex: Integer; 4781 const T: IANTLRInterface); 4782 begin 4783 raise EInvalidOperation.Create('can''t do stream rewrites yet'); 4784 end; 4785 4786 procedure TUnBufferedTreeNodeStream.Reset; 4787 begin 4788 FCurrentNode := FRoot; 4789 FPreviousNode := nil; 4790 FCurrentChildIndex := -1; 4791 FAbsoluteNodeIndex := -1; 4792 FHead := 0; 4793 FTail := 0; 4794 end; 4795 4796 procedure TUnBufferedTreeNodeStream.Rewind(const Marker: Integer); 4797 var 4798 State: ITreeWalkState; 4799 begin 4800 if (FMarkers = nil) then 4801 Exit; 4802 State := FMarkers[Marker]; 4803 FAbsoluteNodeIndex := State.AbsoluteNodeIndex; 4804 FCurrentChildIndex := State.CurrentChildIndex; 4805 FCurrentNode := State.CurrentNode; 4806 FPreviousNode := State.PreviousNode; 4807 // drop node and index stacks back to old size 4808 FNodeStack.Capacity := State.NodeStackSize; 4809 FIndexStack.Capacity := State.IndexStackSize; 4810 FHead := 0; // wack lookahead buffer and then refill 4811 FTail := 0; 4812 while (FTail < Length(State.LookAhead)) do 4813 begin 4814 FLookahead[FTail] := State.LookAhead[FTail]; 4815 Inc(FTail); 4816 end; 4817 Release(Marker); 4818 end; 4819 4820 procedure TUnBufferedTreeNodeStream.Rewind; 4821 begin 4822 Rewind(FLastMarker); 4823 end; 4824 4825 procedure TUnBufferedTreeNodeStream.Seek(const Index: Integer); 4826 begin 4827 if (Index < Self.Index) then 4828 raise EArgumentOutOfRangeException.Create('can''t seek backwards in node stream'); 4829 4830 // seek forward, consume until we hit index 4831 while (Self.Index < Index) do 4832 Consume; 4833 end; 4834 4835 procedure TUnBufferedTreeNodeStream.SetHasUniqueNavigationNodes( 4836 const Value: Boolean); 4837 begin 4838 FUniqueNavigationNodes := Value; 4839 end; 4840 4841 procedure TUnBufferedTreeNodeStream.SetTokenStream(const Value: ITokenStream); 4842 begin 4843 FTokens := Value; 4844 end; 4845 4846 function TUnBufferedTreeNodeStream.Size: Integer; 4847 var 4848 S: ICommonTreeNodeStream; 4849 begin 4850 S := TCommonTreeNodeStream.Create(FRoot); 4851 Result := S.Size; 4852 end; 4853 4854 function TUnBufferedTreeNodeStream.ToString: String; 4855 begin 4856 Result := ToString(FRoot, nil); 4857 end; 4858 4859 procedure TUnBufferedTreeNodeStream.ToStringWork(const P, Stop: IANTLRInterface; 4860 const Buf: TStringBuilder); 4861 var 4862 Text: String; 4863 C, N: Integer; 4864 begin 4865 if (not FAdaptor.IsNil(P)) then 4866 begin 4867 Text := FAdaptor.GetNodeText(P); 4868 if (Text = '') then 4869 Text := ' ' + IntToStr(FAdaptor.GetNodeType(P)); 4870 Buf.Append(Text); // ask the node to go to string 4871 end; 4872 4873 if SameObj(P, Stop) then 4874 Exit; 4875 4876 N := FAdaptor.GetChildCount(P); 4877 if (N > 0) and (not FAdaptor.IsNil(P)) then 4878 begin 4879 Buf.Append(' '); 4880 Buf.Append(TToken.DOWN); 4881 end; 4882 4883 for C := 0 to N - 1 do 4884 ToStringWork(FAdaptor.GetChild(P, C), Stop, Buf); 4885 4886 if (N > 0) and (not FAdaptor.IsNil(P)) then 4887 begin 4888 Buf.Append(' '); 4889 Buf.Append(TToken.UP); 4890 end; 4891 end; 4892 4893 function TUnBufferedTreeNodeStream.VisitChild( 4894 const Child: Integer): IANTLRInterface; 4895 begin 4896 Result := nil; 4897 // save state 4898 FNodeStack.Push(FCurrentNode); 4899 FIndexStack.Push(Child); 4900 if (Child = 0) and (not FAdaptor.IsNil(FCurrentNode)) then 4901 AddNavigationNode(TToken.DOWN); 4902 // visit child 4903 FCurrentNode := FAdaptor.GetChild(FCurrentNode, Child); 4904 FCurrentChildIndex := 0; 4905 Result := FCurrentNode; 4906 AddLookahead(Result); 4907 WalkBackToMostRecentNodeWithUnvisitedChildren; 4908 end; 4909 4910 procedure TUnBufferedTreeNodeStream.WalkBackToMostRecentNodeWithUnvisitedChildren; 4911 begin 4912 while (FCurrentNode <> nil) and (FCurrentChildIndex >= FAdaptor.GetChildCount(FCurrentNode)) do 4913 begin 4914 FCurrentNode := FNodeStack.Pop; 4915 if (FCurrentNode = nil) then 4916 // hit the root? 4917 Exit; 4918 4919 FCurrentChildIndex := FIndexStack.Pop; 4920 Inc(FCurrentChildIndex); // move to next child 4921 if (FCurrentChildIndex >= FAdaptor.GetChildCount(FCurrentNode)) then 4922 begin 4923 if (not FAdaptor.IsNil(FCurrentNode)) then 4924 AddNavigationNode(TToken.UP); 4925 if SameObj(FCurrentNode, FRoot) then 4926 // we done yet? 4927 FCurrentNode := nil; 4928 end; 4929 end; 4930 end; 4931 4932 function TUnBufferedTreeNodeStream.ToString(const Start, 4933 Stop: IANTLRInterface): String; 4934 var 4935 BeginTokenIndex, EndTokenIndex: Integer; 4936 Buf: TStringBuilder; 4937 begin 4938 if (Start = nil) then 4939 Exit(''); 4940 4941 // if we have the token stream, use that to dump text in order 4942 if (FTokens <> nil) then 4943 begin 4944 // don't trust stop node as it's often an UP node etc... 4945 // walk backwards until you find a non-UP, non-DOWN node 4946 // and ask for it's token index. 4947 BeginTokenIndex := FAdaptor.GetTokenStartIndex(Start); 4948 if (Stop <> nil) and (FAdaptor.GetNodeType(Stop) = TToken.UP) then 4949 EndTokenIndex := FAdaptor.GetTokenStopIndex(Start) 4950 else 4951 EndTokenIndex := Size - 1; 4952 Exit(FTokens.ToString(BeginTokenIndex, EndTokenIndex)); 4953 end; 4954 4955 Buf := TStringBuilder.Create; 4956 try 4957 ToStringWork(Start, Stop, Buf); 4958 Result := Buf.ToString; 4959 finally 4960 Buf.Free; 4961 end; 4962 end; 4963 4964 { TUnBufferedTreeNodeStream.TTreeWalkState } 4965 4966 function TUnBufferedTreeNodeStream.TTreeWalkState.GetAbsoluteNodeIndex: Integer; 4967 begin 4968 Result := FAbsoluteNodeIndex; 4969 end; 4970 4971 function TUnBufferedTreeNodeStream.TTreeWalkState.GetCurrentChildIndex: Integer; 4972 begin 4973 Result := FCurrentChildIndex; 4974 end; 4975 4976 function TUnBufferedTreeNodeStream.TTreeWalkState.GetCurrentNode: IANTLRInterface; 4977 begin 4978 Result := FCurrentNode; 4979 end; 4980 4981 function TUnBufferedTreeNodeStream.TTreeWalkState.GetIndexStackSize: integer; 4982 begin 4983 Result := FIndexStackSize; 4984 end; 4985 4986 function TUnBufferedTreeNodeStream.TTreeWalkState.GetLookAhead: TANTLRInterfaceArray; 4987 begin 4988 Result := FLookAhead; 4989 end; 4990 4991 function TUnBufferedTreeNodeStream.TTreeWalkState.GetNodeStackSize: Integer; 4992 begin 4993 Result := FNodeStackSize; 4994 end; 4995 4996 function TUnBufferedTreeNodeStream.TTreeWalkState.GetPreviousNode: IANTLRInterface; 4997 begin 4998 Result := FPreviousNode; 4999 end; 5000 5001 procedure TUnBufferedTreeNodeStream.TTreeWalkState.SetAbsoluteNodeIndex( 5002 const Value: Integer); 5003 begin 5004 FAbsoluteNodeIndex := Value; 5005 end; 5006 5007 procedure TUnBufferedTreeNodeStream.TTreeWalkState.SetCurrentChildIndex( 5008 const Value: Integer); 5009 begin 5010 FCurrentChildIndex := Value; 5011 end; 5012 5013 procedure TUnBufferedTreeNodeStream.TTreeWalkState.SetCurrentNode( 5014 const Value: IANTLRInterface); 5015 begin 5016 FCurrentNode := Value; 5017 end; 5018 5019 procedure TUnBufferedTreeNodeStream.TTreeWalkState.SetIndexStackSize( 5020 const Value: integer); 5021 begin 5022 FIndexStackSize := Value; 5023 end; 5024 5025 procedure TUnBufferedTreeNodeStream.TTreeWalkState.SetLookAhead( 5026 const Value: TANTLRInterfaceArray); 5027 begin 5028 FLookAhead := Value; 5029 end; 5030 5031 procedure TUnBufferedTreeNodeStream.TTreeWalkState.SetNodeStackSize( 5032 const Value: Integer); 5033 begin 5034 FNodeStackSize := Value; 5035 end; 5036 5037 procedure TUnBufferedTreeNodeStream.TTreeWalkState.SetPreviousNode( 5038 const Value: IANTLRInterface); 5039 begin 5040 FPreviousNode := Value; 5041 end; 5042 5043 { Utilities } 5044 5045 var 5046 EmptyCommonTree: ICommonTree = nil; 5047 5048 function Def(const X: ICommonTree): ICommonTree; overload; 5049 begin 5050 if Assigned(X) then 5051 Result := X 5052 else 5053 begin 5054 if (EmptyCommonTree = nil) then 5055 EmptyCommonTree := TCommonTree.Create; 5056 Result := EmptyCommonTree; 5057 end; 5058 end; 5059 5060 initialization 5061 TTree.Initialize; 5062 5063 end. 5064