ParserRuleContext.py 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. # Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
  2. # Use of this file is governed by the BSD 3-clause license that
  3. # can be found in the LICENSE.txt file in the project root.
  4. #* A rule invocation record for parsing.
  5. #
  6. # Contains all of the information about the current rule not stored in the
  7. # RuleContext. It handles parse tree children list, Any ATN state
  8. # tracing, and the default values available for rule indications:
  9. # start, stop, rule index, current alt number, current
  10. # ATN state.
  11. #
  12. # Subclasses made for each rule and grammar track the parameters,
  13. # return values, locals, and labels specific to that rule. These
  14. # are the objects that are returned from rules.
  15. #
  16. # Note text is not an actual field of a rule return value; it is computed
  17. # from start and stop using the input stream's toString() method. I
  18. # could add a ctor to this so that we can pass in and store the input
  19. # stream, but I'm not sure we want to do that. It would seem to be undefined
  20. # to get the .text property anyway if the rule matches tokens from multiple
  21. # input streams.
  22. #
  23. # I do not use getters for fields of objects that are used simply to
  24. # group values such as this aggregate. The getters/setters are there to
  25. # satisfy the superclass interface.
  26. from antlr4.RuleContext import RuleContext
  27. from antlr4.Token import Token
  28. from antlr4.tree.Tree import ParseTreeListener, ParseTree, TerminalNodeImpl, ErrorNodeImpl, TerminalNode, \
  29. INVALID_INTERVAL
  30. # need forward declaration
  31. ParserRuleContext = None
  32. class ParserRuleContext(RuleContext):
  33. __slots__ = ('children', 'start', 'stop', 'exception')
  34. def __init__(self, parent:ParserRuleContext = None, invokingStateNumber:int = None ):
  35. super().__init__(parent, invokingStateNumber)
  36. #* If we are debugging or building a parse tree for a visitor,
  37. # we need to track all of the tokens and rule invocations associated
  38. # with this rule's context. This is empty for parsing w/o tree constr.
  39. # operation because we don't the need to track the details about
  40. # how we parse this rule.
  41. #/
  42. self.children = None
  43. self.start = None
  44. self.stop = None
  45. # The exception that forced this rule to return. If the rule successfully
  46. # completed, this is {@code null}.
  47. self.exception = None
  48. #* COPY a ctx (I'm deliberately not using copy constructor)#/
  49. #
  50. # This is used in the generated parser code to flip a generic XContext
  51. # node for rule X to a YContext for alt label Y. In that sense, it is
  52. # not really a generic copy function.
  53. #
  54. # If we do an error sync() at start of a rule, we might add error nodes
  55. # to the generic XContext so this function must copy those nodes to
  56. # the YContext as well else they are lost!
  57. #/
  58. def copyFrom(self, ctx:ParserRuleContext):
  59. # from RuleContext
  60. self.parentCtx = ctx.parentCtx
  61. self.invokingState = ctx.invokingState
  62. self.children = None
  63. self.start = ctx.start
  64. self.stop = ctx.stop
  65. # copy any error nodes to alt label node
  66. if ctx.children is not None:
  67. self.children = []
  68. # reset parent pointer for any error nodes
  69. for child in ctx.children:
  70. if isinstance(child, ErrorNodeImpl):
  71. self.children.append(child)
  72. child.parentCtx = self
  73. # Double dispatch methods for listeners
  74. def enterRule(self, listener:ParseTreeListener):
  75. pass
  76. def exitRule(self, listener:ParseTreeListener):
  77. pass
  78. #* Does not set parent link; other add methods do that#/
  79. def addChild(self, child:ParseTree):
  80. if self.children is None:
  81. self.children = []
  82. self.children.append(child)
  83. return child
  84. #* Used by enterOuterAlt to toss out a RuleContext previously added as
  85. # we entered a rule. If we have # label, we will need to remove
  86. # generic ruleContext object.
  87. #/
  88. def removeLastChild(self):
  89. if self.children is not None:
  90. del self.children[len(self.children)-1]
  91. def addTokenNode(self, token:Token):
  92. node = TerminalNodeImpl(token)
  93. self.addChild(node)
  94. node.parentCtx = self
  95. return node
  96. def addErrorNode(self, badToken:Token):
  97. node = ErrorNodeImpl(badToken)
  98. self.addChild(node)
  99. node.parentCtx = self
  100. return node
  101. def getChild(self, i:int, ttype:type = None):
  102. if ttype is None:
  103. return self.children[i] if len(self.children)>i else None
  104. else:
  105. for child in self.getChildren():
  106. if not isinstance(child, ttype):
  107. continue
  108. if i==0:
  109. return child
  110. i -= 1
  111. return None
  112. def getChildren(self, predicate = None):
  113. if self.children is not None:
  114. for child in self.children:
  115. if predicate is not None and not predicate(child):
  116. continue
  117. yield child
  118. def getToken(self, ttype:int, i:int):
  119. for child in self.getChildren():
  120. if not isinstance(child, TerminalNode):
  121. continue
  122. if child.symbol.type != ttype:
  123. continue
  124. if i==0:
  125. return child
  126. i -= 1
  127. return None
  128. def getTokens(self, ttype:int ):
  129. if self.getChildren() is None:
  130. return []
  131. tokens = []
  132. for child in self.getChildren():
  133. if not isinstance(child, TerminalNode):
  134. continue
  135. if child.symbol.type != ttype:
  136. continue
  137. tokens.append(child)
  138. return tokens
  139. def getTypedRuleContext(self, ctxType:type, i:int):
  140. return self.getChild(i, ctxType)
  141. def getTypedRuleContexts(self, ctxType:type):
  142. children = self.getChildren()
  143. if children is None:
  144. return []
  145. contexts = []
  146. for child in children:
  147. if not isinstance(child, ctxType):
  148. continue
  149. contexts.append(child)
  150. return contexts
  151. def getChildCount(self):
  152. return len(self.children) if self.children else 0
  153. def getSourceInterval(self):
  154. if self.start is None or self.stop is None:
  155. return INVALID_INTERVAL
  156. else:
  157. return (self.start.tokenIndex, self.stop.tokenIndex)
  158. RuleContext.EMPTY = ParserRuleContext()
  159. class InterpreterRuleContext(ParserRuleContext):
  160. def __init__(self, parent:ParserRuleContext, invokingStateNumber:int, ruleIndex:int):
  161. super().__init__(parent, invokingStateNumber)
  162. self.ruleIndex = ruleIndex