File size: 5,572 Bytes
72268ee |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 |
# 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.
#/
# The basic notion of a tree has a parent, a payload, and a list of children.
# It is the most abstract interface for all the trees used by ANTLR.
#/
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
# Represents a token that was consumed during resynchronization
# rather than during a valid match operation. For example,
# we will create this kind of a node during single token insertion
# and deletion as well as during "consume until error recovery set"
# upon no viable alternative exceptions.
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)
#
# The discovery of a rule node, involves sending two events: the generic
# {@link ParseTreeListener#enterEveryRule} and a
# {@link RuleContext}-specific event. First we trigger the generic and then
# the rule specific. We to them in reverse order upon finishing the node.
#
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()
|