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