00001 """ @package antlr3.tree
00002 @brief ANTLR3 runtime package, tree module
00003
00004 This module contains all support classes for AST construction and tree parsers.
00005
00006 """
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041 import re
00042
00043 from constants import UP, DOWN, EOF, INVALID_TOKEN_TYPE
00044 from recognizers import BaseRecognizer, RuleReturnScope
00045 from streams import IntStream
00046 from tokens import CommonToken, Token, INVALID_TOKEN
00047 from exceptions import MismatchedTreeNodeException, \
00048 MissingTokenException, UnwantedTokenException, MismatchedTokenException, \
00049 NoViableAltException
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059 class RewriteCardinalityException(RuntimeError):
00060 """
00061 @brief Base class for all exceptions thrown during AST rewrite construction.
00062
00063 This signifies a case where the cardinality of two or more elements
00064 in a subrule are different: (ID INT)+ where |ID|!=|INT|
00065 """
00066
00067 def __init__(self, elementDescription):
00068 RuntimeError.__init__(self, elementDescription)
00069
00070 self.elementDescription = elementDescription
00071
00072
00073 def getMessage(self):
00074 return self.elementDescription
00075
00076
00077 class RewriteEarlyExitException(RewriteCardinalityException):
00078 """@brief No elements within a (...)+ in a rewrite rule"""
00079
00080 def __init__(self, elementDescription=None):
00081 RewriteCardinalityException.__init__(self, elementDescription)
00082
00083
00084 class RewriteEmptyStreamException(RewriteCardinalityException):
00085 """
00086 @brief Ref to ID or expr but no tokens in ID stream or subtrees in expr stream
00087 """
00088
00089 pass
00090
00091
00092
00093
00094
00095
00096
00097
00098 class Tree(object):
00099 """
00100 @brief Abstract baseclass for tree nodes.
00101
00102 What does a tree look like? ANTLR has a number of support classes
00103 such as CommonTreeNodeStream that work on these kinds of trees. You
00104 don't have to make your trees implement this interface, but if you do,
00105 you'll be able to use more support code.
00106
00107 NOTE: When constructing trees, ANTLR can build any kind of tree; it can
00108 even use Token objects as trees if you add a child list to your tokens.
00109
00110 This is a tree node without any payload; just navigation and factory stuff.
00111 """
00112
00113
00114 def getChild(self, i):
00115 raise NotImplementedError
00116
00117
00118 def getChildCount(self):
00119 raise NotImplementedError
00120
00121
00122 def getParent(self):
00123 """Tree tracks parent and child index now > 3.0"""
00124
00125 raise NotImplementedError
00126
00127 def setParent(self, t):
00128 """Tree tracks parent and child index now > 3.0"""
00129
00130 raise NotImplementedError
00131
00132
00133 def hasAncestor(self, ttype):
00134 """Walk upwards looking for ancestor with this token type."""
00135
00136 raise NotImplementedError
00137
00138 def getAncestor(self, ttype):
00139 """Walk upwards and get first ancestor with this token type."""
00140
00141 raise NotImplementedError
00142
00143 def getAncestors(self):
00144 """Return a list of all ancestors of this node.
00145
00146 The first node of list is the root and the last is the parent of
00147 this node.
00148 """
00149
00150 raise NotImplementedError
00151
00152
00153 def getChildIndex(self):
00154 """This node is what child index? 0..n-1"""
00155
00156 raise NotImplementedError
00157
00158 def setChildIndex(self, index):
00159 """This node is what child index? 0..n-1"""
00160
00161 raise NotImplementedError
00162
00163
00164 def freshenParentAndChildIndexes(self):
00165 """Set the parent and child index values for all children"""
00166
00167 raise NotImplementedError
00168
00169
00170 def addChild(self, t):
00171 """
00172 Add t as a child to this node. If t is null, do nothing. If t
00173 is nil, add all children of t to this' children.
00174 """
00175
00176 raise NotImplementedError
00177
00178
00179 def setChild(self, i, t):
00180 """Set ith child (0..n-1) to t; t must be non-null and non-nil node"""
00181
00182 raise NotImplementedError
00183
00184
00185 def deleteChild(self, i):
00186 raise NotImplementedError
00187
00188
00189 def replaceChildren(self, startChildIndex, stopChildIndex, t):
00190 """
00191 Delete children from start to stop and replace with t even if t is
00192 a list (nil-root tree). num of children can increase or decrease.
00193 For huge child lists, inserting children can force walking rest of
00194 children to set their childindex; could be slow.
00195 """
00196
00197 raise NotImplementedError
00198
00199
00200 def isNil(self):
00201 """
00202 Indicates the node is a nil node but may still have children, meaning
00203 the tree is a flat list.
00204 """
00205
00206 raise NotImplementedError
00207
00208
00209 def getTokenStartIndex(self):
00210 """
00211 What is the smallest token index (indexing from 0) for this node
00212 and its children?
00213 """
00214
00215 raise NotImplementedError
00216
00217
00218 def setTokenStartIndex(self, index):
00219 raise NotImplementedError
00220
00221
00222 def getTokenStopIndex(self):
00223 """
00224 What is the largest token index (indexing from 0) for this node
00225 and its children?
00226 """
00227
00228 raise NotImplementedError
00229
00230
00231 def setTokenStopIndex(self, index):
00232 raise NotImplementedError
00233
00234
00235 def dupNode(self):
00236 raise NotImplementedError
00237
00238
00239 def getType(self):
00240 """Return a token type; needed for tree parsing."""
00241
00242 raise NotImplementedError
00243
00244
00245 def getText(self):
00246 raise NotImplementedError
00247
00248
00249 def getLine(self):
00250 """
00251 In case we don't have a token payload, what is the line for errors?
00252 """
00253
00254 raise NotImplementedError
00255
00256
00257 def getCharPositionInLine(self):
00258 raise NotImplementedError
00259
00260
00261 def toStringTree(self):
00262 raise NotImplementedError
00263
00264
00265 def toString(self):
00266 raise NotImplementedError
00267
00268
00269
00270 class TreeAdaptor(object):
00271 """
00272 @brief Abstract baseclass for tree adaptors.
00273
00274 How to create and navigate trees. Rather than have a separate factory
00275 and adaptor, I've merged them. Makes sense to encapsulate.
00276
00277 This takes the place of the tree construction code generated in the
00278 generated code in 2.x and the ASTFactory.
00279
00280 I do not need to know the type of a tree at all so they are all
00281 generic Objects. This may increase the amount of typecasting needed. :(
00282 """
00283
00284
00285
00286 def createWithPayload(self, payload):
00287 """
00288 Create a tree node from Token object; for CommonTree type trees,
00289 then the token just becomes the payload. This is the most
00290 common create call.
00291
00292 Override if you want another kind of node to be built.
00293 """
00294
00295 raise NotImplementedError
00296
00297
00298 def dupNode(self, treeNode):
00299 """Duplicate a single tree node.
00300
00301 Override if you want another kind of node to be built."""
00302
00303 raise NotImplementedError
00304
00305
00306 def dupTree(self, tree):
00307 """Duplicate tree recursively, using dupNode() for each node"""
00308
00309 raise NotImplementedError
00310
00311
00312 def nil(self):
00313 """
00314 Return a nil node (an empty but non-null node) that can hold
00315 a list of element as the children. If you want a flat tree (a list)
00316 use "t=adaptor.nil(); t.addChild(x); t.addChild(y);"
00317 """
00318
00319 raise NotImplementedError
00320
00321
00322 def errorNode(self, input, start, stop, exc):
00323 """
00324 Return a tree node representing an error. This node records the
00325 tokens consumed during error recovery. The start token indicates the
00326 input symbol at which the error was detected. The stop token indicates
00327 the last symbol consumed during recovery.
00328
00329 You must specify the input stream so that the erroneous text can
00330 be packaged up in the error node. The exception could be useful
00331 to some applications; default implementation stores ptr to it in
00332 the CommonErrorNode.
00333
00334 This only makes sense during token parsing, not tree parsing.
00335 Tree parsing should happen only when parsing and tree construction
00336 succeed.
00337 """
00338
00339 raise NotImplementedError
00340
00341
00342 def isNil(self, tree):
00343 """Is tree considered a nil node used to make lists of child nodes?"""
00344
00345 raise NotImplementedError
00346
00347
00348 def addChild(self, t, child):
00349 """
00350 Add a child to the tree t. If child is a flat tree (a list), make all
00351 in list children of t. Warning: if t has no children, but child does
00352 and child isNil then you can decide it is ok to move children to t via
00353 t.children = child.children; i.e., without copying the array. Just
00354 make sure that this is consistent with have the user will build
00355 ASTs. Do nothing if t or child is null.
00356 """
00357
00358 raise NotImplementedError
00359
00360
00361 def becomeRoot(self, newRoot, oldRoot):
00362 """
00363 If oldRoot is a nil root, just copy or move the children to newRoot.
00364 If not a nil root, make oldRoot a child of newRoot.
00365
00366 old=^(nil a b c), new=r yields ^(r a b c)
00367 old=^(a b c), new=r yields ^(r ^(a b c))
00368
00369 If newRoot is a nil-rooted single child tree, use the single
00370 child as the new root node.
00371
00372 old=^(nil a b c), new=^(nil r) yields ^(r a b c)
00373 old=^(a b c), new=^(nil r) yields ^(r ^(a b c))
00374
00375 If oldRoot was null, it's ok, just return newRoot (even if isNil).
00376
00377 old=null, new=r yields r
00378 old=null, new=^(nil r) yields ^(nil r)
00379
00380 Return newRoot. Throw an exception if newRoot is not a
00381 simple node or nil root with a single child node--it must be a root
00382 node. If newRoot is ^(nil x) return x as newRoot.
00383
00384 Be advised that it's ok for newRoot to point at oldRoot's
00385 children; i.e., you don't have to copy the list. We are
00386 constructing these nodes so we should have this control for
00387 efficiency.
00388 """
00389
00390 raise NotImplementedError
00391
00392
00393 def rulePostProcessing(self, root):
00394 """
00395 Given the root of the subtree created for this rule, post process
00396 it to do any simplifications or whatever you want. A required
00397 behavior is to convert ^(nil singleSubtree) to singleSubtree
00398 as the setting of start/stop indexes relies on a single non-nil root
00399 for non-flat trees.
00400
00401 Flat trees such as for lists like "idlist : ID+ ;" are left alone
00402 unless there is only one ID. For a list, the start/stop indexes
00403 are set in the nil node.
00404
00405 This method is executed after all rule tree construction and right
00406 before setTokenBoundaries().
00407 """
00408
00409 raise NotImplementedError
00410
00411
00412 def getUniqueID(self, node):
00413 """For identifying trees.
00414
00415 How to identify nodes so we can say "add node to a prior node"?
00416 Even becomeRoot is an issue. Use System.identityHashCode(node)
00417 usually.
00418 """
00419
00420 raise NotImplementedError
00421
00422
00423
00424
00425 def createFromToken(self, tokenType, fromToken, text=None):
00426 """
00427 Create a new node derived from a token, with a new token type and
00428 (optionally) new text.
00429
00430 This is invoked from an imaginary node ref on right side of a
00431 rewrite rule as IMAG[$tokenLabel] or IMAG[$tokenLabel "IMAG"].
00432
00433 This should invoke createToken(Token).
00434 """
00435
00436 raise NotImplementedError
00437
00438
00439 def createFromType(self, tokenType, text):
00440 """Create a new node derived from a token, with a new token type.
00441
00442 This is invoked from an imaginary node ref on right side of a
00443 rewrite rule as IMAG["IMAG"].
00444
00445 This should invoke createToken(int,String).
00446 """
00447
00448 raise NotImplementedError
00449
00450
00451
00452
00453 def getType(self, t):
00454 """For tree parsing, I need to know the token type of a node"""
00455
00456 raise NotImplementedError
00457
00458
00459 def setType(self, t, type):
00460 """Node constructors can set the type of a node"""
00461
00462 raise NotImplementedError
00463
00464
00465 def getText(self, t):
00466 raise NotImplementedError
00467
00468 def setText(self, t, text):
00469 """Node constructors can set the text of a node"""
00470
00471 raise NotImplementedError
00472
00473
00474 def getToken(self, t):
00475 """Return the token object from which this node was created.
00476
00477 Currently used only for printing an error message.
00478 The error display routine in BaseRecognizer needs to
00479 display where the input the error occurred. If your
00480 tree of limitation does not store information that can
00481 lead you to the token, you can create a token filled with
00482 the appropriate information and pass that back. See
00483 BaseRecognizer.getErrorMessage().
00484 """
00485
00486 raise NotImplementedError
00487
00488
00489 def setTokenBoundaries(self, t, startToken, stopToken):
00490 """
00491 Where are the bounds in the input token stream for this node and
00492 all children? Each rule that creates AST nodes will call this
00493 method right before returning. Flat trees (i.e., lists) will
00494 still usually have a nil root node just to hold the children list.
00495 That node would contain the start/stop indexes then.
00496 """
00497
00498 raise NotImplementedError
00499
00500
00501 def getTokenStartIndex(self, t):
00502 """
00503 Get the token start index for this subtree; return -1 if no such index
00504 """
00505
00506 raise NotImplementedError
00507
00508
00509 def getTokenStopIndex(self, t):
00510 """
00511 Get the token stop index for this subtree; return -1 if no such index
00512 """
00513
00514 raise NotImplementedError
00515
00516
00517
00518
00519 def getChild(self, t, i):
00520 """Get a child 0..n-1 node"""
00521
00522 raise NotImplementedError
00523
00524
00525 def setChild(self, t, i, child):
00526 """Set ith child (0..n-1) to t; t must be non-null and non-nil node"""
00527
00528 raise NotImplementedError
00529
00530
00531 def deleteChild(self, t, i):
00532 """Remove ith child and shift children down from right."""
00533
00534 raise NotImplementedError
00535
00536
00537 def getChildCount(self, t):
00538 """How many children? If 0, then this is a leaf node"""
00539
00540 raise NotImplementedError
00541
00542
00543 def getParent(self, t):
00544 """
00545 Who is the parent node of this node; if null, implies node is root.
00546 If your node type doesn't handle this, it's ok but the tree rewrites
00547 in tree parsers need this functionality.
00548 """
00549
00550 raise NotImplementedError
00551
00552
00553 def setParent(self, t, parent):
00554 """
00555 Who is the parent node of this node; if null, implies node is root.
00556 If your node type doesn't handle this, it's ok but the tree rewrites
00557 in tree parsers need this functionality.
00558 """
00559
00560 raise NotImplementedError
00561
00562
00563 def getChildIndex(self, t):
00564 """
00565 What index is this node in the child list? Range: 0..n-1
00566 If your node type doesn't handle this, it's ok but the tree rewrites
00567 in tree parsers need this functionality.
00568 """
00569
00570 raise NotImplementedError
00571
00572
00573 def setChildIndex(self, t, index):
00574 """
00575 What index is this node in the child list? Range: 0..n-1
00576 If your node type doesn't handle this, it's ok but the tree rewrites
00577 in tree parsers need this functionality.
00578 """
00579
00580 raise NotImplementedError
00581
00582
00583 def replaceChildren(self, parent, startChildIndex, stopChildIndex, t):
00584 """
00585 Replace from start to stop child index of parent with t, which might
00586 be a list. Number of children may be different
00587 after this call.
00588
00589 If parent is null, don't do anything; must be at root of overall tree.
00590 Can't replace whatever points to the parent externally. Do nothing.
00591 """
00592
00593 raise NotImplementedError
00594
00595
00596
00597
00598 def create(self, *args):
00599 """
00600 Deprecated, use createWithPayload, createFromToken or createFromType.
00601
00602 This method only exists to mimic the Java interface of TreeAdaptor.
00603
00604 """
00605
00606 if len(args) == 1 and isinstance(args[0], Token):
00607
00608
00609
00610
00611
00612
00613 return self.createWithPayload(args[0])
00614
00615 if (len(args) == 2
00616 and isinstance(args[0], (int, long))
00617 and isinstance(args[1], Token)
00618 ):
00619
00620
00621
00622
00623
00624
00625 return self.createFromToken(args[0], args[1])
00626
00627 if (len(args) == 3
00628 and isinstance(args[0], (int, long))
00629 and isinstance(args[1], Token)
00630 and isinstance(args[2], basestring)
00631 ):
00632
00633
00634
00635
00636
00637
00638 return self.createFromToken(args[0], args[1], args[2])
00639
00640 if (len(args) == 2
00641 and isinstance(args[0], (int, long))
00642 and isinstance(args[1], basestring)
00643 ):
00644
00645
00646
00647
00648
00649
00650 return self.createFromType(args[0], args[1])
00651
00652 raise TypeError(
00653 "No create method with this signature found: %s"
00654 % (', '.join(type(v).__name__ for v in args))
00655 )
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671 class BaseTree(Tree):
00672 """
00673 @brief A generic tree implementation with no payload.
00674
00675 You must subclass to
00676 actually have any user data. ANTLR v3 uses a list of children approach
00677 instead of the child-sibling approach in v2. A flat tree (a list) is
00678 an empty node whose children represent the list. An empty, but
00679 non-null node is called "nil".
00680 """
00681
00682
00683
00684
00685
00686 def __init__(self, node=None):
00687 """
00688 Create a new node from an existing node does nothing for BaseTree
00689 as there are no fields other than the children list, which cannot
00690 be copied as the children are not considered part of this node.
00691 """
00692
00693 Tree.__init__(self)
00694 self.children = []
00695 self.parent = None
00696 self.childIndex = 0
00697
00698
00699 def getChild(self, i):
00700 try:
00701 return self.children[i]
00702 except IndexError:
00703 return None
00704
00705
00706 def getChildren(self):
00707 """@brief Get the children internal List
00708
00709 Note that if you directly mess with
00710 the list, do so at your own risk.
00711 """
00712
00713
00714 return self.children
00715
00716
00717 def getFirstChildWithType(self, treeType):
00718 for child in self.children:
00719 if child.getType() == treeType:
00720 return child
00721
00722 return None
00723
00724
00725 def getChildCount(self):
00726 return len(self.children)
00727
00728
00729 def addChild(self, childTree):
00730 """Add t as child of this node.
00731
00732 Warning: if t has no children, but child does
00733 and child isNil then this routine moves children to t via
00734 t.children = child.children; i.e., without copying the array.
00735 """
00736
00737
00738
00739
00740 if childTree is None:
00741 return
00742
00743 if childTree.isNil():
00744
00745
00746 if self.children is childTree.children:
00747 raise ValueError("attempt to add child list to itself")
00748
00749
00750 for idx, child in enumerate(childTree.children):
00751 child.parent = self
00752 child.childIndex = len(self.children) + idx
00753
00754 self.children += childTree.children
00755
00756 else:
00757
00758 self.children.append(childTree)
00759 childTree.parent = self
00760 childTree.childIndex = len(self.children) - 1
00761
00762
00763 def addChildren(self, children):
00764 """Add all elements of kids list as children of this node"""
00765
00766 self.children += children
00767
00768
00769 def setChild(self, i, t):
00770 if t is None:
00771 return
00772
00773 if t.isNil():
00774 raise ValueError("Can't set single child to a list")
00775
00776 self.children[i] = t
00777 t.parent = self
00778 t.childIndex = i
00779
00780
00781 def deleteChild(self, i):
00782 killed = self.children[i]
00783
00784 del self.children[i]
00785
00786
00787 for idx, child in enumerate(self.children[i:]):
00788 child.childIndex = i + idx
00789
00790 return killed
00791
00792
00793 def replaceChildren(self, startChildIndex, stopChildIndex, newTree):
00794 """
00795 Delete children from start to stop and replace with t even if t is
00796 a list (nil-root tree). num of children can increase or decrease.
00797 For huge child lists, inserting children can force walking rest of
00798 children to set their childindex; could be slow.
00799 """
00800
00801 if (startChildIndex >= len(self.children)
00802 or stopChildIndex >= len(self.children)
00803 ):
00804 raise IndexError("indexes invalid")
00805
00806 replacingHowMany = stopChildIndex - startChildIndex + 1
00807
00808
00809 if newTree.isNil():
00810 newChildren = newTree.children
00811
00812 else:
00813 newChildren = [newTree]
00814
00815 replacingWithHowMany = len(newChildren)
00816 delta = replacingHowMany - replacingWithHowMany
00817
00818
00819 if delta == 0:
00820
00821 for idx, child in enumerate(newChildren):
00822 self.children[idx + startChildIndex] = child
00823 child.parent = self
00824 child.childIndex = idx + startChildIndex
00825
00826 else:
00827
00828
00829
00830 del self.children[startChildIndex:stopChildIndex+1]
00831
00832
00833 self.children[startChildIndex:startChildIndex] = newChildren
00834
00835
00836 self.freshenParentAndChildIndexes(startChildIndex)
00837
00838
00839 def isNil(self):
00840 return False
00841
00842
00843 def freshenParentAndChildIndexes(self, offset=0):
00844 for idx, child in enumerate(self.children[offset:]):
00845 child.childIndex = idx + offset
00846 child.parent = self
00847
00848
00849 def sanityCheckParentAndChildIndexes(self, parent=None, i=-1):
00850 if parent != self.parent:
00851 raise ValueError(
00852 "parents don't match; expected %r found %r"
00853 % (parent, self.parent)
00854 )
00855
00856 if i != self.childIndex:
00857 raise ValueError(
00858 "child indexes don't match; expected %d found %d"
00859 % (i, self.childIndex)
00860 )
00861
00862 for idx, child in enumerate(self.children):
00863 child.sanityCheckParentAndChildIndexes(self, idx)
00864
00865
00866 def getChildIndex(self):
00867 """BaseTree doesn't track child indexes."""
00868
00869 return 0
00870
00871
00872 def setChildIndex(self, index):
00873 """BaseTree doesn't track child indexes."""
00874
00875 pass
00876
00877
00878 def getParent(self):
00879 """BaseTree doesn't track parent pointers."""
00880
00881 return None
00882
00883 def setParent(self, t):
00884 """BaseTree doesn't track parent pointers."""
00885
00886 pass
00887
00888
00889 def hasAncestor(self, ttype):
00890 """Walk upwards looking for ancestor with this token type."""
00891 return self.getAncestor(ttype) is not None
00892
00893 def getAncestor(self, ttype):
00894 """Walk upwards and get first ancestor with this token type."""
00895 t = self.getParent()
00896 while t is not None:
00897 if t.getType() == ttype:
00898 return t
00899 t = t.getParent()
00900
00901 return None
00902
00903 def getAncestors(self):
00904 """Return a list of all ancestors of this node.
00905
00906 The first node of list is the root and the last is the parent of
00907 this node.
00908 """
00909 if selfgetParent() is None:
00910 return None
00911
00912 ancestors = []
00913 t = self.getParent()
00914 while t is not None:
00915 ancestors.insert(0, t)
00916 t = t.getParent()
00917
00918 return ancestors
00919
00920
00921 def toStringTree(self):
00922 """Print out a whole tree not just a node"""
00923
00924 if len(self.children) == 0:
00925 return self.toString()
00926
00927 buf = []
00928 if not self.isNil():
00929 buf.append('(')
00930 buf.append(self.toString())
00931 buf.append(' ')
00932
00933 for i, child in enumerate(self.children):
00934 if i > 0:
00935 buf.append(' ')
00936 buf.append(child.toStringTree())
00937
00938 if not self.isNil():
00939 buf.append(')')
00940
00941 return ''.join(buf)
00942
00943
00944 def getLine(self):
00945 return 0
00946
00947
00948 def getCharPositionInLine(self):
00949 return 0
00950
00951
00952 def toString(self):
00953 """Override to say how a node (not a tree) should look as text"""
00954
00955 raise NotImplementedError
00956
00957
00958
00959 class BaseTreeAdaptor(TreeAdaptor):
00960 """
00961 @brief A TreeAdaptor that works with any Tree implementation.
00962 """
00963
00964
00965
00966
00967
00968 def nil(self):
00969 return self.createWithPayload(None)
00970
00971
00972 def errorNode(self, input, start, stop, exc):
00973 """
00974 create tree node that holds the start and stop tokens associated
00975 with an error.
00976
00977 If you specify your own kind of tree nodes, you will likely have to
00978 override this method. CommonTree returns Token.INVALID_TOKEN_TYPE
00979 if no token payload but you might have to set token type for diff
00980 node type.
00981
00982 You don't have to subclass CommonErrorNode; you will likely need to
00983 subclass your own tree node class to avoid class cast exception.
00984 """
00985
00986 return CommonErrorNode(input, start, stop, exc)
00987
00988
00989 def isNil(self, tree):
00990 return tree.isNil()
00991
00992
00993 def dupTree(self, t, parent=None):
00994 """
00995 This is generic in the sense that it will work with any kind of
00996 tree (not just Tree interface). It invokes the adaptor routines
00997 not the tree node routines to do the construction.
00998 """
00999
01000 if t is None:
01001 return None
01002
01003 newTree = self.dupNode(t)
01004
01005
01006
01007
01008 self.setChildIndex(newTree, self.getChildIndex(t))
01009
01010 self.setParent(newTree, parent)
01011
01012 for i in range(self.getChildCount(t)):
01013 child = self.getChild(t, i)
01014 newSubTree = self.dupTree(child, t)
01015 self.addChild(newTree, newSubTree)
01016
01017 return newTree
01018
01019
01020 def addChild(self, tree, child):
01021 """
01022 Add a child to the tree t. If child is a flat tree (a list), make all
01023 in list children of t. Warning: if t has no children, but child does
01024 and child isNil then you can decide it is ok to move children to t via
01025 t.children = child.children; i.e., without copying the array. Just
01026 make sure that this is consistent with have the user will build
01027 ASTs.
01028 """
01029
01030
01031
01032
01033 if tree is not None and child is not None:
01034 tree.addChild(child)
01035
01036
01037 def becomeRoot(self, newRoot, oldRoot):
01038 """
01039 If oldRoot is a nil root, just copy or move the children to newRoot.
01040 If not a nil root, make oldRoot a child of newRoot.
01041
01042 old=^(nil a b c), new=r yields ^(r a b c)
01043 old=^(a b c), new=r yields ^(r ^(a b c))
01044
01045 If newRoot is a nil-rooted single child tree, use the single
01046 child as the new root node.
01047
01048 old=^(nil a b c), new=^(nil r) yields ^(r a b c)
01049 old=^(a b c), new=^(nil r) yields ^(r ^(a b c))
01050
01051 If oldRoot was null, it's ok, just return newRoot (even if isNil).
01052
01053 old=null, new=r yields r
01054 old=null, new=^(nil r) yields ^(nil r)
01055
01056 Return newRoot. Throw an exception if newRoot is not a
01057 simple node or nil root with a single child node--it must be a root
01058 node. If newRoot is ^(nil x) return x as newRoot.
01059
01060 Be advised that it's ok for newRoot to point at oldRoot's
01061 children; i.e., you don't have to copy the list. We are
01062 constructing these nodes so we should have this control for
01063 efficiency.
01064 """
01065
01066 if isinstance(newRoot, Token):
01067 newRoot = self.create(newRoot)
01068
01069 if oldRoot is None:
01070 return newRoot
01071
01072 if not isinstance(newRoot, CommonTree):
01073 newRoot = self.createWithPayload(newRoot)
01074
01075
01076 if newRoot.isNil():
01077 nc = newRoot.getChildCount()
01078 if nc == 1:
01079 newRoot = newRoot.getChild(0)
01080
01081 elif nc > 1:
01082
01083 raise RuntimeError("more than one node as root")
01084
01085
01086
01087
01088 newRoot.addChild(oldRoot)
01089 return newRoot
01090
01091
01092 def rulePostProcessing(self, root):
01093 """Transform ^(nil x) to x and nil to null"""
01094
01095 if root is not None and root.isNil():
01096 if root.getChildCount() == 0:
01097 root = None
01098
01099 elif root.getChildCount() == 1:
01100 root = root.getChild(0)
01101
01102 root.setParent(None)
01103 root.setChildIndex(-1)
01104
01105 return root
01106
01107
01108 def createFromToken(self, tokenType, fromToken, text=None):
01109 assert isinstance(tokenType, (int, long)), type(tokenType).__name__
01110 assert isinstance(fromToken, Token), type(fromToken).__name__
01111 assert text is None or isinstance(text, basestring), type(text).__name__
01112
01113 fromToken = self.createToken(fromToken)
01114 fromToken.type = tokenType
01115 if text is not None:
01116 fromToken.text = text
01117 t = self.createWithPayload(fromToken)
01118 return t
01119
01120
01121 def createFromType(self, tokenType, text):
01122 assert isinstance(tokenType, (int, long)), type(tokenType).__name__
01123 assert isinstance(text, basestring), type(text).__name__
01124
01125 fromToken = self.createToken(tokenType=tokenType, text=text)
01126 t = self.createWithPayload(fromToken)
01127 return t
01128
01129
01130 def getType(self, t):
01131 return t.getType()
01132
01133
01134 def setType(self, t, type):
01135 raise RuntimeError("don't know enough about Tree node")
01136
01137
01138 def getText(self, t):
01139 return t.getText()
01140
01141
01142 def setText(self, t, text):
01143 raise RuntimeError("don't know enough about Tree node")
01144
01145
01146 def getChild(self, t, i):
01147 return t.getChild(i)
01148
01149
01150 def setChild(self, t, i, child):
01151 t.setChild(i, child)
01152
01153
01154 def deleteChild(self, t, i):
01155 return t.deleteChild(i)
01156
01157
01158 def getChildCount(self, t):
01159 return t.getChildCount()
01160
01161
01162 def getUniqueID(self, node):
01163 return hash(node)
01164
01165
01166 def createToken(self, fromToken=None, tokenType=None, text=None):
01167 """
01168 Tell me how to create a token for use with imaginary token nodes.
01169 For example, there is probably no input symbol associated with imaginary
01170 token DECL, but you need to create it as a payload or whatever for
01171 the DECL node as in ^(DECL type ID).
01172
01173 If you care what the token payload objects' type is, you should
01174 override this method and any other createToken variant.
01175 """
01176
01177 raise NotImplementedError
01178
01179
01180
01181
01182
01183
01184
01185
01186
01187
01188
01189
01190
01191
01192
01193
01194
01195
01196 class CommonTree(BaseTree):
01197 """@brief A tree node that is wrapper for a Token object.
01198
01199 After 3.0 release
01200 while building tree rewrite stuff, it became clear that computing
01201 parent and child index is very difficult and cumbersome. Better to
01202 spend the space in every tree node. If you don't want these extra
01203 fields, it's easy to cut them out in your own BaseTree subclass.
01204
01205 """
01206
01207 def __init__(self, payload):
01208 BaseTree.__init__(self)
01209
01210
01211
01212 self.startIndex = -1
01213 self.stopIndex = -1
01214
01215
01216 self.parent = None
01217
01218
01219 self.childIndex = -1
01220
01221
01222 if payload is None:
01223 self.token = None
01224
01225 elif isinstance(payload, CommonTree):
01226 self.token = payload.token
01227 self.startIndex = payload.startIndex
01228 self.stopIndex = payload.stopIndex
01229
01230 elif payload is None or isinstance(payload, Token):
01231 self.token = payload
01232
01233 else:
01234 raise TypeError(type(payload).__name__)
01235
01236
01237
01238 def getToken(self):
01239 return self.token
01240
01241
01242 def dupNode(self):
01243 return CommonTree(self)
01244
01245
01246 def isNil(self):
01247 return self.token is None
01248
01249
01250 def getType(self):
01251 if self.token is None:
01252 return INVALID_TOKEN_TYPE
01253
01254 return self.token.getType()
01255
01256 type = property(getType)
01257
01258
01259 def getText(self):
01260 if self.token is None:
01261 return None
01262
01263 return self.token.text
01264
01265 text = property(getText)
01266
01267
01268 def getLine(self):
01269 if self.token is None or self.token.getLine() == 0:
01270 if self.getChildCount():
01271 return self.getChild(0).getLine()
01272 else:
01273 return 0
01274
01275 return self.token.getLine()
01276
01277 line = property(getLine)
01278
01279
01280 def getCharPositionInLine(self):
01281 if self.token is None or self.token.getCharPositionInLine() == -1:
01282 if self.getChildCount():
01283 return self.getChild(0).getCharPositionInLine()
01284 else:
01285 return 0
01286
01287 else:
01288 return self.token.getCharPositionInLine()
01289
01290 charPositionInLine = property(getCharPositionInLine)
01291
01292
01293 def getTokenStartIndex(self):
01294 if self.startIndex == -1 and self.token is not None:
01295 return self.token.getTokenIndex()
01296
01297 return self.startIndex
01298
01299 def setTokenStartIndex(self, index):
01300 self.startIndex = index
01301
01302 tokenStartIndex = property(getTokenStartIndex, setTokenStartIndex)
01303
01304
01305 def getTokenStopIndex(self):
01306 if self.stopIndex == -1 and self.token is not None:
01307 return self.token.getTokenIndex()
01308
01309 return self.stopIndex
01310
01311 def setTokenStopIndex(self, index):
01312 self.stopIndex = index
01313
01314 tokenStopIndex = property(getTokenStopIndex, setTokenStopIndex)
01315
01316
01317 def setUnknownTokenBoundaries(self):
01318 """For every node in this subtree, make sure it's start/stop token's
01319 are set. Walk depth first, visit bottom up. Only updates nodes
01320 with at least one token index < 0.
01321 """
01322
01323 if self.children is None:
01324 if self.startIndex < 0 or self.stopIndex < 0:
01325 self.startIndex = self.stopIndex = self.token.getTokenIndex()
01326
01327 return
01328
01329 for child in self.children:
01330 child.setUnknownTokenBoundaries()
01331
01332 if self.startIndex >= 0 and self.stopIndex >= 0:
01333
01334 return
01335
01336 if self.children:
01337 firstChild = self.children[0]
01338 lastChild = self.children[-1]
01339 self.startIndex = firstChild.getTokenStartIndex()
01340 self.stopIndex = lastChild.getTokenStopIndex()
01341
01342
01343 def getChildIndex(self):
01344
01345 return self.childIndex
01346
01347
01348 def setChildIndex(self, idx):
01349
01350 self.childIndex = idx
01351
01352
01353 def getParent(self):
01354
01355 return self.parent
01356
01357
01358 def setParent(self, t):
01359
01360 self.parent = t
01361
01362
01363 def toString(self):
01364 if self.isNil():
01365 return "nil"
01366
01367 if self.getType() == INVALID_TOKEN_TYPE:
01368 return "<errornode>"
01369
01370 return self.token.text
01371
01372 __str__ = toString
01373
01374
01375
01376 def toStringTree(self):
01377 if not self.children:
01378 return self.toString()
01379
01380 ret = ''
01381 if not self.isNil():
01382 ret += '(%s ' % (self.toString())
01383
01384 ret += ' '.join([child.toStringTree() for child in self.children])
01385
01386 if not self.isNil():
01387 ret += ')'
01388
01389 return ret
01390
01391
01392 INVALID_NODE = CommonTree(INVALID_TOKEN)
01393
01394
01395 class CommonErrorNode(CommonTree):
01396 """A node representing erroneous token range in token stream"""
01397
01398 def __init__(self, input, start, stop, exc):
01399 CommonTree.__init__(self, None)
01400
01401 if (stop is None or
01402 (stop.getTokenIndex() < start.getTokenIndex() and
01403 stop.getType() != EOF
01404 )
01405 ):
01406
01407
01408
01409
01410 stop = start
01411
01412 self.input = input
01413 self.start = start
01414 self.stop = stop
01415 self.trappedException = exc
01416
01417
01418 def isNil(self):
01419 return False
01420
01421
01422 def getType(self):
01423 return INVALID_TOKEN_TYPE
01424
01425
01426 def getText(self):
01427 if isinstance(self.start, Token):
01428 i = self.start.getTokenIndex()
01429 j = self.stop.getTokenIndex()
01430 if self.stop.getType() == EOF:
01431 j = self.input.size()
01432
01433 badText = self.input.toString(i, j)
01434
01435 elif isinstance(self.start, Tree):
01436 badText = self.input.toString(self.start, self.stop)
01437
01438 else:
01439
01440
01441 badText = "<unknown>"
01442
01443 return badText
01444
01445
01446 def toString(self):
01447 if isinstance(self.trappedException, MissingTokenException):
01448 return ("<missing type: "
01449 + str(self.trappedException.getMissingType())
01450 + ">")
01451
01452 elif isinstance(self.trappedException, UnwantedTokenException):
01453 return ("<extraneous: "
01454 + str(self.trappedException.getUnexpectedToken())
01455 + ", resync=" + self.getText() + ">")
01456
01457 elif isinstance(self.trappedException, MismatchedTokenException):
01458 return ("<mismatched token: "
01459 + str(self.trappedException.token)
01460 + ", resync=" + self.getText() + ">")
01461
01462 elif isinstance(self.trappedException, NoViableAltException):
01463 return ("<unexpected: "
01464 + str(self.trappedException.token)
01465 + ", resync=" + self.getText() + ">")
01466
01467 return "<error: "+self.getText()+">"
01468
01469
01470 class CommonTreeAdaptor(BaseTreeAdaptor):
01471 """
01472 @brief A TreeAdaptor that works with any Tree implementation.
01473
01474 It provides
01475 really just factory methods; all the work is done by BaseTreeAdaptor.
01476 If you would like to have different tokens created than ClassicToken
01477 objects, you need to override this and then set the parser tree adaptor to
01478 use your subclass.
01479
01480 To get your parser to build nodes of a different type, override
01481 create(Token), errorNode(), and to be safe, YourTreeClass.dupNode().
01482 dupNode is called to duplicate nodes during rewrite operations.
01483 """
01484
01485 def dupNode(self, treeNode):
01486 """
01487 Duplicate a node. This is part of the factory;
01488 override if you want another kind of node to be built.
01489
01490 I could use reflection to prevent having to override this
01491 but reflection is slow.
01492 """
01493
01494 if treeNode is None:
01495 return None
01496
01497 return treeNode.dupNode()
01498
01499
01500 def createWithPayload(self, payload):
01501 return CommonTree(payload)
01502
01503
01504 def createToken(self, fromToken=None, tokenType=None, text=None):
01505 """
01506 Tell me how to create a token for use with imaginary token nodes.
01507 For example, there is probably no input symbol associated with imaginary
01508 token DECL, but you need to create it as a payload or whatever for
01509 the DECL node as in ^(DECL type ID).
01510
01511 If you care what the token payload objects' type is, you should
01512 override this method and any other createToken variant.
01513 """
01514
01515 if fromToken is not None:
01516 return CommonToken(oldToken=fromToken)
01517
01518 return CommonToken(type=tokenType, text=text)
01519
01520
01521 def setTokenBoundaries(self, t, startToken, stopToken):
01522 """
01523 Track start/stop token for subtree root created for a rule.
01524 Only works with Tree nodes. For rules that match nothing,
01525 seems like this will yield start=i and stop=i-1 in a nil node.
01526 Might be useful info so I'll not force to be i..i.
01527 """
01528
01529 if t is None:
01530 return
01531
01532 start = 0
01533 stop = 0
01534
01535 if startToken is not None:
01536 start = startToken.index
01537
01538 if stopToken is not None:
01539 stop = stopToken.index
01540
01541 t.setTokenStartIndex(start)
01542 t.setTokenStopIndex(stop)
01543
01544
01545 def getTokenStartIndex(self, t):
01546 if t is None:
01547 return -1
01548 return t.getTokenStartIndex()
01549
01550
01551 def getTokenStopIndex(self, t):
01552 if t is None:
01553 return -1
01554 return t.getTokenStopIndex()
01555
01556
01557 def getText(self, t):
01558 if t is None:
01559 return None
01560 return t.getText()
01561
01562
01563 def getType(self, t):
01564 if t is None:
01565 return INVALID_TOKEN_TYPE
01566
01567 return t.getType()
01568
01569
01570 def getToken(self, t):
01571 """
01572 What is the Token associated with this node? If
01573 you are not using CommonTree, then you must
01574 override this in your own adaptor.
01575 """
01576
01577 if isinstance(t, CommonTree):
01578 return t.getToken()
01579
01580 return None
01581
01582
01583 def getChild(self, t, i):
01584 if t is None:
01585 return None
01586 return t.getChild(i)
01587
01588
01589 def getChildCount(self, t):
01590 if t is None:
01591 return 0
01592 return t.getChildCount()
01593
01594
01595 def getParent(self, t):
01596 return t.getParent()
01597
01598
01599 def setParent(self, t, parent):
01600 t.setParent(parent)
01601
01602
01603 def getChildIndex(self, t):
01604 if t is None:
01605 return 0
01606 return t.getChildIndex()
01607
01608
01609 def setChildIndex(self, t, index):
01610 t.setChildIndex(index)
01611
01612
01613 def replaceChildren(self, parent, startChildIndex, stopChildIndex, t):
01614 if parent is not None:
01615 parent.replaceChildren(startChildIndex, stopChildIndex, t)
01616
01617
01618
01619
01620
01621
01622
01623
01624
01625
01626
01627
01628
01629
01630
01631
01632
01633
01634 class TreeNodeStream(IntStream):
01635 """@brief A stream of tree nodes
01636
01637 It accessing nodes from a tree of some kind.
01638 """
01639
01640
01641
01642
01643
01644 def get(self, i):
01645 """Get a tree node at an absolute index i; 0..n-1.
01646 If you don't want to buffer up nodes, then this method makes no
01647 sense for you.
01648 """
01649
01650 raise NotImplementedError
01651
01652
01653 def LT(self, k):
01654 """
01655 Get tree node at current input pointer + i ahead where i=1 is next node.
01656 i<0 indicates nodes in the past. So LT(-1) is previous node, but
01657 implementations are not required to provide results for k < -1.
01658 LT(0) is undefined. For i>=n, return null.
01659 Return null for LT(0) and any index that results in an absolute address
01660 that is negative.
01661
01662 This is analogus to the LT() method of the TokenStream, but this
01663 returns a tree node instead of a token. Makes code gen identical
01664 for both parser and tree grammars. :)
01665 """
01666
01667 raise NotImplementedError
01668
01669
01670 def getTreeSource(self):
01671 """
01672 Where is this stream pulling nodes from? This is not the name, but
01673 the object that provides node objects.
01674 """
01675
01676 raise NotImplementedError
01677
01678
01679 def getTokenStream(self):
01680 """
01681 If the tree associated with this stream was created from a TokenStream,
01682 you can specify it here. Used to do rule $text attribute in tree
01683 parser. Optional unless you use tree parser rule text attribute
01684 or output=template and rewrite=true options.
01685 """
01686
01687 raise NotImplementedError
01688
01689
01690 def getTreeAdaptor(self):
01691 """
01692 What adaptor can tell me how to interpret/navigate nodes and
01693 trees. E.g., get text of a node.
01694 """
01695
01696 raise NotImplementedError
01697
01698
01699 def setUniqueNavigationNodes(self, uniqueNavigationNodes):
01700 """
01701 As we flatten the tree, we use UP, DOWN nodes to represent
01702 the tree structure. When debugging we need unique nodes
01703 so we have to instantiate new ones. When doing normal tree
01704 parsing, it's slow and a waste of memory to create unique
01705 navigation nodes. Default should be false;
01706 """
01707
01708 raise NotImplementedError
01709
01710
01711 def toString(self, start, stop):
01712 """
01713 Return the text of all nodes from start to stop, inclusive.
01714 If the stream does not buffer all the nodes then it can still
01715 walk recursively from start until stop. You can always return
01716 null or "" too, but users should not access $ruleLabel.text in
01717 an action of course in that case.
01718 """
01719
01720 raise NotImplementedError
01721
01722
01723
01724 def replaceChildren(self, parent, startChildIndex, stopChildIndex, t):
01725 """
01726 Replace from start to stop child index of parent with t, which might
01727 be a list. Number of children may be different
01728 after this call. The stream is notified because it is walking the
01729 tree and might need to know you are monkeying with the underlying
01730 tree. Also, it might be able to modify the node stream to avoid
01731 restreaming for future phases.
01732
01733 If parent is null, don't do anything; must be at root of overall tree.
01734 Can't replace whatever points to the parent externally. Do nothing.
01735 """
01736
01737 raise NotImplementedError
01738
01739
01740 class CommonTreeNodeStream(TreeNodeStream):
01741 """@brief A buffered stream of tree nodes.
01742
01743 Nodes can be from a tree of ANY kind.
01744
01745 This node stream sucks all nodes out of the tree specified in
01746 the constructor during construction and makes pointers into
01747 the tree using an array of Object pointers. The stream necessarily
01748 includes pointers to DOWN and UP and EOF nodes.
01749
01750 This stream knows how to mark/release for backtracking.
01751
01752 This stream is most suitable for tree interpreters that need to
01753 jump around a lot or for tree parsers requiring speed (at cost of memory).
01754 There is some duplicated functionality here with UnBufferedTreeNodeStream
01755 but just in bookkeeping, not tree walking etc...
01756
01757 @see UnBufferedTreeNodeStream
01758 """
01759
01760 def __init__(self, *args):
01761 TreeNodeStream.__init__(self)
01762
01763 if len(args) == 1:
01764 adaptor = CommonTreeAdaptor()
01765 tree = args[0]
01766
01767 nodes = None
01768 down = None
01769 up = None
01770 eof = None
01771
01772 elif len(args) == 2:
01773 adaptor = args[0]
01774 tree = args[1]
01775
01776 nodes = None
01777 down = None
01778 up = None
01779 eof = None
01780
01781 elif len(args) == 3:
01782 parent = args[0]
01783 start = args[1]
01784 stop = args[2]
01785
01786 adaptor = parent.adaptor
01787 tree = parent.root
01788
01789 nodes = parent.nodes[start:stop]
01790 down = parent.down
01791 up = parent.up
01792 eof = parent.eof
01793
01794 else:
01795 raise TypeError("Invalid arguments")
01796
01797
01798
01799 if down is not None:
01800 self.down = down
01801 else:
01802 self.down = adaptor.createFromType(DOWN, "DOWN")
01803
01804 if up is not None:
01805 self.up = up
01806 else:
01807 self.up = adaptor.createFromType(UP, "UP")
01808
01809 if eof is not None:
01810 self.eof = eof
01811 else:
01812 self.eof = adaptor.createFromType(EOF, "EOF")
01813
01814
01815
01816
01817
01818
01819
01820
01821
01822 if nodes is not None:
01823 self.nodes = nodes
01824 else:
01825 self.nodes = []
01826
01827
01828 self.root = tree
01829
01830
01831 self.tokens = None
01832
01833
01834 self.adaptor = adaptor
01835
01836
01837 self.uniqueNavigationNodes = False
01838
01839
01840
01841 self.p = -1
01842
01843
01844 self.lastMarker = None
01845
01846
01847 self.calls = []
01848
01849
01850 def fillBuffer(self):
01851 """Walk tree with depth-first-search and fill nodes buffer.
01852 Don't do DOWN, UP nodes if its a list (t is isNil).
01853 """
01854
01855 self._fillBuffer(self.root)
01856 self.p = 0
01857
01858
01859 def _fillBuffer(self, t):
01860 nil = self.adaptor.isNil(t)
01861
01862 if not nil:
01863 self.nodes.append(t)
01864
01865
01866 n = self.adaptor.getChildCount(t)
01867 if not nil and n > 0:
01868 self.addNavigationNode(DOWN)
01869
01870
01871 for c in range(n):
01872 self._fillBuffer(self.adaptor.getChild(t, c))
01873
01874
01875 if not nil and n > 0:
01876 self.addNavigationNode(UP)
01877
01878
01879 def getNodeIndex(self, node):
01880 """What is the stream index for node? 0..n-1
01881 Return -1 if node not found.
01882 """
01883
01884 if self.p == -1:
01885 self.fillBuffer()
01886
01887 for i, t in enumerate(self.nodes):
01888 if t == node:
01889 return i
01890
01891 return -1
01892
01893
01894 def addNavigationNode(self, ttype):
01895 """
01896 As we flatten the tree, we use UP, DOWN nodes to represent
01897 the tree structure. When debugging we need unique nodes
01898 so instantiate new ones when uniqueNavigationNodes is true.
01899 """
01900
01901 navNode = None
01902
01903 if ttype == DOWN:
01904 if self.hasUniqueNavigationNodes():
01905 navNode = self.adaptor.createFromType(DOWN, "DOWN")
01906
01907 else:
01908 navNode = self.down
01909
01910 else:
01911 if self.hasUniqueNavigationNodes():
01912 navNode = self.adaptor.createFromType(UP, "UP")
01913
01914 else:
01915 navNode = self.up
01916
01917 self.nodes.append(navNode)
01918
01919
01920 def get(self, i):
01921 if self.p == -1:
01922 self.fillBuffer()
01923
01924 return self.nodes[i]
01925
01926
01927 def LT(self, k):
01928 if self.p == -1:
01929 self.fillBuffer()
01930
01931 if k == 0:
01932 return None
01933
01934 if k < 0:
01935 return self.LB(-k)
01936
01937 if self.p + k - 1 >= len(self.nodes):
01938 return self.eof
01939
01940 return self.nodes[self.p + k - 1]
01941
01942
01943 def getCurrentSymbol(self):
01944 return self.LT(1)
01945
01946
01947 def LB(self, k):
01948 """Look backwards k nodes"""
01949
01950 if k == 0:
01951 return None
01952
01953 if self.p - k < 0:
01954 return None
01955
01956 return self.nodes[self.p - k]
01957
01958
01959 def getTreeSource(self):
01960 return self.root
01961
01962
01963 def getSourceName(self):
01964 return self.getTokenStream().getSourceName()
01965
01966
01967 def getTokenStream(self):
01968 return self.tokens
01969
01970
01971 def setTokenStream(self, tokens):
01972 self.tokens = tokens
01973
01974
01975 def getTreeAdaptor(self):
01976 return self.adaptor
01977
01978
01979 def hasUniqueNavigationNodes(self):
01980 return self.uniqueNavigationNodes
01981
01982
01983 def setUniqueNavigationNodes(self, uniqueNavigationNodes):
01984 self.uniqueNavigationNodes = uniqueNavigationNodes
01985
01986
01987 def consume(self):
01988 if self.p == -1:
01989 self.fillBuffer()
01990
01991 self.p += 1
01992
01993
01994 def LA(self, i):
01995 return self.adaptor.getType(self.LT(i))
01996
01997
01998 def mark(self):
01999 if self.p == -1:
02000 self.fillBuffer()
02001
02002
02003 self.lastMarker = self.index()
02004 return self.lastMarker
02005
02006
02007 def release(self, marker=None):
02008
02009
02010 pass
02011
02012
02013 def index(self):
02014 return self.p
02015
02016
02017 def rewind(self, marker=None):
02018 if marker is None:
02019 marker = self.lastMarker
02020
02021 self.seek(marker)
02022
02023
02024 def seek(self, index):
02025 if self.p == -1:
02026 self.fillBuffer()
02027
02028 self.p = index
02029
02030
02031 def push(self, index):
02032 """
02033 Make stream jump to a new location, saving old location.
02034 Switch back with pop().
02035 """
02036
02037 self.calls.append(self.p)
02038 self.seek(index)
02039
02040
02041 def pop(self):
02042 """
02043 Seek back to previous index saved during last push() call.
02044 Return top of stack (return index).
02045 """
02046
02047 ret = self.calls.pop(-1)
02048 self.seek(ret)
02049 return ret
02050
02051
02052 def reset(self):
02053 self.p = 0
02054 self.lastMarker = 0
02055 self.calls = []
02056
02057
02058 def size(self):
02059 if self.p == -1:
02060 self.fillBuffer()
02061
02062 return len(self.nodes)
02063
02064
02065
02066
02067 def replaceChildren(self, parent, startChildIndex, stopChildIndex, t):
02068 if parent is not None:
02069 self.adaptor.replaceChildren(
02070 parent, startChildIndex, stopChildIndex, t
02071 )
02072
02073
02074 def __str__(self):
02075 """Used for testing, just return the token type stream"""
02076
02077 if self.p == -1:
02078 self.fillBuffer()
02079
02080 return ' '.join([str(self.adaptor.getType(node))
02081 for node in self.nodes
02082 ])
02083
02084
02085 def toString(self, start, stop):
02086 if start is None or stop is None:
02087 return None
02088
02089 if self.p == -1:
02090 self.fillBuffer()
02091
02092
02093
02094
02095
02096
02097
02098
02099
02100
02101
02102
02103 if self.tokens is not None:
02104 beginTokenIndex = self.adaptor.getTokenStartIndex(start)
02105 endTokenIndex = self.adaptor.getTokenStopIndex(stop)
02106
02107
02108
02109 if self.adaptor.getType(stop) == UP:
02110 endTokenIndex = self.adaptor.getTokenStopIndex(start)
02111
02112 elif self.adaptor.getType(stop) == EOF:
02113 endTokenIndex = self.size() -2
02114
02115 return self.tokens.toString(beginTokenIndex, endTokenIndex)
02116
02117
02118 i, t = 0, None
02119 for i, t in enumerate(self.nodes):
02120 if t == start:
02121 break
02122
02123
02124 buf = []
02125 t = self.nodes[i]
02126 while t != stop:
02127 text = self.adaptor.getText(t)
02128 if text is None:
02129 text = " " + self.adaptor.getType(t)
02130
02131 buf.append(text)
02132 i += 1
02133 t = self.nodes[i]
02134
02135
02136 text = self.adaptor.getText(stop)
02137 if text is None:
02138 text = " " +self.adaptor.getType(stop)
02139
02140 buf.append(text)
02141
02142 return ''.join(buf)
02143
02144
02145
02146 def __iter__(self):
02147 if self.p == -1:
02148 self.fillBuffer()
02149
02150 for node in self.nodes:
02151 yield node
02152
02153
02154
02155
02156
02157
02158
02159
02160 class TreeParser(BaseRecognizer):
02161 """@brief Baseclass for generated tree parsers.
02162
02163 A parser for a stream of tree nodes. "tree grammars" result in a subclass
02164 of this. All the error reporting and recovery is shared with Parser via
02165 the BaseRecognizer superclass.
02166 """
02167
02168 def __init__(self, input, state=None):
02169 BaseRecognizer.__init__(self, state)
02170
02171 self.input = None
02172 self.setTreeNodeStream(input)
02173
02174
02175 def reset(self):
02176 BaseRecognizer.reset(self)
02177 if self.input is not None:
02178 self.input.seek(0)
02179
02180
02181 def setTreeNodeStream(self, input):
02182 """Set the input stream"""
02183
02184 self.input = input
02185
02186
02187 def getTreeNodeStream(self):
02188 return self.input
02189
02190
02191 def getSourceName(self):
02192 return self.input.getSourceName()
02193
02194
02195 def getCurrentInputSymbol(self, input):
02196 return input.LT(1)
02197
02198
02199 def getMissingSymbol(self, input, e, expectedTokenType, follow):
02200 tokenText = "<missing " + self.tokenNames[expectedTokenType] + ">"
02201 return CommonTree(CommonToken(type=expectedTokenType, text=tokenText))
02202
02203
02204
02205 dotdot = ".*[^.]\\.\\.[^.].*"
02206 doubleEtc = ".*\\.\\.\\.\\s+\\.\\.\\..*"
02207 dotdotPattern = re.compile(dotdot)
02208 doubleEtcPattern = re.compile(doubleEtc)
02209
02210 def inContext(self, context, adaptor=None, tokenName=None, t=None):
02211 """Check if current node in input has a context.
02212
02213 Context means sequence of nodes towards root of tree. For example,
02214 you might say context is "MULT" which means my parent must be MULT.
02215 "CLASS VARDEF" says current node must be child of a VARDEF and whose
02216 parent is a CLASS node. You can use "..." to mean zero-or-more nodes.
02217 "METHOD ... VARDEF" means my parent is VARDEF and somewhere above
02218 that is a METHOD node. The first node in the context is not
02219 necessarily the root. The context matcher stops matching and returns
02220 true when it runs out of context. There is no way to force the first
02221 node to be the root.
02222 """
02223
02224 return _inContext(
02225 self.input.getTreeAdaptor(), self.getTokenNames(),
02226 self.input.LT(1), context)
02227
02228 @classmethod
02229 def _inContext(cls, adaptor, tokenNames, t, context):
02230 """The worker for inContext.
02231
02232 It's static and full of parameters for testing purposes.
02233 """
02234
02235 if cls.dotdotPattern.match(context):
02236
02237 raise ValueError("invalid syntax: ..")
02238
02239 if cls.doubleEtcPattern.match(context):
02240
02241 raise ValueError("invalid syntax: ... ...")
02242
02243
02244 context = context.replace("...", " ... ")
02245 context = context.strip()
02246 nodes = context.split()
02247
02248 ni = len(nodes) - 1
02249 t = adaptor.getParent(t)
02250 while ni >= 0 and t is not None:
02251 if nodes[ni] == "...":
02252
02253 if ni == 0:
02254
02255 return True
02256 goal = nodes[ni-1]
02257 ancestor = cls._getAncestor(adaptor, tokenNames, t, goal)
02258 if ancestor is None:
02259 return False
02260 t = ancestor
02261 ni -= 1
02262
02263 name = tokenNames[adaptor.getType(t)]
02264 if name != nodes[ni]:
02265 return False
02266
02267
02268 ni -= 1
02269 t = adaptor.getParent(t)
02270
02271
02272 if t is None and ni >= 0:
02273 return False
02274
02275 return True
02276
02277 @staticmethod
02278 def _getAncestor(adaptor, tokenNames, t, goal):
02279 """Helper for static inContext."""
02280 while t is not None:
02281 name = tokenNames[adaptor.getType(t)]
02282 if name == goal:
02283 return t
02284 t = adaptor.getParent(t)
02285
02286 return None
02287
02288
02289 def matchAny(self, ignore):
02290 """
02291 Match '.' in tree parser has special meaning. Skip node or
02292 entire tree if node has children. If children, scan until
02293 corresponding UP node.
02294 """
02295
02296 self._state.errorRecovery = False
02297
02298 look = self.input.LT(1)
02299 if self.input.getTreeAdaptor().getChildCount(look) == 0:
02300 self.input.consume()
02301 return
02302
02303
02304
02305 level = 0
02306 tokenType = self.input.getTreeAdaptor().getType(look)
02307 while tokenType != EOF and not (tokenType == UP and level==0):
02308 self.input.consume()
02309 look = self.input.LT(1)
02310 tokenType = self.input.getTreeAdaptor().getType(look)
02311 if tokenType == DOWN:
02312 level += 1
02313
02314 elif tokenType == UP:
02315 level -= 1
02316
02317 self.input.consume()
02318
02319
02320 def mismatch(self, input, ttype, follow):
02321 """
02322 We have DOWN/UP nodes in the stream that have no line info; override.
02323 plus we want to alter the exception type. Don't try to recover
02324 from tree parser errors inline...
02325 """
02326
02327 raise MismatchedTreeNodeException(ttype, input)
02328
02329
02330 def getErrorHeader(self, e):
02331 """
02332 Prefix error message with the grammar name because message is
02333 always intended for the programmer because the parser built
02334 the input tree not the user.
02335 """
02336
02337 return (self.getGrammarFileName() +
02338 ": node from %sline %s:%s"
02339 % (['', "after "][e.approximateLineInfo],
02340 e.line,
02341 e.charPositionInLine
02342 )
02343 )
02344
02345 def getErrorMessage(self, e, tokenNames):
02346 """
02347 Tree parsers parse nodes they usually have a token object as
02348 payload. Set the exception token and do the default behavior.
02349 """
02350
02351 if isinstance(self, TreeParser):
02352 adaptor = e.input.getTreeAdaptor()
02353 e.token = adaptor.getToken(e.node)
02354 if e.token is not None:
02355 e.token = CommonToken(
02356 type=adaptor.getType(e.node),
02357 text=adaptor.getText(e.node)
02358 )
02359
02360 return BaseRecognizer.getErrorMessage(self, e, tokenNames)
02361
02362
02363 def traceIn(self, ruleName, ruleIndex):
02364 BaseRecognizer.traceIn(self, ruleName, ruleIndex, self.input.LT(1))
02365
02366
02367 def traceOut(self, ruleName, ruleIndex):
02368 BaseRecognizer.traceOut(self, ruleName, ruleIndex, self.input.LT(1))
02369
02370
02371
02372
02373
02374
02375
02376
02377 class TreeVisitor(object):
02378 """Do a depth first walk of a tree, applying pre() and post() actions
02379 we go.
02380 """
02381
02382 def __init__(self, adaptor=None):
02383 if adaptor is not None:
02384 self.adaptor = adaptor
02385 else:
02386 self.adaptor = CommonTreeAdaptor()
02387
02388 def visit(self, t, pre_action=None, post_action=None):
02389 """Visit every node in tree t and trigger an action for each node
02390 before/after having visited all of its children. Bottom up walk.
02391 Execute both actions even if t has no children. Ignore return
02392 results from transforming children since they will have altered
02393 the child list of this node (their parent). Return result of
02394 applying post action to this node.
02395
02396 The Python version differs from the Java version by taking two
02397 callables 'pre_action' and 'post_action' instead of a class instance
02398 that wraps those methods. Those callables must accept a TreeNode as
02399 their single argument and return the (potentially transformed or
02400 replaced) TreeNode.
02401 """
02402
02403 isNil = self.adaptor.isNil(t)
02404 if pre_action is not None and not isNil:
02405
02406 t = pre_action(t)
02407
02408 for idx in xrange(self.adaptor.getChildCount(t)):
02409 child = self.adaptor.getChild(t, idx)
02410 self.visit(child, pre_action, post_action)
02411
02412 if post_action is not None and not isNil:
02413 t = post_action(t)
02414
02415 return t
02416
02417
02418
02419
02420
02421
02422
02423
02424 class RewriteRuleElementStream(object):
02425 """@brief Internal helper class.
02426
02427 A generic list of elements tracked in an alternative to be used in
02428 a -> rewrite rule. We need to subclass to fill in the next() method,
02429 which returns either an AST node wrapped around a token payload or
02430 an existing subtree.
02431
02432 Once you start next()ing, do not try to add more elements. It will
02433 break the cursor tracking I believe.
02434
02435 @see org.antlr.runtime.tree.RewriteRuleSubtreeStream
02436 @see org.antlr.runtime.tree.RewriteRuleTokenStream
02437
02438 TODO: add mechanism to detect/puke on modification after reading from
02439 stream
02440 """
02441
02442 def __init__(self, adaptor, elementDescription, elements=None):
02443
02444
02445 self.cursor = 0
02446
02447
02448 self.singleElement = None
02449
02450
02451 self.elements = None
02452
02453
02454
02455
02456
02457 self.dirty = False
02458
02459
02460
02461
02462 self.elementDescription = elementDescription
02463
02464 self.adaptor = adaptor
02465
02466 if isinstance(elements, (list, tuple)):
02467
02468 self.singleElement = None
02469 self.elements = elements
02470
02471 else:
02472
02473 self.add(elements)
02474
02475
02476 def reset(self):
02477 """
02478 Reset the condition of this stream so that it appears we have
02479 not consumed any of its elements. Elements themselves are untouched.
02480 Once we reset the stream, any future use will need duplicates. Set
02481 the dirty bit.
02482 """
02483
02484 self.cursor = 0
02485 self.dirty = True
02486
02487
02488 def add(self, el):
02489 if el is None:
02490 return
02491
02492 if self.elements is not None:
02493 self.elements.append(el)
02494 return
02495
02496 if self.singleElement is None:
02497 self.singleElement = el
02498 return
02499
02500
02501 self.elements = []
02502 self.elements.append(self.singleElement)
02503 self.singleElement = None
02504 self.elements.append(el)
02505
02506
02507 def nextTree(self):
02508 """
02509 Return the next element in the stream. If out of elements, throw
02510 an exception unless size()==1. If size is 1, then return elements[0].
02511
02512 Return a duplicate node/subtree if stream is out of elements and
02513 size==1. If we've already used the element, dup (dirty bit set).
02514 """
02515
02516 if (self.dirty
02517 or (self.cursor >= len(self) and len(self) == 1)
02518 ):
02519
02520 el = self._next()
02521 return self.dup(el)
02522
02523
02524 el = self._next()
02525 return el
02526
02527
02528 def _next(self):
02529 """
02530 do the work of getting the next element, making sure that it's
02531 a tree node or subtree. Deal with the optimization of single-
02532 element list versus list of size > 1. Throw an exception
02533 if the stream is empty or we're out of elements and size>1.
02534 protected so you can override in a subclass if necessary.
02535 """
02536
02537 if len(self) == 0:
02538 raise RewriteEmptyStreamException(self.elementDescription)
02539
02540 if self.cursor >= len(self):
02541 if len(self) == 1:
02542 return self.toTree(self.singleElement)
02543
02544
02545 raise RewriteCardinalityException(self.elementDescription)
02546
02547
02548 if self.singleElement is not None:
02549 self.cursor += 1
02550 return self.toTree(self.singleElement)
02551
02552
02553 o = self.toTree(self.elements[self.cursor])
02554 self.cursor += 1
02555 return o
02556
02557
02558 def dup(self, el):
02559 """
02560 When constructing trees, sometimes we need to dup a token or AST
02561 subtree. Dup'ing a token means just creating another AST node
02562 around it. For trees, you must call the adaptor.dupTree() unless
02563 the element is for a tree root; then it must be a node dup.
02564 """
02565
02566 raise NotImplementedError
02567
02568
02569 def toTree(self, el):
02570 """
02571 Ensure stream emits trees; tokens must be converted to AST nodes.
02572 AST nodes can be passed through unmolested.
02573 """
02574
02575 return el
02576
02577
02578 def hasNext(self):
02579 return ( (self.singleElement is not None and self.cursor < 1)
02580 or (self.elements is not None
02581 and self.cursor < len(self.elements)
02582 )
02583 )
02584
02585
02586 def size(self):
02587 if self.singleElement is not None:
02588 return 1
02589
02590 if self.elements is not None:
02591 return len(self.elements)
02592
02593 return 0
02594
02595 __len__ = size
02596
02597
02598 def getDescription(self):
02599 """Deprecated. Directly access elementDescription attribute"""
02600
02601 return self.elementDescription
02602
02603
02604 class RewriteRuleTokenStream(RewriteRuleElementStream):
02605 """@brief Internal helper class."""
02606
02607 def toTree(self, el):
02608
02609
02610 return el
02611
02612
02613 def nextNode(self):
02614 t = self._next()
02615 return self.adaptor.createWithPayload(t)
02616
02617
02618 def nextToken(self):
02619 return self._next()
02620
02621
02622 def dup(self, el):
02623 raise TypeError("dup can't be called for a token stream.")
02624
02625
02626 class RewriteRuleSubtreeStream(RewriteRuleElementStream):
02627 """@brief Internal helper class."""
02628
02629 def nextNode(self):
02630 """
02631 Treat next element as a single node even if it's a subtree.
02632 This is used instead of next() when the result has to be a
02633 tree root node. Also prevents us from duplicating recently-added
02634 children; e.g., ^(type ID)+ adds ID to type and then 2nd iteration
02635 must dup the type node, but ID has been added.
02636
02637 Referencing a rule result twice is ok; dup entire tree as
02638 we can't be adding trees as root; e.g., expr expr.
02639
02640 Hideous code duplication here with super.next(). Can't think of
02641 a proper way to refactor. This needs to always call dup node
02642 and super.next() doesn't know which to call: dup node or dup tree.
02643 """
02644
02645 if (self.dirty
02646 or (self.cursor >= len(self) and len(self) == 1)
02647 ):
02648
02649
02650 el = self._next()
02651 return self.adaptor.dupNode(el)
02652
02653
02654 el = self._next()
02655 return el
02656
02657
02658 def dup(self, el):
02659 return self.adaptor.dupTree(el)
02660
02661
02662
02663 class RewriteRuleNodeStream(RewriteRuleElementStream):
02664 """
02665 Queues up nodes matched on left side of -> in a tree parser. This is
02666 the analog of RewriteRuleTokenStream for normal parsers.
02667 """
02668
02669 def nextNode(self):
02670 return self._next()
02671
02672
02673 def toTree(self, el):
02674 return self.adaptor.dupNode(el)
02675
02676
02677 def dup(self, el):
02678
02679
02680 raise TypeError("dup can't be called for a node stream.")
02681
02682
02683 class TreeRuleReturnScope(RuleReturnScope):
02684 """
02685 This is identical to the ParserRuleReturnScope except that
02686 the start property is a tree nodes not Token object
02687 when you are parsing trees. To be generic the tree node types
02688 have to be Object.
02689 """
02690
02691 def __init__(self):
02692 self.start = None
02693 self.tree = None
02694
02695
02696 def getStart(self):
02697 return self.start
02698
02699
02700 def getTree(self):
02701 return self.tree
02702