Repository URL to install this package:
|
Version:
2023.12.1 ▾
|
/* 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.
*/
using System;
using System.Collections.Generic;
using System.Linq;
using Antlr4.Runtime.Atn;
using Antlr4.Runtime.Misc;
using Antlr4.Runtime.Sharpen;
namespace Antlr4.Runtime
{
/// <summary>
/// A parser simulator that mimics what ANTLR's generated
/// parser code does.
/// </summary>
/// <remarks>
/// 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.
/// </remarks>
public class ParserInterpreter : Parser
{
private readonly string _grammarFileName;
private readonly ATN _atn;
private readonly Dfa.DFA[] _decisionToDFA;
protected internal readonly BitSet pushRecursionContextStates;
private readonly string[] _ruleNames;
[NotNull]
private readonly IVocabulary vocabulary;
private readonly Stack<Tuple<ParserRuleContext, int>> _parentContextStack = new Stack<Tuple<ParserRuleContext, int>>();
public ParserInterpreter(string grammarFileName, IVocabulary vocabulary, IEnumerable<string> ruleNames, ATN atn, ITokenStream input)
: base(input)
{
this._grammarFileName = grammarFileName;
this._atn = atn;
this._ruleNames = ruleNames.ToArray();
this.vocabulary = vocabulary;
// identify the ATN states where pushNewRecursionContext must be called
this.pushRecursionContextStates = new BitSet(atn.states.Count);
foreach (ATNState state in atn.states)
{
if (!(state is StarLoopEntryState))
{
continue;
}
if (((StarLoopEntryState)state).isPrecedenceDecision)
{
this.pushRecursionContextStates.Set(state.stateNumber);
}
}
//init decision DFA
int numberofDecisions = atn.NumberOfDecisions;
this._decisionToDFA = new Dfa.DFA[numberofDecisions];
for (int i = 0; i < numberofDecisions; i++)
{
DecisionState decisionState = atn.GetDecisionState(i);
_decisionToDFA[i] = new Dfa.DFA(decisionState, i);
}
// get atn simulator that knows how to do predictions
Interpreter = new ParserATNSimulator(this, atn, _decisionToDFA, null);
}
public override ATN Atn
{
get
{
return _atn;
}
}
public override IVocabulary Vocabulary
{
get
{
return vocabulary;
}
}
public override string[] RuleNames
{
get
{
return _ruleNames;
}
}
public override string GrammarFileName
{
get
{
return _grammarFileName;
}
}
/// <summary>Begin parsing at startRuleIndex</summary>
public virtual ParserRuleContext Parse(int startRuleIndex)
{
RuleStartState startRuleStartState = _atn.ruleToStartState[startRuleIndex];
InterpreterRuleContext rootContext = new InterpreterRuleContext(null, ATNState.InvalidStateNumber, startRuleIndex);
if (startRuleStartState.isPrecedenceRule)
{
EnterRecursionRule(rootContext, startRuleStartState.stateNumber, startRuleIndex, 0);
}
else
{
EnterRule(rootContext, startRuleStartState.stateNumber, startRuleIndex);
}
while (true)
{
ATNState p = AtnState;
switch (p.StateType)
{
case StateType.RuleStop:
{
// pop; return from rule
if (RuleContext.IsEmpty)
{
if (startRuleStartState.isPrecedenceRule)
{
ParserRuleContext result = RuleContext;
Tuple<ParserRuleContext, int> parentContext = _parentContextStack.Pop();
UnrollRecursionContexts(parentContext.Item1);
return result;
}
else
{
ExitRule();
return rootContext;
}
}
VisitRuleStopState(p);
break;
}
default:
{
try
{
VisitState(p);
}
catch (RecognitionException e)
{
State = _atn.ruleToStopState[p.ruleIndex].stateNumber;
Context.exception = e;
ErrorHandler.ReportError(this, e);
ErrorHandler.Recover(this, e);
}
break;
}
}
}
}
public override void EnterRecursionRule(ParserRuleContext localctx, int state, int ruleIndex, int precedence)
{
_parentContextStack.Push(Tuple.Create(RuleContext, localctx.invokingState));
base.EnterRecursionRule(localctx, state, ruleIndex, precedence);
}
protected internal virtual ATNState AtnState
{
get
{
return _atn.states[State];
}
}
protected internal virtual void VisitState(ATNState p)
{
int edge;
if (p.NumberOfTransitions > 1)
{
ErrorHandler.Sync(this);
edge = Interpreter.AdaptivePredict(TokenStream, ((DecisionState)p).decision, RuleContext);
}
else
{
edge = 1;
}
Transition transition = p.Transition(edge - 1);
switch (transition.TransitionType)
{
case TransitionType.EPSILON:
{
if (pushRecursionContextStates.Get(p.stateNumber) && !(transition.target is LoopEndState))
{
InterpreterRuleContext ctx = new InterpreterRuleContext(_parentContextStack.Peek().Item1, _parentContextStack.Peek().Item2, RuleContext.RuleIndex);
PushNewRecursionContext(ctx, _atn.ruleToStartState[p.ruleIndex].stateNumber, RuleContext.RuleIndex);
}
break;
}
case TransitionType.ATOM:
{
Match(((AtomTransition)transition).token);
break;
}
case TransitionType.RANGE:
case TransitionType.SET:
case TransitionType.NOT_SET:
{
if (!transition.Matches(TokenStream.LA(1), TokenConstants.MinUserTokenType, 65535))
{
ErrorHandler.RecoverInline(this);
}
MatchWildcard();
break;
}
case TransitionType.WILDCARD:
{
MatchWildcard();
break;
}
case TransitionType.RULE:
{
RuleStartState ruleStartState = (RuleStartState)transition.target;
int ruleIndex = ruleStartState.ruleIndex;
InterpreterRuleContext ctx_1 = new InterpreterRuleContext(RuleContext, p.stateNumber, ruleIndex);
if (ruleStartState.isPrecedenceRule)
{
EnterRecursionRule(ctx_1, ruleStartState.stateNumber, ruleIndex, ((RuleTransition)transition).precedence);
}
else
{
EnterRule(ctx_1, transition.target.stateNumber, ruleIndex);
}
break;
}
case TransitionType.PREDICATE:
{
PredicateTransition predicateTransition = (PredicateTransition)transition;
if (!Sempred(RuleContext, predicateTransition.ruleIndex, predicateTransition.predIndex))
{
throw new FailedPredicateException(this);
}
break;
}
case TransitionType.ACTION:
{
ActionTransition actionTransition = (ActionTransition)transition;
Action(RuleContext, actionTransition.ruleIndex, actionTransition.actionIndex);
break;
}
case TransitionType.PRECEDENCE:
{
if (!Precpred(RuleContext, ((PrecedencePredicateTransition)transition).precedence))
{
throw new FailedPredicateException(this, string.Format("precpred(_ctx, {0})", ((PrecedencePredicateTransition)transition).precedence));
}
break;
}
default:
{
throw new NotSupportedException("Unrecognized ATN transition type.");
}
}
State = transition.target.stateNumber;
}
protected internal virtual void VisitRuleStopState(ATNState p)
{
RuleStartState ruleStartState = _atn.ruleToStartState[p.ruleIndex];
if (ruleStartState.isPrecedenceRule)
{
Tuple<ParserRuleContext, int> parentContext = _parentContextStack.Pop();
UnrollRecursionContexts(parentContext.Item1);
State = parentContext.Item2;
}
else
{
ExitRule();
}
RuleTransition ruleTransition = (RuleTransition)_atn.states[State].Transition(0);
State = ruleTransition.followState.stateNumber;
}
}
}