protected internal ATNConfigSet(Antlr4.Runtime.Atn.ATNConfigSet set, bool @readonly) { if (@readonly) { this.mergedConfigs = null; this.unmerged = null; } else { if (!set.IsReadOnly) { this.mergedConfigs = new Dictionary <long, ATNConfig>(set.mergedConfigs); this.unmerged = new List <ATNConfig>(set.unmerged); } else { this.mergedConfigs = new Dictionary <long, ATNConfig>(set.configs.Count); this.unmerged = new List <ATNConfig>(); } } this.configs = new List <ATNConfig>(set.configs); this.dipsIntoOuterContext = set.dipsIntoOuterContext; this.hasSemanticContext = set.hasSemanticContext; this.outermostConfigSet = set.outermostConfigSet; if (@readonly || !set.IsReadOnly) { this.uniqueAlt = set.uniqueAlt; this.conflictingAlts = set.conflictingAlts; } }
public virtual Antlr4.Runtime.Atn.ATNConfigSet Clone(bool @readonly) { Antlr4.Runtime.Atn.ATNConfigSet copy = new Antlr4.Runtime.Atn.ATNConfigSet(this, @readonly); if (!@readonly && this.IsReadOnly) { copy.AddAll(configs); } return(copy); }
public override bool Equals(object obj) { if (this == obj) { return(true); } if (!(obj is Antlr4.Runtime.Atn.ATNConfigSet)) { return(false); } Antlr4.Runtime.Atn.ATNConfigSet other = (Antlr4.Runtime.Atn.ATNConfigSet)obj; return(this.outermostConfigSet == other.outermostConfigSet && Utils.Equals(conflictingAlts, other.conflictingAlts) && configs.SequenceEqual(other.configs)); }
protected internal override void ReportAmbiguity([NotNull] DFA dfa, DFAState D, int startIndex, int stopIndex, bool exact, [NotNull] BitSet ambigAlts, [NotNull] ATNConfigSet configs) { int prediction; if (ambigAlts != null) { prediction = ambigAlts.NextSetBit(0); } else { prediction = configs.RepresentedAlternatives.NextSetBit(0); } if (conflictingAltResolvedBySLL != ATN.InvalidAltNumber && prediction != conflictingAltResolvedBySLL) { // Even though this is an ambiguity we are reporting, we can // still detect some context sensitivities. Both SLL and LL // are showing a conflict, hence an ambiguity, but if they resolve // to different minimum alternatives we have also identified a // context sensitivity. decisions[currentDecision].contextSensitivities.Add(new ContextSensitivityInfo(currentDecision, currentState, _input, startIndex, stopIndex)); } decisions[currentDecision].ambiguities.Add(new AmbiguityInfo(currentDecision, currentState, ambigAlts, _input, startIndex, stopIndex)); base.ReportAmbiguity(dfa, D, startIndex, stopIndex, exact, ambigAlts, configs); }
// side-effect: can alter configs.hasSemanticContext protected LexerATNConfig GetEpsilonTarget(ICharStream input, LexerATNConfig config, Transition t, ATNConfigSet configs, bool speculative, bool treatEofAsEpsilon) { LexerATNConfig c = null; switch (t.TransitionType) { case TransitionType.RULE: RuleTransition ruleTransition = (RuleTransition)t; PredictionContext newContext = new SingletonPredictionContext(config.context, ruleTransition.followState.stateNumber); c = new LexerATNConfig(config, t.target, newContext); break; case TransitionType.PRECEDENCE: throw new Exception("Precedence predicates are not supported in lexers."); case TransitionType.PREDICATE: /* Track traversing semantic predicates. If we traverse, * we cannot add a DFA state for this "reach" computation * because the DFA would not test the predicate again in the * future. Rather than creating collections of semantic predicates * like v3 and testing them on prediction, v4 will test them on the * fly all the time using the ATN not the DFA. This is slower but * semantically it's not used that often. One of the key elements to * this predicate mechanism is not adding DFA states that see * predicates immediately afterwards in the ATN. For example, * * a : ID {p1}? | ID {p2}? ; * * should create the start state for rule 'a' (to save start state * competition), but should not create target of ID state. The * collection of ATN states the following ID references includes * states reached by traversing predicates. Since this is when we * test them, we cannot cash the DFA state target of ID. */ PredicateTransition pt = (PredicateTransition)t; if (debug) { ConsoleWriteLine("EVAL rule " + pt.ruleIndex + ":" + pt.predIndex); } configs.hasSemanticContext = true; if (EvaluatePredicate(input, pt.ruleIndex, pt.predIndex, speculative)) { c = new LexerATNConfig(config, t.target); } break; case TransitionType.ACTION: if (config.context == null || config.context.HasEmptyPath) { // execute actions anywhere in the start rule for a token. // // TODO: if the entry rule is invoked recursively, some // actions may be executed during the recursive call. The // problem can appear when hasEmptyPath() is true but // isEmpty() is false. In this case, the config needs to be // split into two contexts - one with just the empty path // and another with everything but the empty path. // Unfortunately, the current algorithm does not allow // getEpsilonTarget to return two configurations, so // additional modifications are needed before we can support // the split operation. LexerActionExecutor lexerActionExecutor = LexerActionExecutor.Append(config.getLexerActionExecutor(), atn.lexerActions[((ActionTransition)t).actionIndex]); c = new LexerATNConfig(config, t.target, lexerActionExecutor); break; } else { // ignore actions in referenced rules c = new LexerATNConfig(config, t.target); break; } case TransitionType.EPSILON: c = new LexerATNConfig(config, t.target); break; case TransitionType.ATOM: case TransitionType.RANGE: case TransitionType.SET: if (treatEofAsEpsilon) { if (t.Matches(IntStreamConstants.EOF, Lexer.MinCharValue, Lexer.MaxCharValue)) { c = new LexerATNConfig(config, t.target); break; } } break; } return(c); }
/** * Since the alternatives within any lexer decision are ordered by * preference, this method stops pursuing the closure as soon as an accept * state is reached. After the first accept state is reached by depth-first * search from {@code config}, all other (potentially reachable) states for * this rule would have a lower priority. * * @return {@code true} if an accept state is reached, otherwise * {@code false}. */ protected bool Closure(ICharStream input, LexerATNConfig config, ATNConfigSet configs, bool currentAltReachedAcceptState, bool speculative, bool treatEofAsEpsilon) { if (debug) { ConsoleWriteLine("closure(" + config.ToString(recog, true) + ")"); } if (config.state is RuleStopState) { if (debug) { if (recog != null) { ConsoleWriteLine("closure at " + recog.RuleNames[config.state.ruleIndex] + " rule stop " + config); } else { ConsoleWriteLine("closure at rule stop " + config); } } if (config.context == null || config.context.HasEmptyPath) { if (config.context == null || config.context.IsEmpty) { configs.Add(config); return(true); } else { configs.Add(new LexerATNConfig(config, config.state, PredictionContext.EMPTY)); currentAltReachedAcceptState = true; } } if (config.context != null && !config.context.IsEmpty) { for (int i = 0; i < config.context.Size; i++) { if (config.context.GetReturnState(i) != PredictionContext.EMPTY_RETURN_STATE) { PredictionContext newContext = config.context.GetParent(i); // "pop" return state ATNState returnState = atn.states[config.context.GetReturnState(i)]; LexerATNConfig c = new LexerATNConfig(config, returnState, newContext); currentAltReachedAcceptState = Closure(input, c, configs, currentAltReachedAcceptState, speculative, treatEofAsEpsilon); } } } return(currentAltReachedAcceptState); } // optimization if (!config.state.OnlyHasEpsilonTransitions) { if (!currentAltReachedAcceptState || !config.hasPassedThroughNonGreedyDecision()) { configs.Add(config); } } ATNState p = config.state; for (int i = 0; i < p.NumberOfTransitions; i++) { Transition t = p.Transition(i); LexerATNConfig c = GetEpsilonTarget(input, config, t, configs, speculative, treatEofAsEpsilon); if (c != null) { currentAltReachedAcceptState = Closure(input, c, configs, currentAltReachedAcceptState, speculative, treatEofAsEpsilon); } } return(currentAltReachedAcceptState); }
/** Given a starting configuration set, figure out all ATN configurations * we can reach upon input {@code t}. Parameter {@code reach} is a return * parameter. */ protected void GetReachableConfigSet(ICharStream input, ATNConfigSet closure, ATNConfigSet reach, int t) { // this is used to skip processing for configs which have a lower priority // than a config that already reached an accept state for the same rule int skipAlt = ATN.INVALID_ALT_NUMBER; foreach (ATNConfig c in closure.configs) { bool currentAltReachedAcceptState = c.alt == skipAlt; if (currentAltReachedAcceptState && ((LexerATNConfig)c).hasPassedThroughNonGreedyDecision()) { continue; } if (debug) { ConsoleWriteLine("testing " + GetTokenName(t) + " at " + c.ToString(recog, true)); } int n = c.state.NumberOfTransitions; for (int ti = 0; ti < n; ti++) { // for each transition Transition trans = c.state.Transition(ti); ATNState target = GetReachableTarget(trans, t); if (target != null) { LexerActionExecutor lexerActionExecutor = ((LexerATNConfig)c).getLexerActionExecutor(); if (lexerActionExecutor != null) { lexerActionExecutor = lexerActionExecutor.FixOffsetBeforeMatch(input.Index - startIndex); } bool treatEofAsEpsilon = t == IntStreamConstants.EOF; if (Closure(input, new LexerATNConfig((LexerATNConfig)c, target, lexerActionExecutor), reach, currentAltReachedAcceptState, true, treatEofAsEpsilon)) { // any remaining configs for this alt have a lower priority than // the one that just reached an accept state. skipAlt = c.alt; break; } } } } }
protected internal virtual ATNConfig GetEpsilonTarget(ICharStream input, ATNConfig config, Transition t, ATNConfigSet configs, bool speculative, bool treatEofAsEpsilon) { ATNConfig c; switch (t.TransitionType) { case TransitionType.Rule: { RuleTransition ruleTransition = (RuleTransition)t; if (optimize_tail_calls && ruleTransition.optimizedTailCall && !config.Context.HasEmpty) { c = config.Transform(t.target, true); } else { PredictionContext newContext = config.Context.GetChild(ruleTransition.followState.stateNumber); c = config.Transform(t.target, newContext, true); } break; } case TransitionType.Precedence: { throw new NotSupportedException("Precedence predicates are not supported in lexers."); } case TransitionType.Predicate: { PredicateTransition pt = (PredicateTransition)t; configs.MarkExplicitSemanticContext(); if (EvaluatePredicate(input, pt.ruleIndex, pt.predIndex, speculative)) { c = config.Transform(t.target, true); } else { c = null; } break; } case TransitionType.Action: { if (config.Context.HasEmpty) { // execute actions anywhere in the start rule for a token. // // TODO: if the entry rule is invoked recursively, some // actions may be executed during the recursive call. The // problem can appear when hasEmpty() is true but // isEmpty() is false. In this case, the config needs to be // split into two contexts - one with just the empty path // and another with everything but the empty path. // Unfortunately, the current algorithm does not allow // getEpsilonTarget to return two configurations, so // additional modifications are needed before we can support // the split operation. LexerActionExecutor lexerActionExecutor = LexerActionExecutor.Append(config.ActionExecutor, atn.lexerActions[((ActionTransition)t).actionIndex]); c = config.Transform(t.target, lexerActionExecutor, true); break; } else { // ignore actions in referenced rules c = config.Transform(t.target, true); break; } } case TransitionType.Epsilon: { c = config.Transform(t.target, true); break; } case TransitionType.Atom: case TransitionType.Range: case TransitionType.Set: { if (treatEofAsEpsilon) { if (t.Matches(IntStreamConstants.Eof, char.MinValue, char.MaxValue)) { c = config.Transform(t.target, false); break; } } c = null; break; } default: { c = null; break; } } return(c); }
/// <summary> /// Constructs a new instance of the /// <see cref="ErrorInfo"/> /// class with the /// specified detailed syntax error information. /// </summary> /// <param name="decision">The decision number</param> /// <param name="configs">The final configuration set reached during prediction /// prior to reaching the {@link ATNSimulator#ERROR} state /// </param> /// <param name="input">The input token stream</param> /// <param name="startIndex">The start index for the current prediction</param> /// <param name="stopIndex">The index at which the syntax error was identified</param> /// <param name="fullCtx">{@code true} if the syntax error was identified during LL /// prediction; otherwise, {@code false} if the syntax error was identified /// during SLL prediction /// </param> public ErrorInfo(int decision, ATNConfigSet configs, ITokenStream input, int startIndex, int stopIndex, bool fullCtx) : base(decision, configs, input, startIndex, stopIndex, fullCtx) { }
/// <summary> /// Constructs a new instance of the /// <see cref="ContextSensitivityInfo"/> /// class /// with the specified detailed context sensitivity information. /// </summary> /// <param name="decision">The decision number</param> /// <param name="configs">The final configuration set identifying the ambiguous /// alternatives for the current input /// </param> /// <param name="input">The input token stream</param> /// <param name="startIndex">The start index for the current prediction</param> /// <param name="stopIndex"> /// The index at which the context sensitivity was /// identified during full-context prediction /// </param> public ContextSensitivityInfo(int decision, ATNConfigSet configs, ITokenStream input, int startIndex, int stopIndex) : base(decision, configs, input, startIndex, stopIndex, true) { }
public override void ReportAmbiguity(Parser recognizer, Antlr4.Runtime.Dfa.DFA dfa, int startIndex, int stopIndex, bool exact, Antlr4.Runtime.Sharpen.BitSet ambigAlts, Antlr4.Runtime.Atn.ATNConfigSet configs) { if (_captureDiagnostics) { _warningMessages.Add(string.Format("reportAmbiguity d={0}: ambigAlts={1}, input='{2}'", GetDecisionDescription(recognizer, dfa), GetConflictingAlts(ambigAlts, configs), ((ITokenStream)recognizer.InputStream).GetText(Interval.Of(startIndex, stopIndex)))); Debug.Log(string.Format("reportAmbiguity d={0}: ambigAlts={1}, input='{2}'", GetDecisionDescription(recognizer, dfa), GetConflictingAlts(ambigAlts, configs), ((ITokenStream)recognizer.InputStream).GetText(Interval.Of(startIndex, stopIndex)))); MyConsole.main.AppendText(string.Format("reportAmbiguity d={0}: ambigAlts={1}, input='{2}'", GetDecisionDescription(recognizer, dfa), GetConflictingAlts(ambigAlts, configs), ((ITokenStream)recognizer.InputStream).GetText(Interval.Of(startIndex, stopIndex)))); } }
protected override void ReportAttemptingFullContext(DFA dfa, BitSet conflictingAlts, ATNConfigSet configs, int startIndex, int stopIndex) { if (conflictingAlts != null) { conflictingAltResolvedBySLL = conflictingAlts.NextSetBit(0); } else { conflictingAltResolvedBySLL = configs.GetAlts().NextSetBit(0); } decisions[currentDecision].LL_Fallback++; base.ReportAttemptingFullContext(dfa, conflictingAlts, configs, startIndex, stopIndex); }
protected internal virtual DFAState AddDFAEdge([NotNull] DFAState from, int t, [NotNull] ATNConfigSet q) { /* leading to this call, ATNConfigSet.hasSemanticContext is used as a * marker indicating dynamic predicate evaluation makes this edge * dependent on the specific input sequence, so the static edge in the * DFA should be omitted. The target DFAState is still created since * execATN has the ability to resynchronize with the DFA state cache * following the predicate evaluation step. * * TJP notes: next time through the DFA, we see a pred again and eval. * If that gets us to a previously created (but dangling) DFA * state, we can continue in pure DFA mode from there. */ bool suppressEdge = q.HasSemanticContext; if (suppressEdge) { q.ClearExplicitSemanticContext(); } DFAState to = AddDFAState(q); if (suppressEdge) { return(to); } AddDFAEdge(from, t, to); return(to); }
protected internal virtual ATNConfig GetEpsilonTarget([NotNull] ICharStream input, [NotNull] ATNConfig config, [NotNull] Transition t, [NotNull] ATNConfigSet configs, bool speculative, bool treatEofAsEpsilon) { ATNConfig c; switch (t.TransitionType) { case TransitionType.Rule: { RuleTransition ruleTransition = (RuleTransition)t; if (optimize_tail_calls && ruleTransition.optimizedTailCall && !config.Context.HasEmpty) { c = config.Transform(t.target, true); } else { PredictionContext newContext = config.Context.GetChild(ruleTransition.followState.stateNumber); c = config.Transform(t.target, newContext, true); } break; } case TransitionType.Precedence: { throw new NotSupportedException("Precedence predicates are not supported in lexers."); } case TransitionType.Predicate: { /* Track traversing semantic predicates. If we traverse, * we cannot add a DFA state for this "reach" computation * because the DFA would not test the predicate again in the * future. Rather than creating collections of semantic predicates * like v3 and testing them on prediction, v4 will test them on the * fly all the time using the ATN not the DFA. This is slower but * semantically it's not used that often. One of the key elements to * this predicate mechanism is not adding DFA states that see * predicates immediately afterwards in the ATN. For example, * * a : ID {p1}? | ID {p2}? ; * * should create the start state for rule 'a' (to save start state * competition), but should not create target of ID state. The * collection of ATN states the following ID references includes * states reached by traversing predicates. Since this is when we * test them, we cannot cash the DFA state target of ID. */ PredicateTransition pt = (PredicateTransition)t; configs.MarkExplicitSemanticContext(); if (EvaluatePredicate(input, pt.ruleIndex, pt.predIndex, speculative)) { c = config.Transform(t.target, true); } else { c = null; } break; } case TransitionType.Action: { if (config.Context.HasEmpty) { // execute actions anywhere in the start rule for a token. // // TODO: if the entry rule is invoked recursively, some // actions may be executed during the recursive call. The // problem can appear when hasEmpty() is true but // isEmpty() is false. In this case, the config needs to be // split into two contexts - one with just the empty path // and another with everything but the empty path. // Unfortunately, the current algorithm does not allow // getEpsilonTarget to return two configurations, so // additional modifications are needed before we can support // the split operation. LexerActionExecutor lexerActionExecutor = LexerActionExecutor.Append(config.ActionExecutor, atn.lexerActions[((ActionTransition)t).actionIndex]); c = config.Transform(t.target, lexerActionExecutor, true); break; } else { // ignore actions in referenced rules c = config.Transform(t.target, true); break; } } case TransitionType.Epsilon: { c = config.Transform(t.target, true); break; } case TransitionType.Atom: case TransitionType.Range: case TransitionType.Set: { if (treatEofAsEpsilon) { if (t.Matches(IntStreamConstants.Eof, char.MinValue, char.MaxValue)) { c = config.Transform(t.target, false); break; } } c = null; break; } default: { c = null; break; } } return(c); }
/// <summary> /// Since the alternatives within any lexer decision are ordered by /// preference, this method stops pursuing the closure as soon as an accept /// state is reached. /// </summary> /// <remarks> /// Since the alternatives within any lexer decision are ordered by /// preference, this method stops pursuing the closure as soon as an accept /// state is reached. After the first accept state is reached by depth-first /// search from /// <paramref name="config"/> /// , all other (potentially reachable) states for /// this rule would have a lower priority. /// </remarks> /// <returns> /// /// <see langword="true"/> /// if an accept state is reached, otherwise /// <see langword="false"/> /// . /// </returns> protected internal virtual bool Closure([NotNull] ICharStream input, [NotNull] ATNConfig config, [NotNull] ATNConfigSet configs, bool currentAltReachedAcceptState, bool speculative, bool treatEofAsEpsilon) { if (config.State is RuleStopState) { PredictionContext context = config.Context; if (context.IsEmpty) { configs.Add(config); return(true); } else { if (context.HasEmpty) { configs.Add(config.Transform(config.State, PredictionContext.EmptyFull, true)); currentAltReachedAcceptState = true; } } for (int i = 0; i < context.Size; i++) { int returnStateNumber = context.GetReturnState(i); if (returnStateNumber == PredictionContext.EmptyFullStateKey) { continue; } PredictionContext newContext = context.GetParent(i); // "pop" return state ATNState returnState = atn.states[returnStateNumber]; ATNConfig c = config.Transform(returnState, newContext, false); currentAltReachedAcceptState = Closure(input, c, configs, currentAltReachedAcceptState, speculative, treatEofAsEpsilon); } return(currentAltReachedAcceptState); } // optimization if (!config.State.OnlyHasEpsilonTransitions) { if (!currentAltReachedAcceptState || !config.PassedThroughNonGreedyDecision) { configs.Add(config); } } ATNState p = config.State; for (int i_1 = 0; i_1 < p.NumberOfOptimizedTransitions; i_1++) { Transition t = p.GetOptimizedTransition(i_1); ATNConfig c = GetEpsilonTarget(input, config, t, configs, speculative, treatEofAsEpsilon); if (c != null) { currentAltReachedAcceptState = Closure(input, c, configs, currentAltReachedAcceptState, speculative, treatEofAsEpsilon); } } return(currentAltReachedAcceptState); }
/// <summary> /// Constructs a new instance of the /// <see cref="LookaheadEventInfo"/> /// class with /// the specified detailed lookahead information. /// </summary> /// <param name="decision">The decision number</param> /// <param name="configs">The final configuration set containing the necessary /// information to determine the result of a prediction, or {@code null} if /// the final configuration set is not available /// </param> /// <param name="predictedAlt"></param> /// <param name="input">The input token stream</param> /// <param name="startIndex">The start index for the current prediction</param> /// <param name="stopIndex">The index at which the prediction was finally made</param> /// <param name="fullCtx"> /// <see langword="true"/> /// if the current lookahead is part of an LL /// prediction; otherwise, /// <see langword="false"/> /// if the current lookahead is part of /// an SLL prediction /// </param> public LookaheadEventInfo(int decision, ATNConfigSet configs, int predictedAlt, ITokenStream input, int startIndex, int stopIndex, bool fullCtx) : base(decision, configs, input, startIndex, stopIndex, fullCtx) { this.predictedAlt = predictedAlt; }
protected internal virtual int FailOrAccept(LexerATNSimulator.SimState prevAccept, ICharStream input, ATNConfigSet reach, int t) { if (prevAccept.dfaState != null) { LexerActionExecutor lexerActionExecutor = prevAccept.dfaState.LexerActionExecutor; Accept(input, lexerActionExecutor, startIndex, prevAccept.index, prevAccept.line, prevAccept.charPos); return(prevAccept.dfaState.Prediction); } else { // if no accept and EOF is first char, return EOF if (t == IntStreamConstants.Eof && input.Index == startIndex) { return(TokenConstants.Eof); } throw new LexerNoViableAltException(recog, input, startIndex, reach); } }
/// <summary> /// Given a starting configuration set, figure out all ATN configurations /// we can reach upon input /// <paramref name="t"/> /// . Parameter /// <paramref name="reach"/> /// is a return /// parameter. /// </summary> protected internal virtual void GetReachableConfigSet(ICharStream input, ATNConfigSet closure, ATNConfigSet reach, int t) { // this is used to skip processing for configs which have a lower priority // than a config that already reached an accept state for the same rule int skipAlt = ATN.InvalidAltNumber; foreach (ATNConfig c in closure) { bool currentAltReachedAcceptState = c.Alt == skipAlt; if (currentAltReachedAcceptState && c.PassedThroughNonGreedyDecision) { continue; } int n = c.State.NumberOfOptimizedTransitions; for (int ti = 0; ti < n; ti++) { // for each optimized transition Transition trans = c.State.GetOptimizedTransition(ti); ATNState target = GetReachableTarget(trans, t); if (target != null) { LexerActionExecutor lexerActionExecutor = c.ActionExecutor; if (lexerActionExecutor != null) { lexerActionExecutor = lexerActionExecutor.FixOffsetBeforeMatch(input.Index - startIndex); } bool treatEofAsEpsilon = t == IntStreamConstants.Eof; if (Closure(input, c.Transform(target, lexerActionExecutor, true), reach, currentAltReachedAcceptState, true, treatEofAsEpsilon)) { // any remaining configs for this alt have a lower priority than // the one that just reached an accept state. skipAlt = c.Alt; break; } } } } }
public OrderedATNConfigSet(ATNConfigSet set, bool @readonly) : base(set, @readonly) { }
protected internal virtual ATNConfig GetEpsilonTarget(ICharStream input, ATNConfig config, Transition t, ATNConfigSet configs, bool speculative) { ATNConfig c; switch (t.TransitionType) { case TransitionType.Rule: { RuleTransition ruleTransition = (RuleTransition)t; if (optimize_tail_calls && ruleTransition.optimizedTailCall && !config.Context.HasEmpty) { c = config.Transform(t.target); } else { PredictionContext newContext = config.Context.GetChild(ruleTransition.followState .stateNumber); c = config.Transform(t.target, newContext); } break; } case TransitionType.Precedence: { throw new NotSupportedException("Precedence predicates are not supported in lexers." ); } case TransitionType.Predicate: { PredicateTransition pt = (PredicateTransition)t; configs.MarkExplicitSemanticContext(); if (EvaluatePredicate(input, pt.ruleIndex, pt.predIndex, speculative)) { c = config.Transform(t.target); } else { c = null; } break; } case TransitionType.Action: { // ignore actions; just exec one per rule upon accept c = config.Transform(t.target, ((ActionTransition)t).actionIndex); break; } case TransitionType.Epsilon: { c = config.Transform(t.target); break; } default: { c = null; break; } } return(c); }