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); }
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); }
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); }