|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
from antlr4.Token import Token |
|
|
|
INVALID_INTERVAL = (-1, -2) |
|
|
|
class Tree(object): |
|
pass |
|
|
|
class SyntaxTree(Tree): |
|
pass |
|
|
|
class ParseTree(SyntaxTree): |
|
pass |
|
|
|
class RuleNode(ParseTree): |
|
pass |
|
|
|
class TerminalNode(ParseTree): |
|
pass |
|
|
|
class ErrorNode(TerminalNode): |
|
pass |
|
|
|
class ParseTreeVisitor(object): |
|
def visit(self, tree): |
|
return tree.accept(self) |
|
|
|
def visitChildren(self, node): |
|
result = self.defaultResult() |
|
n = node.getChildCount() |
|
for i in range(n): |
|
if not self.shouldVisitNextChild(node, result): |
|
return result |
|
|
|
c = node.getChild(i) |
|
childResult = c.accept(self) |
|
result = self.aggregateResult(result, childResult) |
|
|
|
return result |
|
|
|
def visitTerminal(self, node): |
|
return self.defaultResult() |
|
|
|
def visitErrorNode(self, node): |
|
return self.defaultResult() |
|
|
|
def defaultResult(self): |
|
return None |
|
|
|
def aggregateResult(self, aggregate, nextResult): |
|
return nextResult |
|
|
|
def shouldVisitNextChild(self, node, currentResult): |
|
return True |
|
|
|
ParserRuleContext = None |
|
|
|
class ParseTreeListener(object): |
|
|
|
def visitTerminal(self, node:TerminalNode): |
|
pass |
|
|
|
def visitErrorNode(self, node:ErrorNode): |
|
pass |
|
|
|
def enterEveryRule(self, ctx:ParserRuleContext): |
|
pass |
|
|
|
def exitEveryRule(self, ctx:ParserRuleContext): |
|
pass |
|
|
|
del ParserRuleContext |
|
|
|
class TerminalNodeImpl(TerminalNode): |
|
__slots__ = ('parentCtx', 'symbol') |
|
|
|
def __init__(self, symbol:Token): |
|
self.parentCtx = None |
|
self.symbol = symbol |
|
def __setattr__(self, key, value): |
|
super().__setattr__(key, value) |
|
|
|
def getChild(self, i:int): |
|
return None |
|
|
|
def getSymbol(self): |
|
return self.symbol |
|
|
|
def getParent(self): |
|
return self.parentCtx |
|
|
|
def getPayload(self): |
|
return self.symbol |
|
|
|
def getSourceInterval(self): |
|
if self.symbol is None: |
|
return INVALID_INTERVAL |
|
tokenIndex = self.symbol.tokenIndex |
|
return (tokenIndex, tokenIndex) |
|
|
|
def getChildCount(self): |
|
return 0 |
|
|
|
def accept(self, visitor:ParseTreeVisitor): |
|
return visitor.visitTerminal(self) |
|
|
|
def getText(self): |
|
return self.symbol.text |
|
|
|
def __str__(self): |
|
if self.symbol.type == Token.EOF: |
|
return "<EOF>" |
|
else: |
|
return self.symbol.text |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class ErrorNodeImpl(TerminalNodeImpl,ErrorNode): |
|
|
|
def __init__(self, token:Token): |
|
super().__init__(token) |
|
|
|
def accept(self, visitor:ParseTreeVisitor): |
|
return visitor.visitErrorNode(self) |
|
|
|
|
|
class ParseTreeWalker(object): |
|
|
|
DEFAULT = None |
|
|
|
def walk(self, listener:ParseTreeListener, t:ParseTree): |
|
""" |
|
Performs a walk on the given parse tree starting at the root and going down recursively |
|
with depth-first search. On each node, {@link ParseTreeWalker#enterRule} is called before |
|
recursively walking down into child nodes, then |
|
{@link ParseTreeWalker#exitRule} is called after the recursive call to wind up. |
|
@param listener The listener used by the walker to process grammar rules |
|
@param t The parse tree to be walked on |
|
""" |
|
if isinstance(t, ErrorNode): |
|
listener.visitErrorNode(t) |
|
return |
|
elif isinstance(t, TerminalNode): |
|
listener.visitTerminal(t) |
|
return |
|
self.enterRule(listener, t) |
|
for child in t.getChildren(): |
|
self.walk(listener, child) |
|
self.exitRule(listener, t) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def enterRule(self, listener:ParseTreeListener, r:RuleNode): |
|
""" |
|
Enters a grammar rule by first triggering the generic event {@link ParseTreeListener#enterEveryRule} |
|
then by triggering the event specific to the given parse tree node |
|
@param listener The listener responding to the trigger events |
|
@param r The grammar rule containing the rule context |
|
""" |
|
ctx = r.getRuleContext() |
|
listener.enterEveryRule(ctx) |
|
ctx.enterRule(listener) |
|
|
|
def exitRule(self, listener:ParseTreeListener, r:RuleNode): |
|
""" |
|
Exits a grammar rule by first triggering the event specific to the given parse tree node |
|
then by triggering the generic event {@link ParseTreeListener#exitEveryRule} |
|
@param listener The listener responding to the trigger events |
|
@param r The grammar rule containing the rule context |
|
""" |
|
ctx = r.getRuleContext() |
|
ctx.exitRule(listener) |
|
listener.exitEveryRule(ctx) |
|
|
|
ParseTreeWalker.DEFAULT = ParseTreeWalker() |
|
|