protected int ExecATN(DFA dfa, DFAState s0,
ITokenStream input, int startIndex,
ParserRuleContext outerContext)
{
if (debug || debug_list_atn_decisions)
{
Console.WriteLine("execATN decision " + dfa.decision +
" exec LA(1)==" + GetLookaheadName(input) +
" line " + input.LT(1).Line + ":" + input.LT(1).Column);
}
DFAState previousD = s0;
if (debug) Console.WriteLine("s0 = " + s0);
int t = input.LA(1);
while (true)
{ // while more work
DFAState D = GetExistingTargetState(previousD, t);
if (D == null)
{
D = ComputeTargetState(dfa, previousD, t);
}
if (D == ERROR)
{
// if any configs in previous dipped into outer context, that
// means that input up to t actually finished entry rule
// at least for SLL decision. Full LL doesn't dip into outer
// so don't need special case.
// We will get an error no matter what so delay until after
// decision; better error message. Also, no reachable target
// ATN states in SLL implies LL will also get nowhere.
// If conflict in states that dip out, choose min since we
// will get error no matter what.
NoViableAltException e = NoViableAlt(input, outerContext, previousD.configSet, startIndex);
input.Seek(startIndex);
int alt = GetSynValidOrSemInvalidAltThatFinishedDecisionEntryRule(previousD.configSet, outerContext);
if (alt != ATN.INVALID_ALT_NUMBER)
{
return alt;
}
throw e;
}
if (D.requiresFullContext && mode != PredictionMode.SLL)
{
// IF PREDS, MIGHT RESOLVE TO SINGLE ALT => SLL (or syntax error)
BitSet conflictingAlts = D.configSet.conflictingAlts;
if (D.predicates != null)
{
if (debug) Console.WriteLine("DFA state has preds in DFA sim LL failover");
int conflictIndex = input.Index;
if (conflictIndex != startIndex)
{
input.Seek(startIndex);
}
conflictingAlts = EvalSemanticContext(D.predicates, outerContext, true);
if (conflictingAlts.Cardinality() == 1)
{
if (debug) Console.WriteLine("Full LL avoided");
return conflictingAlts.NextSetBit(0);
}
if (conflictIndex != startIndex)
{
// restore the index so reporting the fallback to full
// context occurs with the index at the correct spot
input.Seek(conflictIndex);
}
}
if (dfa_debug) Console.WriteLine("ctx sensitive state " + outerContext + " in " + D);
bool fullCtx = true;
ATNConfigSet s0_closure =
ComputeStartState(dfa.atnStartState, outerContext, fullCtx);
ReportAttemptingFullContext(dfa, conflictingAlts, D.configSet, startIndex, input.Index);
int alt = ExecATNWithFullContext(dfa, D, s0_closure,
input, startIndex,
outerContext);
return alt;
}
if (D.isAcceptState)
{
if (D.predicates == null)
{
return D.prediction;
}
int stopIndex = input.Index;
input.Seek(startIndex);
BitSet alts = EvalSemanticContext(D.predicates, outerContext, true);
switch (alts.Cardinality())
{
case 0:
throw NoViableAlt(input, outerContext, D.configSet, startIndex);
case 1:
return alts.NextSetBit(0);
default:
// report ambiguity after predicate evaluation to make sure the correct
// set of ambig alts is reported.
ReportAmbiguity(dfa, D, startIndex, stopIndex, false, alts, D.configSet);
return alts.NextSetBit(0);
}
}
previousD = D;
if (t != IntStreamConstants.EOF)
{
input.Consume();
t = input.LA(1);
}
}
}