| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191 |
- # 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()
|