예제 #1
0
        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));
        }
예제 #2
0
 public LexerATNConfig(LexerATNConfig c, ATNState state,
                       PredictionContext context)
     : base(c, state, context, c.semanticContext)
 {
     this.lexerActionExecutor            = c.lexerActionExecutor;
     this.passedThroughNonGreedyDecision = checkNonGreedyDecision(c, state);
 }
예제 #3
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);
        }
예제 #4
0
 private static bool checkNonGreedyDecision(LexerATNConfig source, ATNState target)
 {
     return(source.passedThroughNonGreedyDecision ||
            target is DecisionState && ((DecisionState)target).nonGreedy);
 }
예제 #5
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)
                {
                    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);
        }
예제 #6
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)
            {
                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);
        }