Spaces:
Sleeping
Sleeping
# Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. | |
# Use of this file is governed by the BSD 3-clause license that | |
# can be found in the LICENSE.txt file in the project root. | |
#* A rule invocation record for parsing. | |
# | |
# Contains all of the information about the current rule not stored in the | |
# RuleContext. It handles parse tree children list, Any ATN state | |
# tracing, and the default values available for rule indications: | |
# start, stop, rule index, current alt number, current | |
# ATN state. | |
# | |
# Subclasses made for each rule and grammar track the parameters, | |
# return values, locals, and labels specific to that rule. These | |
# are the objects that are returned from rules. | |
# | |
# Note text is not an actual field of a rule return value; it is computed | |
# from start and stop using the input stream's toString() method. I | |
# could add a ctor to this so that we can pass in and store the input | |
# stream, but I'm not sure we want to do that. It would seem to be undefined | |
# to get the .text property anyway if the rule matches tokens from multiple | |
# input streams. | |
# | |
# I do not use getters for fields of objects that are used simply to | |
# group values such as this aggregate. The getters/setters are there to | |
# satisfy the superclass interface. | |
from antlr4.RuleContext import RuleContext | |
from antlr4.Token import Token | |
from antlr4.tree.Tree import ParseTreeListener, ParseTree, TerminalNodeImpl, ErrorNodeImpl, TerminalNode, \ | |
INVALID_INTERVAL | |
# need forward declaration | |
ParserRuleContext = None | |
class ParserRuleContext(RuleContext): | |
__slots__ = ('children', 'start', 'stop', 'exception') | |
def __init__(self, parent:ParserRuleContext = None, invokingStateNumber:int = None ): | |
super().__init__(parent, invokingStateNumber) | |
#* If we are debugging or building a parse tree for a visitor, | |
# we need to track all of the tokens and rule invocations associated | |
# with this rule's context. This is empty for parsing w/o tree constr. | |
# operation because we don't the need to track the details about | |
# how we parse this rule. | |
#/ | |
self.children = None | |
self.start = None | |
self.stop = None | |
# The exception that forced this rule to return. If the rule successfully | |
# completed, this is {@code null}. | |
self.exception = None | |
#* COPY a ctx (I'm deliberately not using copy constructor)#/ | |
# | |
# This is used in the generated parser code to flip a generic XContext | |
# node for rule X to a YContext for alt label Y. In that sense, it is | |
# not really a generic copy function. | |
# | |
# If we do an error sync() at start of a rule, we might add error nodes | |
# to the generic XContext so this function must copy those nodes to | |
# the YContext as well else they are lost! | |
#/ | |
def copyFrom(self, ctx:ParserRuleContext): | |
# from RuleContext | |
self.parentCtx = ctx.parentCtx | |
self.invokingState = ctx.invokingState | |
self.children = None | |
self.start = ctx.start | |
self.stop = ctx.stop | |
# copy any error nodes to alt label node | |
if ctx.children is not None: | |
self.children = [] | |
# reset parent pointer for any error nodes | |
for child in ctx.children: | |
if isinstance(child, ErrorNodeImpl): | |
self.children.append(child) | |
child.parentCtx = self | |
# Double dispatch methods for listeners | |
def enterRule(self, listener:ParseTreeListener): | |
pass | |
def exitRule(self, listener:ParseTreeListener): | |
pass | |
#* Does not set parent link; other add methods do that#/ | |
def addChild(self, child:ParseTree): | |
if self.children is None: | |
self.children = [] | |
self.children.append(child) | |
return child | |
#* Used by enterOuterAlt to toss out a RuleContext previously added as | |
# we entered a rule. If we have # label, we will need to remove | |
# generic ruleContext object. | |
#/ | |
def removeLastChild(self): | |
if self.children is not None: | |
del self.children[len(self.children)-1] | |
def addTokenNode(self, token:Token): | |
node = TerminalNodeImpl(token) | |
self.addChild(node) | |
node.parentCtx = self | |
return node | |
def addErrorNode(self, badToken:Token): | |
node = ErrorNodeImpl(badToken) | |
self.addChild(node) | |
node.parentCtx = self | |
return node | |
def getChild(self, i:int, ttype:type = None): | |
if ttype is None: | |
return self.children[i] if len(self.children)>i else None | |
else: | |
for child in self.getChildren(): | |
if not isinstance(child, ttype): | |
continue | |
if i==0: | |
return child | |
i -= 1 | |
return None | |
def getChildren(self, predicate = None): | |
if self.children is not None: | |
for child in self.children: | |
if predicate is not None and not predicate(child): | |
continue | |
yield child | |
def getToken(self, ttype:int, i:int): | |
for child in self.getChildren(): | |
if not isinstance(child, TerminalNode): | |
continue | |
if child.symbol.type != ttype: | |
continue | |
if i==0: | |
return child | |
i -= 1 | |
return None | |
def getTokens(self, ttype:int ): | |
if self.getChildren() is None: | |
return [] | |
tokens = [] | |
for child in self.getChildren(): | |
if not isinstance(child, TerminalNode): | |
continue | |
if child.symbol.type != ttype: | |
continue | |
tokens.append(child) | |
return tokens | |
def getTypedRuleContext(self, ctxType:type, i:int): | |
return self.getChild(i, ctxType) | |
def getTypedRuleContexts(self, ctxType:type): | |
children = self.getChildren() | |
if children is None: | |
return [] | |
contexts = [] | |
for child in children: | |
if not isinstance(child, ctxType): | |
continue | |
contexts.append(child) | |
return contexts | |
def getChildCount(self): | |
return len(self.children) if self.children else 0 | |
def getSourceInterval(self): | |
if self.start is None or self.stop is None: | |
return INVALID_INTERVAL | |
else: | |
return (self.start.tokenIndex, self.stop.tokenIndex) | |
RuleContext.EMPTY = ParserRuleContext() | |
class InterpreterRuleContext(ParserRuleContext): | |
def __init__(self, parent:ParserRuleContext, invokingStateNumber:int, ruleIndex:int): | |
super().__init__(parent, invokingStateNumber) | |
self.ruleIndex = ruleIndex | |