| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170 |
- #
- # 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 parser simulator that mimics what ANTLR's generated
- # parser code does. A ParserATNSimulator is used to make
- # predictions via adaptivePredict but this class moves a pointer through the
- # ATN to simulate parsing. ParserATNSimulator just
- # makes us efficient rather than having to backtrack, for example.
- #
- # This properly creates parse trees even for left recursive rules.
- #
- # We rely on the left recursive rule invocation and special predicate
- # transitions to make left recursive rules work.
- #
- # See TestParserInterpreter for examples.
- #
- from antlr4.dfa.DFA import DFA
- from antlr4.BufferedTokenStream import TokenStream
- from antlr4.Lexer import Lexer
- from antlr4.Parser import Parser
- from antlr4.ParserRuleContext import InterpreterRuleContext, ParserRuleContext
- from antlr4.Token import Token
- from antlr4.atn.ATN import ATN
- from antlr4.atn.ATNState import StarLoopEntryState, ATNState, LoopEndState
- from antlr4.atn.ParserATNSimulator import ParserATNSimulator
- from antlr4.PredictionContext import PredictionContextCache
- from antlr4.atn.Transition import Transition
- from antlr4.error.Errors import RecognitionException, UnsupportedOperationException, FailedPredicateException
- class ParserInterpreter(Parser):
- __slots__ = (
- 'grammarFileName', 'atn', 'tokenNames', 'ruleNames', 'decisionToDFA',
- 'sharedContextCache', '_parentContextStack',
- 'pushRecursionContextStates'
- )
- def __init__(self, grammarFileName:str, tokenNames:list, ruleNames:list, atn:ATN, input:TokenStream):
- super().__init__(input)
- self.grammarFileName = grammarFileName
- self.atn = atn
- self.tokenNames = tokenNames
- self.ruleNames = ruleNames
- self.decisionToDFA = [ DFA(state) for state in atn.decisionToState ]
- self.sharedContextCache = PredictionContextCache()
- self._parentContextStack = list()
- # identify the ATN states where pushNewRecursionContext must be called
- self.pushRecursionContextStates = set()
- for state in atn.states:
- if not isinstance(state, StarLoopEntryState):
- continue
- if state.isPrecedenceDecision:
- self.pushRecursionContextStates.add(state.stateNumber)
- # get atn simulator that knows how to do predictions
- self._interp = ParserATNSimulator(self, atn, self.decisionToDFA, self.sharedContextCache)
- # Begin parsing at startRuleIndex#
- def parse(self, startRuleIndex:int):
- startRuleStartState = self.atn.ruleToStartState[startRuleIndex]
- rootContext = InterpreterRuleContext(None, ATNState.INVALID_STATE_NUMBER, startRuleIndex)
- if startRuleStartState.isPrecedenceRule:
- self.enterRecursionRule(rootContext, startRuleStartState.stateNumber, startRuleIndex, 0)
- else:
- self.enterRule(rootContext, startRuleStartState.stateNumber, startRuleIndex)
- while True:
- p = self.getATNState()
- if p.stateType==ATNState.RULE_STOP :
- # pop; return from rule
- if len(self._ctx)==0:
- if startRuleStartState.isPrecedenceRule:
- result = self._ctx
- parentContext = self._parentContextStack.pop()
- self.unrollRecursionContexts(parentContext.a)
- return result
- else:
- self.exitRule()
- return rootContext
- self.visitRuleStopState(p)
- else:
- try:
- self.visitState(p)
- except RecognitionException as e:
- self.state = self.atn.ruleToStopState[p.ruleIndex].stateNumber
- self._ctx.exception = e
- self._errHandler.reportError(self, e)
- self._errHandler.recover(self, e)
- def enterRecursionRule(self, localctx:ParserRuleContext, state:int, ruleIndex:int, precedence:int):
- self._parentContextStack.append((self._ctx, localctx.invokingState))
- super().enterRecursionRule(localctx, state, ruleIndex, precedence)
- def getATNState(self):
- return self.atn.states[self.state]
- def visitState(self, p:ATNState):
- edge = 0
- if len(p.transitions) > 1:
- self._errHandler.sync(self)
- edge = self._interp.adaptivePredict(self._input, p.decision, self._ctx)
- else:
- edge = 1
- transition = p.transitions[edge - 1]
- tt = transition.serializationType
- if tt==Transition.EPSILON:
- if self.pushRecursionContextStates[p.stateNumber] and not isinstance(transition.target, LoopEndState):
- t = self._parentContextStack[-1]
- ctx = InterpreterRuleContext(t[0], t[1], self._ctx.ruleIndex)
- self.pushNewRecursionContext(ctx, self.atn.ruleToStartState[p.ruleIndex].stateNumber, self._ctx.ruleIndex)
- elif tt==Transition.ATOM:
- self.match(transition.label)
- elif tt in [ Transition.RANGE, Transition.SET, Transition.NOT_SET]:
- if not transition.matches(self._input.LA(1), Token.MIN_USER_TOKEN_TYPE, Lexer.MAX_CHAR_VALUE):
- self._errHandler.recoverInline(self)
- self.matchWildcard()
- elif tt==Transition.WILDCARD:
- self.matchWildcard()
- elif tt==Transition.RULE:
- ruleStartState = transition.target
- ruleIndex = ruleStartState.ruleIndex
- ctx = InterpreterRuleContext(self._ctx, p.stateNumber, ruleIndex)
- if ruleStartState.isPrecedenceRule:
- self.enterRecursionRule(ctx, ruleStartState.stateNumber, ruleIndex, transition.precedence)
- else:
- self.enterRule(ctx, transition.target.stateNumber, ruleIndex)
- elif tt==Transition.PREDICATE:
- if not self.sempred(self._ctx, transition.ruleIndex, transition.predIndex):
- raise FailedPredicateException(self)
- elif tt==Transition.ACTION:
- self.action(self._ctx, transition.ruleIndex, transition.actionIndex)
- elif tt==Transition.PRECEDENCE:
- if not self.precpred(self._ctx, transition.precedence):
- msg = "precpred(_ctx, " + str(transition.precedence) + ")"
- raise FailedPredicateException(self, msg)
- else:
- raise UnsupportedOperationException("Unrecognized ATN transition type.")
- self.state = transition.target.stateNumber
- def visitRuleStopState(self, p:ATNState):
- ruleStartState = self.atn.ruleToStartState[p.ruleIndex]
- if ruleStartState.isPrecedenceRule:
- parentContext = self._parentContextStack.pop()
- self.unrollRecursionContexts(parentContext.a)
- self.state = parentContext[1]
- else:
- self.exitRule()
- ruleTransition = self.atn.states[self.state].transitions[0]
- self.state = ruleTransition.followState.stateNumber
|