public override bool Equals(ATNConfig other) { if (this == other) { return(true); } else if (!(other is LexerATNConfig)) { return(false); } LexerATNConfig lexerOther = (LexerATNConfig)other; if (passedThroughNonGreedyDecision != lexerOther.passedThroughNonGreedyDecision) { return(false); } if (!(lexerActionExecutor == null ? lexerOther.lexerActionExecutor == null : lexerActionExecutor.Equals(lexerOther.lexerActionExecutor))) { return(false); } return(base.Equals(other)); }
public LexerATNConfig(LexerATNConfig c, ATNState state, PredictionContext context) : base(c, state, context, c.semanticContext) { this.lexerActionExecutor = c.lexerActionExecutor; this.passedThroughNonGreedyDecision = checkNonGreedyDecision(c, state); }
protected ATNConfigSet ComputeStartState(ICharStream input, ATNState p) { PredictionContext initialContext = PredictionContext.EMPTY; ATNConfigSet configs = new OrderedATNConfigSet(); for (int i = 0; i < p.NumberOfTransitions; i++) { ATNState target = p.Transition(i).target; LexerATNConfig c = new LexerATNConfig(target, i + 1, initialContext); Closure(input, c, configs, false, false, false); } return(configs); }
private static bool checkNonGreedyDecision(LexerATNConfig source, ATNState target) { return(source.passedThroughNonGreedyDecision || target is DecisionState && ((DecisionState)target).nonGreedy); }
// 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); }