Пример #1
0
        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;
        }
Пример #2
0
        // 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)
                    {
                        Console.WriteLine("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, char.MinValue, char.MaxValue))
                        {
                            c = new LexerATNConfig(config, t.target);
                            break;
                        }
                    }

                    break;
            }

            return c;
        }
Пример #3
0
        /**
         * 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)
            {
                Console.WriteLine("closure(" + config.ToString(recog, true) + ")");
            }

            if (config.state is RuleStopState)
            {
                if (debug)
                {
                    if (recog != null)
                    {
                        Console.WriteLine("closure at " + recog.RuleNames[config.state.ruleIndex] + " rule stop " + config);
                    }
                    else {
                        Console.WriteLine("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;
        }