Class: ParserInterpreter
- Inherits:
-
Parser
- Object
- Recognizer
- Parser
- ParserInterpreter
- Defined in:
- lib/antlr4/ParserInterpreter.rb
Overview
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.
Instance Attribute Summary collapse
-
#atn ⇒ Object
Returns the value of attribute atn.
-
#decisionToDFA ⇒ Object
Returns the value of attribute decisionToDFA.
-
#grammarFileName ⇒ Object
Returns the value of attribute grammarFileName.
-
#interp ⇒ Object
Returns the value of attribute interp.
-
#parentContextStack ⇒ Object
Returns the value of attribute parentContextStack.
-
#pushRecursionContextStates ⇒ Object
Returns the value of attribute pushRecursionContextStates.
-
#ruleNames ⇒ Object
Returns the value of attribute ruleNames.
-
#sharedContextCache ⇒ Object
Returns the value of attribute sharedContextCache.
-
#tokenNames ⇒ Object
Returns the value of attribute tokenNames.
Attributes inherited from Parser
#buildParseTrees, #ctx, #errHandler, #input, #parseListeners, #precedenceStack, #syntaxErrors, #tracer
Attributes inherited from Recognizer
#listeners, #ruleIndexMapCache, #state, #tokenTypeMapCache
Instance Method Summary collapse
- #enterRecursionRule(localctx, state, ruleIndex, precedence) ⇒ Object
- #getATNState ⇒ Object
-
#initialize(grammarFileName, tokenNames, ruleNames, atn, input) ⇒ ParserInterpreter
constructor
A new instance of ParserInterpreter.
-
#parse(startRuleIndex) ⇒ Object
Begin parsing at startRuleIndex#.
-
#visitRuleStopState(p) ⇒ Object
p:ATNState).
- #visitState(p) ⇒ Object
Methods inherited from Parser
#addContextToParseTree, #addParseListener, #compileParseTreePattern, #consume, #dumpDFA, #enterOuterAlt, #enterRule, #exitRule, #getATNWithBypassAlts, #getCurrentToken, #getDFAStrings, #getExpectedTokens, #getExpectedTokensWithinCurrentRule, #getInputStream, #getInvokingContext, #getParseListeners, #getPrecedence, #getRuleIndex, #getRuleInvocationStack, #getSourceName, #getTokenFactory, #getTokenStream, #inContext, #isExpectedToken, #match, #matchWildcard, #notifyErrorListeners, #precpred, #pushNewRecursionContext, #removeParseListener, #removeParseListeners, #reset, #setInputStream, #setTokenFactory, #setTokenStream, #setTrace, #triggerEnterRuleEvent, #triggerExitRuleEvent, #unrollRecursionContexts
Methods inherited from Recognizer
#addErrorListener, #checkVersion, #extractVersion, #getErrorHeader, #getErrorListenerDispatch, #getRuleIndexMap, #getState, #getTokenErrorDisplay, #getTokenType, #getTokenTypeMap, #precpred, #sempred
Constructor Details
#initialize(grammarFileName, tokenNames, ruleNames, atn, input) ⇒ ParserInterpreter
Returns a new instance of ParserInterpreter.
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
# File 'lib/antlr4/ParserInterpreter.rb', line 20 def initialize(grammarFileName, tokenNames, ruleNames, atn, input) super(input) self.grammarFileName = grammarFileName self.atn = atn self.tokenNames = tokenNames self.ruleNames = ruleNames self.decisionToDFA = atn.decisionToState.map {|state| DFA.new(state) } self.sharedContextCache = PredictionContextCache.new() self.parentContextStack = Array.new # identify the ATN states where pushNewRecursionContext must be called self.pushRecursionContextStates = Set.new() atn.states.each do |state| next if not state.kind_of? StarLoopEntryState if state.precedenceRuleDecision self.pushRecursionContextStates.add(state.stateNumber) end end # get atn simulator that knows how to do predictions self.interp = ParserATNSimulator.new(self, atn, self.decisionToDFA, self.sharedContextCache) end |
Instance Attribute Details
#atn ⇒ Object
Returns the value of attribute atn.
17 18 19 |
# File 'lib/antlr4/ParserInterpreter.rb', line 17 def atn @atn end |
#decisionToDFA ⇒ Object
Returns the value of attribute decisionToDFA.
18 19 20 |
# File 'lib/antlr4/ParserInterpreter.rb', line 18 def decisionToDFA @decisionToDFA end |
#grammarFileName ⇒ Object
Returns the value of attribute grammarFileName.
17 18 19 |
# File 'lib/antlr4/ParserInterpreter.rb', line 17 def grammarFileName @grammarFileName end |
#interp ⇒ Object
Returns the value of attribute interp.
19 20 21 |
# File 'lib/antlr4/ParserInterpreter.rb', line 19 def interp @interp end |
#parentContextStack ⇒ Object
Returns the value of attribute parentContextStack.
17 18 19 |
# File 'lib/antlr4/ParserInterpreter.rb', line 17 def parentContextStack @parentContextStack end |
#pushRecursionContextStates ⇒ Object
Returns the value of attribute pushRecursionContextStates.
19 20 21 |
# File 'lib/antlr4/ParserInterpreter.rb', line 19 def pushRecursionContextStates @pushRecursionContextStates end |
#ruleNames ⇒ Object
Returns the value of attribute ruleNames.
18 19 20 |
# File 'lib/antlr4/ParserInterpreter.rb', line 18 def ruleNames @ruleNames end |
#sharedContextCache ⇒ Object
Returns the value of attribute sharedContextCache.
18 19 20 |
# File 'lib/antlr4/ParserInterpreter.rb', line 18 def sharedContextCache @sharedContextCache end |
#tokenNames ⇒ Object
Returns the value of attribute tokenNames.
18 19 20 |
# File 'lib/antlr4/ParserInterpreter.rb', line 18 def tokenNames @tokenNames end |
Instance Method Details
#enterRecursionRule(localctx, state, ruleIndex, precedence) ⇒ Object
77 78 79 80 |
# File 'lib/antlr4/ParserInterpreter.rb', line 77 def enterRecursionRule(localctx, state, ruleIndex, precedence) self.parentContextStack.push([self.ctx, localctx.invokingState]) super(localctx, state, ruleIndex, precedence) end |
#getATNState ⇒ Object
81 82 83 |
# File 'lib/antlr4/ParserInterpreter.rb', line 81 def getATNState return self.atn.states[self.state] end |
#parse(startRuleIndex) ⇒ Object
Begin parsing at startRuleIndex#
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 |
# File 'lib/antlr4/ParserInterpreter.rb', line 41 def parse(startRuleIndex) startRuleStartState = self.atn.ruleToStartState[startRuleIndex] rootContext = InterpreterRuleContext.new(nil, ATNState::INVALID_STATE_NUMBER, startRuleIndex) if startRuleStartState.isPrecedenceRule self.enterRecursionRule(rootContext, startRuleStartState.stateNumber, startRuleIndex, 0) else self.enterRule(rootContext, startRuleStartState.stateNumber, startRuleIndex) end while true p = self.getATNState() if p.stateType==ATNState::RULE_STOP # pop; return from rule if self.ctx.length==0 if startRuleStartState.isPrecedenceRule result = self.ctx parentContext = self.parentContextStack.pop() self.unrollRecursionContexts(parentContext.a) return result else self.exitRule() return rootContext end end self.visitRuleStopState(p) else begin self.visitState(p) rescue RecognitionException => e self.state = self.atn.ruleToStopState[p.ruleIndex].stateNumber self.ctx.exception = e self.errHandler.reportError(self, e) self.errHandler.recover(self, e) end end end end |
#visitRuleStopState(p) ⇒ Object
p:ATNState)
137 138 139 140 141 142 143 144 145 146 147 148 |
# File 'lib/antlr4/ParserInterpreter.rb', line 137 def visitRuleStopState(p) # p:ATNState) ruleStartState = self.atn.ruleToStartState[p.ruleIndex] if ruleStartState.isPrecedenceRule then parentContext = self.parentContextStack.pop() self.unrollRecursionContexts(parentContext.a) self.state = parentContext[1] else self.exitRule() end ruleTransition = self.atn.states[self.state].transitions[0] self.state = ruleTransition.followState.stateNumber end |
#visitState(p) ⇒ Object
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 |
# File 'lib/antlr4/ParserInterpreter.rb', line 85 def visitState(p) edge = 0 if p.transitions.length() > 1 self.errHandler.sync(self) edge = self.interp.adaptivePredict(self.input, p.decision, self.ctx) else edge = 1 end transition = p.transitions[edge - 1] tt = transition.serializationType if tt==Transition::EPSILON then if self.pushRecursionContextStates[p.stateNumber] and not transition.target.kind_of? LoopEndState t = self.parentContextStack[-1] ctx = InterpreterRuleContext.new(t[0], t[1], self.ctx.ruleIndex) self.pushNewRecursionContext(ctx, self.atn.ruleToStartState[p.ruleIndex].stateNumber, self.ctx.ruleIndex) end elsif tt==Transition::ATOM self.match(transition.label) elsif [ Transition::RANGE, Transition::SET, Transition::NOT_SET].member? tt if not transition.matches(self.input.LA(1), Token::MIN_USER_TOKEN_TYPE, 0xFFFF) self.errHandler.recoverInline(self) end self.matchWildcard() elsif tt==Transition::WILDCARD self.matchWildcard() elsif 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) end elsif tt==Transition::PREDICATE if not self.sempred(self.ctx, transition.ruleIndex, transition.predIndex) raise FailedPredicateException.new(self) end elsif tt==Transition::ACTION self.action(self.ctx, transition.ruleIndex, transition.actionIndex) elsif tt==Transition::PRECEDENCE if not self.precpred(self.ctx, transition.precedence) msg = "precpred(ctx, #{transition.precedence})" raise FailedPredicateException.new(self, msg) end else raise UnsupportedOperationException.new("Unrecognized ATN transition type.") end self.state = transition.target.stateNumber end |