1# Lint as: python2, python3 2""" @package antlr3.tree 3@brief ANTLR3 runtime package, tree module 4 5This module contains all support classes for AST construction and tree parsers. 6 7""" 8 9# begin[licence] 10# 11# [The "BSD licence"] 12# Copyright (c) 2005-2008 Terence Parr 13# All rights reserved. 14# 15# Redistribution and use in source and binary forms, with or without 16# modification, are permitted provided that the following conditions 17# are met: 18# 1. Redistributions of source code must retain the above copyright 19# notice, this list of conditions and the following disclaimer. 20# 2. Redistributions in binary form must reproduce the above copyright 21# notice, this list of conditions and the following disclaimer in the 22# documentation and/or other materials provided with the distribution. 23# 3. The name of the author may not be used to endorse or promote products 24# derived from this software without specific prior written permission. 25# 26# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 27# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 28# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 29# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 30# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 31# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 35# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36# 37# end[licence] 38 39# lot's of docstrings are missing, don't complain for now... 40# pylint: disable-msg=C0111 41 42from __future__ import absolute_import 43from __future__ import division 44from __future__ import print_function 45 46from antlr3.constants import UP, DOWN, EOF, INVALID_TOKEN_TYPE 47from antlr3.exceptions import MismatchedTreeNodeException, \ 48 MissingTokenException, UnwantedTokenException, MismatchedTokenException, \ 49 NoViableAltException 50from antlr3.recognizers import BaseRecognizer, RuleReturnScope 51from antlr3.streams import IntStream 52from antlr3.tokens import CommonToken, Token, INVALID_TOKEN 53import six 54from six.moves import range 55 56 57############################################################################ 58# 59# tree related exceptions 60# 61############################################################################ 62 63 64class RewriteCardinalityException(RuntimeError): 65 """ 66 @brief Base class for all exceptions thrown during AST rewrite construction. 67 68 This signifies a case where the cardinality of two or more elements 69 in a subrule are different: (ID INT)+ where |ID|!=|INT| 70 """ 71 72 def __init__(self, elementDescription): 73 RuntimeError.__init__(self, elementDescription) 74 75 self.elementDescription = elementDescription 76 77 def getMessage(self): 78 return self.elementDescription 79 80 81class RewriteEarlyExitException(RewriteCardinalityException): 82 """@brief No elements within a (...)+ in a rewrite rule""" 83 84 def __init__(self, elementDescription=None): 85 RewriteCardinalityException.__init__(self, elementDescription) 86 87 88class RewriteEmptyStreamException(RewriteCardinalityException): 89 """ 90 @brief Ref to ID or expr but no tokens in ID stream or subtrees in expr 91 stream 92 """ 93 94 pass 95 96 97############################################################################ 98# 99# basic Tree and TreeAdaptor interfaces 100# 101############################################################################ 102 103class Tree(object): 104 """ 105 @brief Abstract baseclass for tree nodes. 106 107 What does a tree look like? ANTLR has a number of support classes 108 such as CommonTreeNodeStream that work on these kinds of trees. You 109 don't have to make your trees implement this interface, but if you do, 110 you'll be able to use more support code. 111 112 NOTE: When constructing trees, ANTLR can build any kind of tree; it can 113 even use Token objects as trees if you add a child list to your tokens. 114 115 This is a tree node without any payload; just navigation and factory stuff. 116 """ 117 118 def getChild(self, i): 119 raise NotImplementedError 120 121 def getChildCount(self): 122 raise NotImplementedError 123 124 def getParent(self): 125 """Tree tracks parent and child index now > 3.0""" 126 127 raise NotImplementedError 128 129 def setParent(self, t): 130 """Tree tracks parent and child index now > 3.0""" 131 132 raise NotImplementedError 133 134 def getChildIndex(self): 135 """This node is what child index? 0..n-1""" 136 137 raise NotImplementedError 138 139 def setChildIndex(self, index): 140 """This node is what child index? 0..n-1""" 141 142 raise NotImplementedError 143 144 def freshenParentAndChildIndexes(self): 145 """Set the parent and child index values for all children""" 146 147 raise NotImplementedError 148 149 def addChild(self, t): 150 """ 151 Add t as a child to this node. If t is null, do nothing. If t 152 is nil, add all children of t to this' children. 153 """ 154 155 raise NotImplementedError 156 157 def setChild(self, i, t): 158 """Set ith child (0..n-1) to t; t must be non-null and non-nil node""" 159 160 raise NotImplementedError 161 162 def deleteChild(self, i): 163 raise NotImplementedError 164 165 def replaceChildren(self, startChildIndex, stopChildIndex, t): 166 """ 167 Delete children from start to stop and replace with t even if t is 168 a list (nil-root tree). num of children can increase or decrease. 169 For huge child lists, inserting children can force walking rest of 170 children to set their childindex; could be slow. 171 """ 172 173 raise NotImplementedError 174 175 def isNil(self): 176 """ 177 Indicates the node is a nil node but may still have children, meaning 178 the tree is a flat list. 179 """ 180 181 raise NotImplementedError 182 183 def getTokenStartIndex(self): 184 """ 185 What is the smallest token index (indexing from 0) for this node 186 and its children? 187 """ 188 189 raise NotImplementedError 190 191 def setTokenStartIndex(self, index): 192 raise NotImplementedError 193 194 def getTokenStopIndex(self): 195 """ 196 What is the largest token index (indexing from 0) for this node 197 and its children? 198 """ 199 200 raise NotImplementedError 201 202 def setTokenStopIndex(self, index): 203 raise NotImplementedError 204 205 def dupNode(self): 206 raise NotImplementedError 207 208 def getType(self): 209 """Return a token type; needed for tree parsing.""" 210 211 raise NotImplementedError 212 213 def getText(self): 214 raise NotImplementedError 215 216 def getLine(self): 217 """ 218 In case we don't have a token payload, what is the line for errors? 219 """ 220 221 raise NotImplementedError 222 223 def getCharPositionInLine(self): 224 raise NotImplementedError 225 226 def toStringTree(self): 227 raise NotImplementedError 228 229 def toString(self): 230 raise NotImplementedError 231 232 233 234class TreeAdaptor(object): 235 """ 236 @brief Abstract baseclass for tree adaptors. 237 238 How to create and navigate trees. Rather than have a separate factory 239 and adaptor, I've merged them. Makes sense to encapsulate. 240 241 This takes the place of the tree construction code generated in the 242 generated code in 2.x and the ASTFactory. 243 244 I do not need to know the type of a tree at all so they are all 245 generic Objects. This may increase the amount of typecasting needed. :( 246 """ 247 248 # C o n s t r u c t i o n 249 250 def createWithPayload(self, payload): 251 """ 252 Create a tree node from Token object; for CommonTree type trees, 253 then the token just becomes the payload. This is the most 254 common create call. 255 256 Override if you want another kind of node to be built. 257 """ 258 259 raise NotImplementedError 260 261 def dupNode(self, treeNode): 262 """Duplicate a single tree node. 263 264 Override if you want another kind of node to be built. 265 """ 266 267 raise NotImplementedError 268 269 def dupTree(self, tree): 270 """Duplicate tree recursively, using dupNode() for each node""" 271 272 raise NotImplementedError 273 274 def nil(self): 275 """ 276 Return a nil node (an empty but non-null node) that can hold 277 a list of element as the children. If you want a flat tree (a list) 278 use "t=adaptor.nil(); t.addChild(x); t.addChild(y);" 279 """ 280 281 raise NotImplementedError 282 283 def errorNode(self, input, start, stop, exc): 284 """ 285 Return a tree node representing an error. This node records the 286 tokens consumed during error recovery. The start token indicates the 287 input symbol at which the error was detected. The stop token indicates 288 the last symbol consumed during recovery. 289 290 You must specify the input stream so that the erroneous text can 291 be packaged up in the error node. The exception could be useful 292 to some applications; default implementation stores ptr to it in 293 the CommonErrorNode. 294 295 This only makes sense during token parsing, not tree parsing. 296 Tree parsing should happen only when parsing and tree construction 297 succeed. 298 """ 299 300 raise NotImplementedError 301 302 def isNil(self, tree): 303 """Is tree considered a nil node used to make lists of child nodes?""" 304 305 raise NotImplementedError 306 307 def addChild(self, t, child): 308 """ 309 Add a child to the tree t. If child is a flat tree (a list), make all 310 in list children of t. Warning: if t has no children, but child does 311 and child isNil then you can decide it is ok to move children to t via 312 t.children = child.children; i.e., without copying the array. Just 313 make sure that this is consistent with have the user will build 314 ASTs. Do nothing if t or child is null. 315 """ 316 317 raise NotImplementedError 318 319 def becomeRoot(self, newRoot, oldRoot): 320 """ 321 If oldRoot is a nil root, just copy or move the children to newRoot. 322 If not a nil root, make oldRoot a child of newRoot. 323 324 old=^(nil a b c), new=r yields ^(r a b c) 325 old=^(a b c), new=r yields ^(r ^(a b c)) 326 327 If newRoot is a nil-rooted single child tree, use the single 328 child as the new root node. 329 330 old=^(nil a b c), new=^(nil r) yields ^(r a b c) 331 old=^(a b c), new=^(nil r) yields ^(r ^(a b c)) 332 333 If oldRoot was null, it's ok, just return newRoot (even if isNil). 334 335 old=null, new=r yields r 336 old=null, new=^(nil r) yields ^(nil r) 337 338 Return newRoot. Throw an exception if newRoot is not a 339 simple node or nil root with a single child node--it must be a root 340 node. If newRoot is ^(nil x) return x as newRoot. 341 342 Be advised that it's ok for newRoot to point at oldRoot's 343 children; i.e., you don't have to copy the list. We are 344 constructing these nodes so we should have this control for 345 efficiency. 346 """ 347 348 raise NotImplementedError 349 350 def rulePostProcessing(self, root): 351 """ 352 Given the root of the subtree created for this rule, post process 353 it to do any simplifications or whatever you want. A required 354 behavior is to convert ^(nil singleSubtree) to singleSubtree 355 as the setting of start/stop indexes relies on a single non-nil root 356 for non-flat trees. 357 358 Flat trees such as for lists like "idlist : ID+ ;" are left alone 359 unless there is only one ID. For a list, the start/stop indexes 360 are set in the nil node. 361 362 This method is executed after all rule tree construction and right 363 before setTokenBoundaries(). 364 """ 365 366 raise NotImplementedError 367 368 def getUniqueID(self, node): 369 """For identifying trees. 370 371 How to identify nodes so we can say "add node to a prior node"? 372 Even becomeRoot is an issue. Use System.identityHashCode(node) 373 usually. 374 """ 375 376 raise NotImplementedError 377 378 # R e w r i t e R u l e s 379 380 def createFromToken(self, tokenType, fromToken, text=None): 381 """ 382 Create a new node derived from a token, with a new token type and 383 (optionally) new text. 384 385 This is invoked from an imaginary node ref on right side of a 386 rewrite rule as IMAG[$tokenLabel] or IMAG[$tokenLabel "IMAG"]. 387 388 This should invoke createToken(Token). 389 """ 390 391 raise NotImplementedError 392 393 def createFromType(self, tokenType, text): 394 """Create a new node derived from a token, with a new token type. 395 396 This is invoked from an imaginary node ref on right side of a 397 rewrite rule as IMAG["IMAG"]. 398 399 This should invoke createToken(int,String). 400 """ 401 402 raise NotImplementedError 403 404 # C o n t e n t 405 406 def getType(self, t): 407 """For tree parsing, I need to know the token type of a node""" 408 409 raise NotImplementedError 410 411 def setType(self, t, type): 412 """Node constructors can set the type of a node""" 413 414 raise NotImplementedError 415 416 def getText(self, t): 417 raise NotImplementedError 418 419 def setText(self, t, text): 420 """Node constructors can set the text of a node""" 421 422 raise NotImplementedError 423 424 def getToken(self, t): 425 """Return the token object from which this node was created. 426 427 Currently used only for printing an error message. 428 The error display routine in BaseRecognizer needs to 429 display where the input the error occurred. If your 430 tree of limitation does not store information that can 431 lead you to the token, you can create a token filled with 432 the appropriate information and pass that back. See 433 BaseRecognizer.getErrorMessage(). 434 """ 435 436 raise NotImplementedError 437 438 def setTokenBoundaries(self, t, startToken, stopToken): 439 """ 440 Where are the bounds in the input token stream for this node and 441 all children? Each rule that creates AST nodes will call this 442 method right before returning. Flat trees (i.e., lists) will 443 still usually have a nil root node just to hold the children list. 444 That node would contain the start/stop indexes then. 445 """ 446 447 raise NotImplementedError 448 449 def getTokenStartIndex(self, t): 450 """ 451 Get the token start index for this subtree; return -1 if no such index 452 """ 453 454 raise NotImplementedError 455 456 def getTokenStopIndex(self, t): 457 """ 458 Get the token stop index for this subtree; return -1 if no such index 459 """ 460 461 raise NotImplementedError 462 463 # N a v i g a t i o n / T r e e P a r s i n g 464 465 def getChild(self, t, i): 466 """Get a child 0..n-1 node""" 467 468 raise NotImplementedError 469 470 def setChild(self, t, i, child): 471 """Set ith child (0..n-1) to t; t must be non-null and non-nil node""" 472 473 raise NotImplementedError 474 475 def deleteChild(self, t, i): 476 """Remove ith child and shift children down from right.""" 477 478 raise NotImplementedError 479 480 def getChildCount(self, t): 481 """How many children? If 0, then this is a leaf node""" 482 483 raise NotImplementedError 484 485 def getParent(self, t): 486 """ 487 Who is the parent node of this node; if null, implies node is root. 488 If your node type doesn't handle this, it's ok but the tree rewrites 489 in tree parsers need this functionality. 490 """ 491 492 raise NotImplementedError 493 494 def setParent(self, t, parent): 495 """ 496 Who is the parent node of this node; if null, implies node is root. 497 If your node type doesn't handle this, it's ok but the tree rewrites 498 in tree parsers need this functionality. 499 """ 500 501 raise NotImplementedError 502 503 def getChildIndex(self, t): 504 """ 505 What index is this node in the child list? Range: 0..n-1 506 If your node type doesn't handle this, it's ok but the tree rewrites 507 in tree parsers need this functionality. 508 """ 509 510 raise NotImplementedError 511 512 def setChildIndex(self, t, index): 513 """ 514 What index is this node in the child list? Range: 0..n-1 515 If your node type doesn't handle this, it's ok but the tree rewrites 516 in tree parsers need this functionality. 517 """ 518 519 raise NotImplementedError 520 521 def replaceChildren(self, parent, startChildIndex, stopChildIndex, t): 522 """ 523 Replace from start to stop child index of parent with t, which might 524 be a list. Number of children may be different 525 after this call. 526 527 If parent is null, don't do anything; must be at root of overall tree. 528 Can't replace whatever points to the parent externally. Do nothing. 529 """ 530 531 raise NotImplementedError 532 533 # Misc 534 535 def create(self, *args): 536 """ 537 Deprecated, use createWithPayload, createFromToken or createFromType. 538 539 This method only exists to mimic the Java interface of TreeAdaptor. 540 541 """ 542 543 if len(args) == 1 and isinstance(args[0], Token): 544 # Object create(Token payload); 545 ## warnings.warn( 546 ## "Using create() is deprecated, use createWithPayload()", 547 ## DeprecationWarning, 548 ## stacklevel=2 549 ## ) 550 return self.createWithPayload(args[0]) 551 552 if (len(args) == 2 and isinstance(args[0], six.integer_types) and 553 isinstance(args[1], Token)): 554 # Object create(int tokenType, Token fromToken); 555 ## warnings.warn( 556 ## "Using create() is deprecated, use createFromToken()", 557 ## DeprecationWarning, 558 ## stacklevel=2 559 ## ) 560 return self.createFromToken(args[0], args[1]) 561 562 if (len(args) == 3 and isinstance(args[0], six.integer_types) and 563 isinstance(args[1], Token) and isinstance(args[2], six.string_types)): 564 # Object create(int tokenType, Token fromToken, String text); 565 ## warnings.warn( 566 ## "Using create() is deprecated, use createFromToken()", 567 ## DeprecationWarning, 568 ## stacklevel=2 569 ## ) 570 return self.createFromToken(args[0], args[1], args[2]) 571 572 if (len(args) == 2 and isinstance(args[0], six.integer_types) and 573 isinstance(args[1], six.string_types)): 574 # Object create(int tokenType, String text); 575 ## warnings.warn( 576 ## "Using create() is deprecated, use createFromType()", 577 ## DeprecationWarning, 578 ## stacklevel=2 579 ## ) 580 return self.createFromType(args[0], args[1]) 581 582 raise TypeError("No create method with this signature found: %s" % 583 (", ".join(type(v).__name__ for v in args))) 584 585 586############################################################################ 587# 588# base implementation of Tree and TreeAdaptor 589# 590# Tree 591# \- BaseTree 592# 593# TreeAdaptor 594# \- BaseTreeAdaptor 595# 596############################################################################ 597 598 599class BaseTree(Tree): 600 """ 601 @brief A generic tree implementation with no payload. 602 603 You must subclass to 604 actually have any user data. ANTLR v3 uses a list of children approach 605 instead of the child-sibling approach in v2. A flat tree (a list) is 606 an empty node whose children represent the list. An empty, but 607 non-null node is called "nil". 608 """ 609 610 # BaseTree is abstract, no need to complain about not implemented abstract 611 # methods 612 # pylint: disable-msg=W0223 613 614 def __init__(self, node=None): 615 """ 616 Create a new node from an existing node does nothing for BaseTree 617 as there are no fields other than the children list, which cannot 618 be copied as the children are not considered part of this node. 619 """ 620 621 Tree.__init__(self) 622 self.children = [] 623 self.parent = None 624 self.childIndex = 0 625 626 def getChild(self, i): 627 try: 628 return self.children[i] 629 except IndexError: 630 return None 631 632 def getChildren(self): 633 """@brief Get the children internal List 634 635 Note that if you directly mess with 636 the list, do so at your own risk. 637 """ 638 639 # FIXME: mark as deprecated 640 return self.children 641 642 def getFirstChildWithType(self, treeType): 643 for child in self.children: 644 if child.getType() == treeType: 645 return child 646 647 return None 648 649 def getChildCount(self): 650 return len(self.children) 651 652 def addChild(self, childTree): 653 """Add t as child of this node. 654 655 Warning: if t has no children, but child does 656 and child isNil then this routine moves children to t via 657 t.children = child.children; i.e., without copying the array. 658 """ 659 660 # this implementation is much simpler and probably less efficient 661 # than the mumbo-jumbo that Ter did for the Java runtime. 662 663 if childTree is None: 664 return 665 666 if childTree.isNil(): 667 # t is an empty node possibly with children 668 669 if self.children is childTree.children: 670 raise ValueError("attempt to add child list to itself") 671 672 # fix parent pointer and childIndex for new children 673 for idx, child in enumerate(childTree.children): 674 child.parent = self 675 child.childIndex = len(self.children) + idx 676 677 self.children += childTree.children 678 679 else: 680 # child is not nil (don't care about children) 681 self.children.append(childTree) 682 childTree.parent = self 683 childTree.childIndex = len(self.children) - 1 684 685 def addChildren(self, children): 686 """Add all elements of kids list as children of this node""" 687 688 self.children += children 689 690 def setChild(self, i, t): 691 if t is None: 692 return 693 694 if t.isNil(): 695 raise ValueError("Can't set single child to a list") 696 697 self.children[i] = t 698 t.parent = self 699 t.childIndex = i 700 701 def deleteChild(self, i): 702 killed = self.children[i] 703 704 del self.children[i] 705 706 # walk rest and decrement their child indexes 707 for idx, child in enumerate(self.children[i:]): 708 child.childIndex = i + idx 709 710 return killed 711 712 def replaceChildren(self, startChildIndex, stopChildIndex, newTree): 713 """ 714 Delete children from start to stop and replace with t even if t is 715 a list (nil-root tree). num of children can increase or decrease. 716 For huge child lists, inserting children can force walking rest of 717 children to set their childindex; could be slow. 718 """ 719 720 if (startChildIndex >= len(self.children) or 721 stopChildIndex >= len(self.children)): 722 raise IndexError("indexes invalid") 723 724 replacingHowMany = stopChildIndex - startChildIndex + 1 725 726 # normalize to a list of children to add: newChildren 727 if newTree.isNil(): 728 newChildren = newTree.children 729 730 else: 731 newChildren = [newTree] 732 733 replacingWithHowMany = len(newChildren) 734 delta = replacingHowMany - replacingWithHowMany 735 736 if delta == 0: 737 # if same number of nodes, do direct replace 738 for idx, child in enumerate(newChildren): 739 self.children[idx + startChildIndex] = child 740 child.parent = self 741 child.childIndex = idx + startChildIndex 742 743 else: 744 # length of children changes... 745 746 # ...delete replaced segment... 747 del self.children[startChildIndex:stopChildIndex + 1] 748 749 # ...insert new segment... 750 self.children[startChildIndex:startChildIndex] = newChildren 751 752 # ...and fix indeces 753 self.freshenParentAndChildIndexes(startChildIndex) 754 755 def isNil(self): 756 return False 757 758 def freshenParentAndChildIndexes(self, offset=0): 759 for idx, child in enumerate(self.children[offset:]): 760 child.childIndex = idx + offset 761 child.parent = self 762 763 def sanityCheckParentAndChildIndexes(self, parent=None, i=-1): 764 if parent != self.parent: 765 raise ValueError("parents don't match; expected %r found %r" % 766 (parent, self.parent)) 767 768 if i != self.childIndex: 769 raise ValueError("child indexes don't match; expected %d found %d" % 770 (i, self.childIndex)) 771 772 for idx, child in enumerate(self.children): 773 child.sanityCheckParentAndChildIndexes(self, idx) 774 775 def getChildIndex(self): 776 """BaseTree doesn't track child indexes.""" 777 778 return 0 779 780 def setChildIndex(self, index): 781 """BaseTree doesn't track child indexes.""" 782 783 pass 784 785 def getParent(self): 786 """BaseTree doesn't track parent pointers.""" 787 788 return None 789 790 def setParent(self, t): 791 """BaseTree doesn't track parent pointers.""" 792 793 pass 794 795 def toStringTree(self): 796 """Print out a whole tree not just a node""" 797 798 if len(self.children) == 0: 799 return self.toString() 800 801 buf = [] 802 if not self.isNil(): 803 buf.append("(") 804 buf.append(self.toString()) 805 buf.append(" ") 806 807 for i, child in enumerate(self.children): 808 if i > 0: 809 buf.append(" ") 810 buf.append(child.toStringTree()) 811 812 if not self.isNil(): 813 buf.append(")") 814 815 return "".join(buf) 816 817 def getLine(self): 818 return 0 819 820 def getCharPositionInLine(self): 821 return 0 822 823 def toString(self): 824 """Override to say how a node (not a tree) should look as text""" 825 826 raise NotImplementedError 827 828 829 830class BaseTreeAdaptor(TreeAdaptor): 831 """ 832 @brief A TreeAdaptor that works with any Tree implementation. 833 """ 834 835 # BaseTreeAdaptor is abstract, no need to complain about not implemented 836 # abstract methods 837 # pylint: disable-msg=W0223 838 839 def nil(self): 840 return self.createWithPayload(None) 841 842 def errorNode(self, input, start, stop, exc): 843 """ 844 create tree node that holds the start and stop tokens associated 845 with an error. 846 847 If you specify your own kind of tree nodes, you will likely have to 848 override this method. CommonTree returns Token.INVALID_TOKEN_TYPE 849 if no token payload but you might have to set token type for diff 850 node type. 851 """ 852 853 return CommonErrorNode(input, start, stop, exc) 854 855 def isNil(self, tree): 856 return tree.isNil() 857 858 def dupTree(self, t, parent=None): 859 """ 860 This is generic in the sense that it will work with any kind of 861 tree (not just Tree interface). It invokes the adaptor routines 862 not the tree node routines to do the construction. 863 """ 864 865 if t is None: 866 return None 867 868 newTree = self.dupNode(t) 869 870 # ensure new subtree root has parent/child index set 871 872 # same index in new tree 873 self.setChildIndex(newTree, self.getChildIndex(t)) 874 875 self.setParent(newTree, parent) 876 877 for i in range(self.getChildCount(t)): 878 child = self.getChild(t, i) 879 newSubTree = self.dupTree(child, t) 880 self.addChild(newTree, newSubTree) 881 882 return newTree 883 884 def addChild(self, tree, child): 885 """ 886 Add a child to the tree t. If child is a flat tree (a list), make all 887 in list children of t. Warning: if t has no children, but child does 888 and child isNil then you can decide it is ok to move children to t via 889 t.children = child.children; i.e., without copying the array. Just 890 make sure that this is consistent with have the user will build 891 ASTs. 892 """ 893 894 #if isinstance(child, Token): 895 # child = self.createWithPayload(child) 896 897 if tree is not None and child is not None: 898 tree.addChild(child) 899 900 def becomeRoot(self, newRoot, oldRoot): 901 """ 902 If oldRoot is a nil root, just copy or move the children to newRoot. 903 If not a nil root, make oldRoot a child of newRoot. 904 905 old=^(nil a b c), new=r yields ^(r a b c) 906 old=^(a b c), new=r yields ^(r ^(a b c)) 907 908 If newRoot is a nil-rooted single child tree, use the single 909 child as the new root node. 910 911 old=^(nil a b c), new=^(nil r) yields ^(r a b c) 912 old=^(a b c), new=^(nil r) yields ^(r ^(a b c)) 913 914 If oldRoot was null, it's ok, just return newRoot (even if isNil). 915 916 old=null, new=r yields r 917 old=null, new=^(nil r) yields ^(nil r) 918 919 Return newRoot. Throw an exception if newRoot is not a 920 simple node or nil root with a single child node--it must be a root 921 node. If newRoot is ^(nil x) return x as newRoot. 922 923 Be advised that it's ok for newRoot to point at oldRoot's 924 children; i.e., you don't have to copy the list. We are 925 constructing these nodes so we should have this control for 926 efficiency. 927 """ 928 929 if isinstance(newRoot, Token): 930 newRoot = self.create(newRoot) 931 932 if oldRoot is None: 933 return newRoot 934 935 if not isinstance(newRoot, CommonTree): 936 newRoot = self.createWithPayload(newRoot) 937 938 # handle ^(nil real-node) 939 if newRoot.isNil(): 940 nc = newRoot.getChildCount() 941 if nc == 1: 942 newRoot = newRoot.getChild(0) 943 944 elif nc > 1: 945 # TODO: make tree run time exceptions hierarchy 946 raise RuntimeError("more than one node as root") 947 948 # add oldRoot to newRoot; addChild takes care of case where oldRoot 949 # is a flat list (i.e., nil-rooted tree). All children of oldRoot 950 # are added to newRoot. 951 newRoot.addChild(oldRoot) 952 return newRoot 953 954 def rulePostProcessing(self, root): 955 """Transform ^(nil x) to x and nil to null""" 956 957 if root is not None and root.isNil(): 958 if root.getChildCount() == 0: 959 root = None 960 961 elif root.getChildCount() == 1: 962 root = root.getChild(0) 963 # whoever invokes rule will set parent and child index 964 root.setParent(None) 965 root.setChildIndex(-1) 966 967 return root 968 969 def createFromToken(self, tokenType, fromToken, text=None): 970 assert isinstance(tokenType, six.integer_types), type(tokenType).__name__ 971 assert isinstance(fromToken, Token), type(fromToken).__name__ 972 assert text is None or isinstance(text, 973 six.string_types), type(text).__name__ 974 975 fromToken = self.createToken(fromToken) 976 fromToken.type = tokenType 977 if text is not None: 978 fromToken.text = text 979 t = self.createWithPayload(fromToken) 980 return t 981 982 def createFromType(self, tokenType, text): 983 assert isinstance(tokenType, six.integer_types), type(tokenType).__name__ 984 assert isinstance(text, six.string_types), type(text).__name__ 985 986 fromToken = self.createToken(tokenType=tokenType, text=text) 987 t = self.createWithPayload(fromToken) 988 return t 989 990 def getType(self, t): 991 return t.getType() 992 993 def setType(self, t, type): 994 raise RuntimeError("don't know enough about Tree node") 995 996 def getText(self, t): 997 return t.getText() 998 999 def setText(self, t, text): 1000 raise RuntimeError("don't know enough about Tree node") 1001 1002 def getChild(self, t, i): 1003 return t.getChild(i) 1004 1005 def setChild(self, t, i, child): 1006 t.setChild(i, child) 1007 1008 def deleteChild(self, t, i): 1009 return t.deleteChild(i) 1010 1011 def getChildCount(self, t): 1012 return t.getChildCount() 1013 1014 def getUniqueID(self, node): 1015 return hash(node) 1016 1017 def createToken(self, fromToken=None, tokenType=None, text=None): 1018 """ 1019 Tell me how to create a token for use with imaginary token nodes. 1020 For example, there is probably no input symbol associated with imaginary 1021 token DECL, but you need to create it as a payload or whatever for 1022 the DECL node as in ^(DECL type ID). 1023 1024 If you care what the token payload objects' type is, you should 1025 override this method and any other createToken variant. 1026 """ 1027 1028 raise NotImplementedError 1029 1030 1031############################################################################ 1032# 1033# common tree implementation 1034# 1035# Tree 1036# \- BaseTree 1037# \- CommonTree 1038# \- CommonErrorNode 1039# 1040# TreeAdaptor 1041# \- BaseTreeAdaptor 1042# \- CommonTreeAdaptor 1043# 1044############################################################################ 1045 1046 1047class CommonTree(BaseTree): 1048 """@brief A tree node that is wrapper for a Token object. 1049 1050 After 3.0 release 1051 while building tree rewrite stuff, it became clear that computing 1052 parent and child index is very difficult and cumbersome. Better to 1053 spend the space in every tree node. If you don't want these extra 1054 fields, it's easy to cut them out in your own BaseTree subclass. 1055 1056 """ 1057 1058 def __init__(self, payload): 1059 BaseTree.__init__(self) 1060 1061 # What token indexes bracket all tokens associated with this node 1062 # and below? 1063 self.startIndex = -1 1064 self.stopIndex = -1 1065 1066 # Who is the parent node of this node; if null, implies node is root 1067 self.parent = None 1068 1069 # What index is this node in the child list? Range: 0..n-1 1070 self.childIndex = -1 1071 1072 # A single token is the payload 1073 if payload is None: 1074 self.token = None 1075 1076 elif isinstance(payload, CommonTree): 1077 self.token = payload.token 1078 self.startIndex = payload.startIndex 1079 self.stopIndex = payload.stopIndex 1080 1081 elif payload is None or isinstance(payload, Token): 1082 self.token = payload 1083 1084 else: 1085 raise TypeError(type(payload).__name__) 1086 1087 def getToken(self): 1088 return self.token 1089 1090 def dupNode(self): 1091 return CommonTree(self) 1092 1093 def isNil(self): 1094 return self.token is None 1095 1096 def getType(self): 1097 if self.token is None: 1098 return INVALID_TOKEN_TYPE 1099 1100 return self.token.getType() 1101 1102 type = property(getType) 1103 1104 def getText(self): 1105 if self.token is None: 1106 return None 1107 1108 return self.token.text 1109 1110 text = property(getText) 1111 1112 def getLine(self): 1113 if self.token is None or self.token.getLine() == 0: 1114 if self.getChildCount(): 1115 return self.getChild(0).getLine() 1116 else: 1117 return 0 1118 1119 return self.token.getLine() 1120 1121 line = property(getLine) 1122 1123 def getCharPositionInLine(self): 1124 if self.token is None or self.token.getCharPositionInLine() == -1: 1125 if self.getChildCount(): 1126 return self.getChild(0).getCharPositionInLine() 1127 else: 1128 return 0 1129 1130 else: 1131 return self.token.getCharPositionInLine() 1132 1133 charPositionInLine = property(getCharPositionInLine) 1134 1135 def getTokenStartIndex(self): 1136 if self.startIndex == -1 and self.token is not None: 1137 return self.token.getTokenIndex() 1138 1139 return self.startIndex 1140 1141 def setTokenStartIndex(self, index): 1142 self.startIndex = index 1143 1144 tokenStartIndex = property(getTokenStartIndex, setTokenStartIndex) 1145 1146 def getTokenStopIndex(self): 1147 if self.stopIndex == -1 and self.token is not None: 1148 return self.token.getTokenIndex() 1149 1150 return self.stopIndex 1151 1152 def setTokenStopIndex(self, index): 1153 self.stopIndex = index 1154 1155 tokenStopIndex = property(getTokenStopIndex, setTokenStopIndex) 1156 1157 def getChildIndex(self): 1158 #FIXME: mark as deprecated 1159 return self.childIndex 1160 1161 def setChildIndex(self, idx): 1162 #FIXME: mark as deprecated 1163 self.childIndex = idx 1164 1165 def getParent(self): 1166 #FIXME: mark as deprecated 1167 return self.parent 1168 1169 def setParent(self, t): 1170 #FIXME: mark as deprecated 1171 self.parent = t 1172 1173 def toString(self): 1174 if self.isNil(): 1175 return "nil" 1176 1177 if self.getType() == INVALID_TOKEN_TYPE: 1178 return "<errornode>" 1179 1180 return self.token.text 1181 1182 __str__ = toString 1183 1184 def toStringTree(self): 1185 if not self.children: 1186 return self.toString() 1187 1188 ret = "" 1189 if not self.isNil(): 1190 ret += "(%s " % (self.toString()) 1191 1192 ret += " ".join([child.toStringTree() for child in self.children]) 1193 1194 if not self.isNil(): 1195 ret += ")" 1196 1197 return ret 1198 1199 1200INVALID_NODE = CommonTree(INVALID_TOKEN) 1201 1202 1203class CommonErrorNode(CommonTree): 1204 """A node representing erroneous token range in token stream""" 1205 1206 def __init__(self, input, start, stop, exc): 1207 CommonTree.__init__(self, None) 1208 1209 if (stop is None or (stop.getTokenIndex() < start.getTokenIndex() and 1210 stop.getType() != EOF)): 1211 # sometimes resync does not consume a token (when LT(1) is 1212 # in follow set. So, stop will be 1 to left to start. adjust. 1213 # Also handle case where start is the first token and no token 1214 # is consumed during recovery; LT(-1) will return null. 1215 stop = start 1216 1217 self.input = input 1218 self.start = start 1219 self.stop = stop 1220 self.trappedException = exc 1221 1222 def isNil(self): 1223 return False 1224 1225 def getType(self): 1226 return INVALID_TOKEN_TYPE 1227 1228 def getText(self): 1229 if isinstance(self.start, Token): 1230 i = self.start.getTokenIndex() 1231 j = self.stop.getTokenIndex() 1232 if self.stop.getType() == EOF: 1233 j = self.input.size() 1234 1235 badText = self.input.toString(i, j) 1236 1237 elif isinstance(self.start, Tree): 1238 badText = self.input.toString(self.start, self.stop) 1239 1240 else: 1241 # people should subclass if they alter the tree type so this 1242 # next one is for sure correct. 1243 badText = "<unknown>" 1244 1245 return badText 1246 1247 def toString(self): 1248 if isinstance(self.trappedException, MissingTokenException): 1249 return ("<missing type: " + str(self.trappedException.getMissingType()) + 1250 ">") 1251 1252 elif isinstance(self.trappedException, UnwantedTokenException): 1253 return ("<extraneous: " + 1254 str(self.trappedException.getUnexpectedToken()) + ", resync=" + 1255 self.getText() + ">") 1256 1257 elif isinstance(self.trappedException, MismatchedTokenException): 1258 return ("<mismatched token: " + str(self.trappedException.token) + 1259 ", resync=" + self.getText() + ">") 1260 1261 elif isinstance(self.trappedException, NoViableAltException): 1262 return ("<unexpected: " + str(self.trappedException.token) + ", resync=" + 1263 self.getText() + ">") 1264 1265 return "<error: " + self.getText() + ">" 1266 1267 1268class CommonTreeAdaptor(BaseTreeAdaptor): 1269 """ 1270 @brief A TreeAdaptor that works with any Tree implementation. 1271 1272 It provides 1273 really just factory methods; all the work is done by BaseTreeAdaptor. 1274 If you would like to have different tokens created than ClassicToken 1275 objects, you need to override this and then set the parser tree adaptor to 1276 use your subclass. 1277 1278 To get your parser to build nodes of a different type, override 1279 create(Token). 1280 """ 1281 1282 def dupNode(self, treeNode): 1283 """ 1284 Duplicate a node. This is part of the factory; 1285 override if you want another kind of node to be built. 1286 1287 I could use reflection to prevent having to override this 1288 but reflection is slow. 1289 """ 1290 1291 if treeNode is None: 1292 return None 1293 1294 return treeNode.dupNode() 1295 1296 def createWithPayload(self, payload): 1297 return CommonTree(payload) 1298 1299 def createToken(self, fromToken=None, tokenType=None, text=None): 1300 """ 1301 Tell me how to create a token for use with imaginary token nodes. 1302 For example, there is probably no input symbol associated with imaginary 1303 token DECL, but you need to create it as a payload or whatever for 1304 the DECL node as in ^(DECL type ID). 1305 1306 If you care what the token payload objects' type is, you should 1307 override this method and any other createToken variant. 1308 """ 1309 1310 if fromToken is not None: 1311 return CommonToken(oldToken=fromToken) 1312 1313 return CommonToken(type=tokenType, text=text) 1314 1315 def setTokenBoundaries(self, t, startToken, stopToken): 1316 """ 1317 Track start/stop token for subtree root created for a rule. 1318 Only works with Tree nodes. For rules that match nothing, 1319 seems like this will yield start=i and stop=i-1 in a nil node. 1320 Might be useful info so I'll not force to be i..i. 1321 """ 1322 1323 if t is None: 1324 return 1325 1326 start = 0 1327 stop = 0 1328 1329 if startToken is not None: 1330 start = startToken.index 1331 1332 if stopToken is not None: 1333 stop = stopToken.index 1334 1335 t.setTokenStartIndex(start) 1336 t.setTokenStopIndex(stop) 1337 1338 def getTokenStartIndex(self, t): 1339 if t is None: 1340 return -1 1341 return t.getTokenStartIndex() 1342 1343 def getTokenStopIndex(self, t): 1344 if t is None: 1345 return -1 1346 return t.getTokenStopIndex() 1347 1348 def getText(self, t): 1349 if t is None: 1350 return None 1351 return t.getText() 1352 1353 def getType(self, t): 1354 if t is None: 1355 return INVALID_TOKEN_TYPE 1356 1357 return t.getType() 1358 1359 def getToken(self, t): 1360 """ 1361 What is the Token associated with this node? If 1362 you are not using CommonTree, then you must 1363 override this in your own adaptor. 1364 """ 1365 1366 if isinstance(t, CommonTree): 1367 return t.getToken() 1368 1369 return None # no idea what to do 1370 1371 def getChild(self, t, i): 1372 if t is None: 1373 return None 1374 return t.getChild(i) 1375 1376 def getChildCount(self, t): 1377 if t is None: 1378 return 0 1379 return t.getChildCount() 1380 1381 def getParent(self, t): 1382 return t.getParent() 1383 1384 def setParent(self, t, parent): 1385 t.setParent(parent) 1386 1387 def getChildIndex(self, t): 1388 return t.getChildIndex() 1389 1390 def setChildIndex(self, t, index): 1391 t.setChildIndex(index) 1392 1393 def replaceChildren(self, parent, startChildIndex, stopChildIndex, t): 1394 if parent is not None: 1395 parent.replaceChildren(startChildIndex, stopChildIndex, t) 1396 1397 1398############################################################################ 1399# 1400# streams 1401# 1402# TreeNodeStream 1403# \- BaseTree 1404# \- CommonTree 1405# 1406# TreeAdaptor 1407# \- BaseTreeAdaptor 1408# \- CommonTreeAdaptor 1409# 1410############################################################################ 1411 1412 1413 1414class TreeNodeStream(IntStream): 1415 """@brief A stream of tree nodes 1416 1417 It accessing nodes from a tree of some kind. 1418 """ 1419 1420 # TreeNodeStream is abstract, no need to complain about not implemented 1421 # abstract methods 1422 # pylint: disable-msg=W0223 1423 1424 def get(self, i): 1425 """Get a tree node at an absolute index i; 0..n-1. 1426 1427 If you don't want to buffer up nodes, then this method makes no 1428 sense for you. 1429 """ 1430 1431 raise NotImplementedError 1432 1433 def LT(self, k): 1434 """ 1435 Get tree node at current input pointer + i ahead where i=1 is next node. 1436 i<0 indicates nodes in the past. So LT(-1) is previous node, but 1437 implementations are not required to provide results for k < -1. 1438 LT(0) is undefined. For i>=n, return null. 1439 Return null for LT(0) and any index that results in an absolute address 1440 that is negative. 1441 1442 This is analogus to the LT() method of the TokenStream, but this 1443 returns a tree node instead of a token. Makes code gen identical 1444 for both parser and tree grammars. :) 1445 """ 1446 1447 raise NotImplementedError 1448 1449 def getTreeSource(self): 1450 """ 1451 Where is this stream pulling nodes from? This is not the name, but 1452 the object that provides node objects. 1453 """ 1454 1455 raise NotImplementedError 1456 1457 def getTokenStream(self): 1458 """ 1459 If the tree associated with this stream was created from a TokenStream, 1460 you can specify it here. Used to do rule $text attribute in tree 1461 parser. Optional unless you use tree parser rule text attribute 1462 or output=template and rewrite=true options. 1463 """ 1464 1465 raise NotImplementedError 1466 1467 def getTreeAdaptor(self): 1468 """ 1469 What adaptor can tell me how to interpret/navigate nodes and 1470 trees. E.g., get text of a node. 1471 """ 1472 1473 raise NotImplementedError 1474 1475 def setUniqueNavigationNodes(self, uniqueNavigationNodes): 1476 """ 1477 As we flatten the tree, we use UP, DOWN nodes to represent 1478 the tree structure. When debugging we need unique nodes 1479 so we have to instantiate new ones. When doing normal tree 1480 parsing, it's slow and a waste of memory to create unique 1481 navigation nodes. Default should be false; 1482 """ 1483 1484 raise NotImplementedError 1485 1486 def toString(self, start, stop): 1487 """ 1488 Return the text of all nodes from start to stop, inclusive. 1489 If the stream does not buffer all the nodes then it can still 1490 walk recursively from start until stop. You can always return 1491 null or "" too, but users should not access $ruleLabel.text in 1492 an action of course in that case. 1493 """ 1494 1495 raise NotImplementedError 1496 1497 # REWRITING TREES (used by tree parser) 1498 def replaceChildren(self, parent, startChildIndex, stopChildIndex, t): 1499 """ 1500 Replace from start to stop child index of parent with t, which might 1501 be a list. Number of children may be different 1502 after this call. The stream is notified because it is walking the 1503 tree and might need to know you are monkeying with the underlying 1504 tree. Also, it might be able to modify the node stream to avoid 1505 restreaming for future phases. 1506 1507 If parent is null, don't do anything; must be at root of overall tree. 1508 Can't replace whatever points to the parent externally. Do nothing. 1509 """ 1510 1511 raise NotImplementedError 1512 1513 1514class CommonTreeNodeStream(TreeNodeStream): 1515 """@brief A buffered stream of tree nodes. 1516 1517 Nodes can be from a tree of ANY kind. 1518 1519 This node stream sucks all nodes out of the tree specified in 1520 the constructor during construction and makes pointers into 1521 the tree using an array of Object pointers. The stream necessarily 1522 includes pointers to DOWN and UP and EOF nodes. 1523 1524 This stream knows how to mark/release for backtracking. 1525 1526 This stream is most suitable for tree interpreters that need to 1527 jump around a lot or for tree parsers requiring speed (at cost of memory). 1528 There is some duplicated functionality here with UnBufferedTreeNodeStream 1529 but just in bookkeeping, not tree walking etc... 1530 1531 @see UnBufferedTreeNodeStream 1532 """ 1533 1534 def __init__(self, *args): 1535 TreeNodeStream.__init__(self) 1536 1537 if len(args) == 1: 1538 adaptor = CommonTreeAdaptor() 1539 tree = args[0] 1540 1541 elif len(args) == 2: 1542 adaptor = args[0] 1543 tree = args[1] 1544 1545 else: 1546 raise TypeError("Invalid arguments") 1547 1548 # all these navigation nodes are shared and hence they 1549 # cannot contain any line/column info 1550 self.down = adaptor.createFromType(DOWN, "DOWN") 1551 self.up = adaptor.createFromType(UP, "UP") 1552 self.eof = adaptor.createFromType(EOF, "EOF") 1553 1554 # The complete mapping from stream index to tree node. 1555 # This buffer includes pointers to DOWN, UP, and EOF nodes. 1556 # It is built upon ctor invocation. The elements are type 1557 # Object as we don't what the trees look like. 1558 1559 # Load upon first need of the buffer so we can set token types 1560 # of interest for reverseIndexing. Slows us down a wee bit to 1561 # do all of the if p==-1 testing everywhere though. 1562 self.nodes = [] 1563 1564 # Pull nodes from which tree? 1565 self.root = tree 1566 1567 # IF this tree (root) was created from a token stream, track it. 1568 self.tokens = None 1569 1570 # What tree adaptor was used to build these trees 1571 self.adaptor = adaptor 1572 1573 # Reuse same DOWN, UP navigation nodes unless this is true 1574 self.uniqueNavigationNodes = False 1575 1576 # The index into the nodes list of the current node (next node 1577 # to consume). If -1, nodes array not filled yet. 1578 self.p = -1 1579 1580 # Track the last mark() call result value for use in rewind(). 1581 self.lastMarker = None 1582 1583 # Stack of indexes used for push/pop calls 1584 self.calls = [] 1585 1586 def fillBuffer(self): 1587 """Walk tree with depth-first-search and fill nodes buffer. 1588 1589 Don't do DOWN, UP nodes if its a list (t is isNil). 1590 """ 1591 1592 self._fillBuffer(self.root) 1593 self.p = 0 # buffer of nodes intialized now 1594 1595 def _fillBuffer(self, t): 1596 nil = self.adaptor.isNil(t) 1597 1598 if not nil: 1599 self.nodes.append(t) # add this node 1600 1601 # add DOWN node if t has children 1602 n = self.adaptor.getChildCount(t) 1603 if not nil and n > 0: 1604 self.addNavigationNode(DOWN) 1605 1606 # and now add all its children 1607 for c in range(n): 1608 self._fillBuffer(self.adaptor.getChild(t, c)) 1609 1610 # add UP node if t has children 1611 if not nil and n > 0: 1612 self.addNavigationNode(UP) 1613 1614 def getNodeIndex(self, node): 1615 """What is the stream index for node? 1616 1617 0..n-1 1618 Return -1 if node not found. 1619 """ 1620 1621 if self.p == -1: 1622 self.fillBuffer() 1623 1624 for i, t in enumerate(self.nodes): 1625 if t == node: 1626 return i 1627 1628 return -1 1629 1630 def addNavigationNode(self, ttype): 1631 """ 1632 As we flatten the tree, we use UP, DOWN nodes to represent 1633 the tree structure. When debugging we need unique nodes 1634 so instantiate new ones when uniqueNavigationNodes is true. 1635 """ 1636 1637 navNode = None 1638 1639 if ttype == DOWN: 1640 if self.hasUniqueNavigationNodes(): 1641 navNode = self.adaptor.createFromType(DOWN, "DOWN") 1642 1643 else: 1644 navNode = self.down 1645 1646 else: 1647 if self.hasUniqueNavigationNodes(): 1648 navNode = self.adaptor.createFromType(UP, "UP") 1649 1650 else: 1651 navNode = self.up 1652 1653 self.nodes.append(navNode) 1654 1655 def get(self, i): 1656 if self.p == -1: 1657 self.fillBuffer() 1658 1659 return self.nodes[i] 1660 1661 def LT(self, k): 1662 if self.p == -1: 1663 self.fillBuffer() 1664 1665 if k == 0: 1666 return None 1667 1668 if k < 0: 1669 return self.LB(-k) 1670 1671 #System.out.print("LT(p="+p+","+k+")="); 1672 if self.p + k - 1 >= len(self.nodes): 1673 return self.eof 1674 1675 return self.nodes[self.p + k - 1] 1676 1677 def getCurrentSymbol(self): 1678 return self.LT(1) 1679 1680 def LB(self, k): 1681 """Look backwards k nodes""" 1682 1683 if k == 0: 1684 return None 1685 1686 if self.p - k < 0: 1687 return None 1688 1689 return self.nodes[self.p - k] 1690 1691 def getTreeSource(self): 1692 return self.root 1693 1694 def getSourceName(self): 1695 return self.getTokenStream().getSourceName() 1696 1697 def getTokenStream(self): 1698 return self.tokens 1699 1700 def setTokenStream(self, tokens): 1701 self.tokens = tokens 1702 1703 def getTreeAdaptor(self): 1704 return self.adaptor 1705 1706 def hasUniqueNavigationNodes(self): 1707 return self.uniqueNavigationNodes 1708 1709 def setUniqueNavigationNodes(self, uniqueNavigationNodes): 1710 self.uniqueNavigationNodes = uniqueNavigationNodes 1711 1712 def consume(self): 1713 if self.p == -1: 1714 self.fillBuffer() 1715 1716 self.p += 1 1717 1718 def LA(self, i): 1719 return self.adaptor.getType(self.LT(i)) 1720 1721 def mark(self): 1722 if self.p == -1: 1723 self.fillBuffer() 1724 1725 self.lastMarker = self.index() 1726 return self.lastMarker 1727 1728 def release(self, marker=None): 1729 # no resources to release 1730 1731 pass 1732 1733 def index(self): 1734 return self.p 1735 1736 def rewind(self, marker=None): 1737 if marker is None: 1738 marker = self.lastMarker 1739 1740 self.seek(marker) 1741 1742 def seek(self, index): 1743 if self.p == -1: 1744 self.fillBuffer() 1745 1746 self.p = index 1747 1748 def push(self, index): 1749 """ 1750 Make stream jump to a new location, saving old location. 1751 Switch back with pop(). 1752 """ 1753 1754 self.calls.append(self.p) # save current index 1755 self.seek(index) 1756 1757 def pop(self): 1758 """ 1759 Seek back to previous index saved during last push() call. 1760 Return top of stack (return index). 1761 """ 1762 1763 ret = self.calls.pop(-1) 1764 self.seek(ret) 1765 return ret 1766 1767 def reset(self): 1768 self.p = 0 1769 self.lastMarker = 0 1770 self.calls = [] 1771 1772 def size(self): 1773 if self.p == -1: 1774 self.fillBuffer() 1775 1776 return len(self.nodes) 1777 1778 # TREE REWRITE INTERFACE 1779 1780 def replaceChildren(self, parent, startChildIndex, stopChildIndex, t): 1781 if parent is not None: 1782 self.adaptor.replaceChildren(parent, startChildIndex, stopChildIndex, t) 1783 1784 def __str__(self): 1785 """Used for testing, just return the token type stream""" 1786 1787 if self.p == -1: 1788 self.fillBuffer() 1789 1790 return " ".join([str(self.adaptor.getType(node)) for node in self.nodes]) 1791 1792 def toString(self, start, stop): 1793 if start is None or stop is None: 1794 return None 1795 1796 if self.p == -1: 1797 self.fillBuffer() 1798 1799 #System.out.println("stop: "+stop); 1800 #if ( start instanceof CommonTree ) 1801 # System.out.print("toString: "+((CommonTree)start).getToken()+", "); 1802 #else 1803 # System.out.println(start); 1804 #if ( stop instanceof CommonTree ) 1805 # System.out.println(((CommonTree)stop).getToken()); 1806 #else 1807 # System.out.println(stop); 1808 1809 # if we have the token stream, use that to dump text in order 1810 if self.tokens is not None: 1811 beginTokenIndex = self.adaptor.getTokenStartIndex(start) 1812 endTokenIndex = self.adaptor.getTokenStopIndex(stop) 1813 1814 # if it's a tree, use start/stop index from start node 1815 # else use token range from start/stop nodes 1816 if self.adaptor.getType(stop) == UP: 1817 endTokenIndex = self.adaptor.getTokenStopIndex(start) 1818 1819 elif self.adaptor.getType(stop) == EOF: 1820 endTokenIndex = self.size() - 2 # don't use EOF 1821 1822 return self.tokens.toString(beginTokenIndex, endTokenIndex) 1823 1824 # walk nodes looking for start 1825 i, t = 0, None 1826 for i, t in enumerate(self.nodes): 1827 if t == start: 1828 break 1829 1830 # now walk until we see stop, filling string buffer with text 1831 buf = [] 1832 t = self.nodes[i] 1833 while t != stop: 1834 text = self.adaptor.getText(t) 1835 if text is None: 1836 text = " " + self.adaptor.getType(t) 1837 1838 buf.append(text) 1839 i += 1 1840 t = self.nodes[i] 1841 1842 # include stop node too 1843 text = self.adaptor.getText(stop) 1844 if text is None: 1845 text = " " + self.adaptor.getType(stop) 1846 1847 buf.append(text) 1848 1849 return "".join(buf) 1850 1851 ## iterator interface 1852 def __iter__(self): 1853 if self.p == -1: 1854 self.fillBuffer() 1855 1856 for node in self.nodes: 1857 yield node 1858 1859 1860############################################################################# 1861# 1862# tree parser 1863# 1864############################################################################# 1865 1866class TreeParser(BaseRecognizer): 1867 """@brief Baseclass for generated tree parsers. 1868 1869 A parser for a stream of tree nodes. "tree grammars" result in a subclass 1870 of this. All the error reporting and recovery is shared with Parser via 1871 the BaseRecognizer superclass. 1872 """ 1873 1874 def __init__(self, input, state=None): 1875 BaseRecognizer.__init__(self, state) 1876 1877 self.input = None 1878 self.setTreeNodeStream(input) 1879 1880 def reset(self): 1881 BaseRecognizer.reset(self) # reset all recognizer state variables 1882 if self.input is not None: 1883 self.input.seek(0) # rewind the input 1884 1885 def setTreeNodeStream(self, input): 1886 """Set the input stream""" 1887 1888 self.input = input 1889 1890 def getTreeNodeStream(self): 1891 return self.input 1892 1893 def getSourceName(self): 1894 return self.input.getSourceName() 1895 1896 def getCurrentInputSymbol(self, input): 1897 return input.LT(1) 1898 1899 def getMissingSymbol(self, input, e, expectedTokenType, follow): 1900 tokenText = "<missing " + self.tokenNames[expectedTokenType] + ">" 1901 return CommonTree(CommonToken(type=expectedTokenType, text=tokenText)) 1902 1903 def matchAny(self, ignore): # ignore stream, copy of this.input 1904 """ 1905 Match '.' in tree parser has special meaning. Skip node or 1906 entire tree if node has children. If children, scan until 1907 corresponding UP node. 1908 """ 1909 1910 self._state.errorRecovery = False 1911 1912 look = self.input.LT(1) 1913 if self.input.getTreeAdaptor().getChildCount(look) == 0: 1914 self.input.consume() # not subtree, consume 1 node and return 1915 return 1916 1917 # current node is a subtree, skip to corresponding UP. 1918 # must count nesting level to get right UP 1919 level = 0 1920 tokenType = self.input.getTreeAdaptor().getType(look) 1921 while tokenType != EOF and not (tokenType == UP and level == 0): 1922 self.input.consume() 1923 look = self.input.LT(1) 1924 tokenType = self.input.getTreeAdaptor().getType(look) 1925 if tokenType == DOWN: 1926 level += 1 1927 1928 elif tokenType == UP: 1929 level -= 1 1930 1931 self.input.consume() # consume UP 1932 1933 def mismatch(self, input, ttype, follow): 1934 """ 1935 We have DOWN/UP nodes in the stream that have no line info; override. 1936 plus we want to alter the exception type. Don't try to recover 1937 from tree parser errors inline... 1938 """ 1939 1940 raise MismatchedTreeNodeException(ttype, input) 1941 1942 def getErrorHeader(self, e): 1943 """ 1944 Prefix error message with the grammar name because message is 1945 always intended for the programmer because the parser built 1946 the input tree not the user. 1947 """ 1948 1949 return ( 1950 self.getGrammarFileName() + ": node from %sline %s:%s" % 1951 (["", "after "][e.approximateLineInfo], e.line, e.charPositionInLine)) 1952 1953 def getErrorMessage(self, e, tokenNames): 1954 """ 1955 Tree parsers parse nodes they usually have a token object as 1956 payload. Set the exception token and do the default behavior. 1957 """ 1958 1959 if isinstance(self, TreeParser): 1960 adaptor = e.input.getTreeAdaptor() 1961 e.token = adaptor.getToken(e.node) 1962 if e.token is not None: # could be an UP/DOWN node 1963 e.token = CommonToken( 1964 type=adaptor.getType(e.node), text=adaptor.getText(e.node)) 1965 1966 return BaseRecognizer.getErrorMessage(self, e, tokenNames) 1967 1968 def traceIn(self, ruleName, ruleIndex): 1969 BaseRecognizer.traceIn(self, ruleName, ruleIndex, self.input.LT(1)) 1970 1971 def traceOut(self, ruleName, ruleIndex): 1972 BaseRecognizer.traceOut(self, ruleName, ruleIndex, self.input.LT(1)) 1973 1974 1975############################################################################# 1976# 1977# streams for rule rewriting 1978# 1979############################################################################# 1980 1981class RewriteRuleElementStream(object): 1982 """@brief Internal helper class. 1983 1984 A generic list of elements tracked in an alternative to be used in 1985 a -> rewrite rule. We need to subclass to fill in the next() method, 1986 which returns either an AST node wrapped around a token payload or 1987 an existing subtree. 1988 1989 Once you start next()ing, do not try to add more elements. It will 1990 break the cursor tracking I believe. 1991 1992 @see org.antlr.runtime.tree.RewriteRuleSubtreeStream 1993 @see org.antlr.runtime.tree.RewriteRuleTokenStream 1994 1995 TODO: add mechanism to detect/puke on modification after reading from 1996 stream 1997 """ 1998 1999 def __init__(self, adaptor, elementDescription, elements=None): 2000 # Cursor 0..n-1. If singleElement!=null, cursor is 0 until you next(), 2001 # which bumps it to 1 meaning no more elements. 2002 self.cursor = 0 2003 2004 # Track single elements w/o creating a list. Upon 2nd add, alloc list 2005 self.singleElement = None 2006 2007 # The list of tokens or subtrees we are tracking 2008 self.elements = None 2009 2010 # Once a node / subtree has been used in a stream, it must be dup'd 2011 # from then on. Streams are reset after subrules so that the streams 2012 # can be reused in future subrules. So, reset must set a dirty bit. 2013 # If dirty, then next() always returns a dup. 2014 self.dirty = False 2015 2016 # The element or stream description; usually has name of the token or 2017 # rule reference that this list tracks. Can include rulename too, but 2018 # the exception would track that info. 2019 self.elementDescription = elementDescription 2020 2021 self.adaptor = adaptor 2022 2023 if isinstance(elements, (list, tuple)): 2024 # Create a stream, but feed off an existing list 2025 self.singleElement = None 2026 self.elements = elements 2027 2028 else: 2029 # Create a stream with one element 2030 self.add(elements) 2031 2032 def reset(self): 2033 """ 2034 Reset the condition of this stream so that it appears we have 2035 not consumed any of its elements. Elements themselves are untouched. 2036 Once we reset the stream, any future use will need duplicates. Set 2037 the dirty bit. 2038 """ 2039 2040 self.cursor = 0 2041 self.dirty = True 2042 2043 def add(self, el): 2044 if el is None: 2045 return 2046 2047 if self.elements is not None: # if in list, just add 2048 self.elements.append(el) 2049 return 2050 2051 if self.singleElement is None: # no elements yet, track w/o list 2052 self.singleElement = el 2053 return 2054 2055 # adding 2nd element, move to list 2056 self.elements = [] 2057 self.elements.append(self.singleElement) 2058 self.singleElement = None 2059 self.elements.append(el) 2060 2061 def nextTree(self): 2062 """ 2063 Return the next element in the stream. If out of elements, throw 2064 an exception unless size()==1. If size is 1, then return elements[0]. 2065 2066 Return a duplicate node/subtree if stream is out of elements and 2067 size==1. If we've already used the element, dup (dirty bit set). 2068 """ 2069 2070 if (self.dirty or (self.cursor >= len(self) and len(self) == 1)): 2071 # if out of elements and size is 1, dup 2072 el = self._next() 2073 return self.dup(el) 2074 2075 # test size above then fetch 2076 el = self._next() 2077 return el 2078 2079 def _next(self): 2080 """ 2081 do the work of getting the next element, making sure that it's 2082 a tree node or subtree. Deal with the optimization of single- 2083 element list versus list of size > 1. Throw an exception 2084 if the stream is empty or we're out of elements and size>1. 2085 protected so you can override in a subclass if necessary. 2086 """ 2087 2088 if len(self) == 0: 2089 raise RewriteEmptyStreamException(self.elementDescription) 2090 2091 if self.cursor >= len(self): # out of elements? 2092 if len(self) == 1: # if size is 1, it's ok; return and we'll dup 2093 return self.toTree(self.singleElement) 2094 2095 # out of elements and size was not 1, so we can't dup 2096 raise RewriteCardinalityException(self.elementDescription) 2097 2098 # we have elements 2099 if self.singleElement is not None: 2100 self.cursor += 1 # move cursor even for single element list 2101 return self.toTree(self.singleElement) 2102 2103 # must have more than one in list, pull from elements 2104 o = self.toTree(self.elements[self.cursor]) 2105 self.cursor += 1 2106 return o 2107 2108 def dup(self, el): 2109 """ 2110 When constructing trees, sometimes we need to dup a token or AST 2111 subtree. Dup'ing a token means just creating another AST node 2112 around it. For trees, you must call the adaptor.dupTree() unless 2113 the element is for a tree root; then it must be a node dup. 2114 """ 2115 2116 raise NotImplementedError 2117 2118 def toTree(self, el): 2119 """ 2120 Ensure stream emits trees; tokens must be converted to AST nodes. 2121 AST nodes can be passed through unmolested. 2122 """ 2123 2124 return el 2125 2126 def hasNext(self): 2127 return ((self.singleElement is not None and self.cursor < 1) or 2128 (self.elements is not None and self.cursor < len(self.elements))) 2129 2130 def size(self): 2131 if self.singleElement is not None: 2132 return 1 2133 2134 if self.elements is not None: 2135 return len(self.elements) 2136 2137 return 0 2138 2139 __len__ = size 2140 2141 def getDescription(self): 2142 """Deprecated. Directly access elementDescription attribute""" 2143 2144 return self.elementDescription 2145 2146 2147class RewriteRuleTokenStream(RewriteRuleElementStream): 2148 """@brief Internal helper class.""" 2149 2150 def toTree(self, el): 2151 # Don't convert to a tree unless they explicitly call nextTree. 2152 # This way we can do hetero tree nodes in rewrite. 2153 return el 2154 2155 def nextNode(self): 2156 t = self._next() 2157 return self.adaptor.createWithPayload(t) 2158 2159 def nextToken(self): 2160 return self._next() 2161 2162 def dup(self, el): 2163 raise TypeError("dup can't be called for a token stream.") 2164 2165 2166class RewriteRuleSubtreeStream(RewriteRuleElementStream): 2167 """@brief Internal helper class.""" 2168 2169 def nextNode(self): 2170 """ 2171 Treat next element as a single node even if it's a subtree. 2172 This is used instead of next() when the result has to be a 2173 tree root node. Also prevents us from duplicating recently-added 2174 children; e.g., ^(type ID)+ adds ID to type and then 2nd iteration 2175 must dup the type node, but ID has been added. 2176 2177 Referencing a rule result twice is ok; dup entire tree as 2178 we can't be adding trees as root; e.g., expr expr. 2179 2180 Hideous code duplication here with super.next(). Can't think of 2181 a proper way to refactor. This needs to always call dup node 2182 and super.next() doesn't know which to call: dup node or dup tree. 2183 """ 2184 2185 if (self.dirty or (self.cursor >= len(self) and len(self) == 1)): 2186 # if out of elements and size is 1, dup (at most a single node 2187 # since this is for making root nodes). 2188 el = self._next() 2189 return self.adaptor.dupNode(el) 2190 2191 # test size above then fetch 2192 el = self._next() 2193 return el 2194 2195 def dup(self, el): 2196 return self.adaptor.dupTree(el) 2197 2198 2199 2200class RewriteRuleNodeStream(RewriteRuleElementStream): 2201 """ 2202 Queues up nodes matched on left side of -> in a tree parser. This is 2203 the analog of RewriteRuleTokenStream for normal parsers. 2204 """ 2205 2206 def nextNode(self): 2207 return self._next() 2208 2209 def toTree(self, el): 2210 return self.adaptor.dupNode(el) 2211 2212 def dup(self, el): 2213 # we dup every node, so don't have to worry about calling dup; short- 2214 #circuited next() so it doesn't call. 2215 raise TypeError("dup can't be called for a node stream.") 2216 2217 2218class TreeRuleReturnScope(RuleReturnScope): 2219 """ 2220 This is identical to the ParserRuleReturnScope except that 2221 the start property is a tree nodes not Token object 2222 when you are parsing trees. To be generic the tree node types 2223 have to be Object. 2224 """ 2225 2226 def __init__(self): 2227 self.start = None 2228 self.tree = None 2229 2230 def getStart(self): 2231 return self.start 2232 2233 def getTree(self): 2234 return self.tree 2235