Ejemplo n.º 1
0
        /// <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(ICharStream input, ATNConfig config, 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);
        }
Ejemplo n.º 2
0
        /// <summary>Computes the SLL prediction termination condition.</summary>
        /// <remarks>
        /// Computes the SLL prediction termination condition.
        /// <p>
        /// This method computes the SLL prediction termination condition for both of
        /// the following cases.</p>
        /// <ul>
        /// <li>The usual SLL+LL fallback upon SLL conflict</li>
        /// <li>Pure SLL without LL fallback</li>
        /// </ul>
        /// <p><strong>COMBINED SLL+LL PARSING</strong></p>
        /// <p>When LL-fallback is enabled upon SLL conflict, correct predictions are
        /// ensured regardless of how the termination condition is computed by this
        /// method. Due to the substantially higher cost of LL prediction, the
        /// prediction should only fall back to LL when the additional lookahead
        /// cannot lead to a unique SLL prediction.</p>
        /// <p>Assuming combined SLL+LL parsing, an SLL configuration set with only
        /// conflicting subsets should fall back to full LL, even if the
        /// configuration sets don't resolve to the same alternative (e.g.
        /// <c/>
        ///
        /// 1,2}} and
        /// <c/>
        ///
        /// 3,4}}. If there is at least one non-conflicting
        /// configuration, SLL could continue with the hopes that more lookahead will
        /// resolve via one of those non-conflicting configurations.</p>
        /// <p>Here's the prediction termination rule them: SLL (for SLL+LL parsing)
        /// stops when it sees only conflicting configuration subsets. In contrast,
        /// full LL keeps going when there is uncertainty.</p>
        /// <p><strong>HEURISTIC</strong></p>
        /// <p>As a heuristic, we stop prediction when we see any conflicting subset
        /// unless we see a state that only has one alternative associated with it.
        /// The single-alt-state thing lets prediction continue upon rules like
        /// (otherwise, it would admit defeat too soon):</p>
        /// <p>
        /// <c>[12|1|[], 6|2|[], 12|2|[]]. s : (ID | ID ID?) ';' ;</c>
        /// </p>
        /// <p>When the ATN simulation reaches the state before
        /// <c>';'</c>
        /// , it has a
        /// DFA state that looks like:
        /// <c>[12|1|[], 6|2|[], 12|2|[]]</c>
        /// . Naturally
        /// <c>12|1|[]</c>
        /// and
        /// <c>12|2|[]</c>
        /// conflict, but we cannot stop
        /// processing this node because alternative to has another way to continue,
        /// via
        /// <c>[6|2|[]]</c>
        /// .</p>
        /// <p>It also let's us continue for this rule:</p>
        /// <p>
        /// <c>[1|1|[], 1|2|[], 8|3|[]] a : A | A | A B ;</c>
        /// </p>
        /// <p>After matching input A, we reach the stop state for rule A, state 1.
        /// State 8 is the state right before B. Clearly alternatives 1 and 2
        /// conflict and no amount of further lookahead will separate the two.
        /// However, alternative 3 will be able to continue and so we do not stop
        /// working on this state. In the previous example, we're concerned with
        /// states associated with the conflicting alternatives. Here alt 3 is not
        /// associated with the conflicting configs, but since we can continue
        /// looking for input reasonably, don't declare the state done.</p>
        /// <p><strong>PURE SLL PARSING</strong></p>
        /// <p>To handle pure SLL parsing, all we have to do is make sure that we
        /// combine stack contexts for configurations that differ only by semantic
        /// predicate. From there, we can do the usual SLL termination heuristic.</p>
        /// <p><strong>PREDICATES IN SLL+LL PARSING</strong></p>
        /// <p>SLL decisions don't evaluate predicates until after they reach DFA stop
        /// states because they need to create the DFA cache that works in all
        /// semantic situations. In contrast, full LL evaluates predicates collected
        /// during start state computation so it can ignore predicates thereafter.
        /// This means that SLL termination detection can totally ignore semantic
        /// predicates.</p>
        /// <p>Implementation-wise,
        /// <see cref="ATNConfigSet"/>
        /// combines stack contexts but not
        /// semantic predicate contexts so we might see two configurations like the
        /// following.</p>
        /// <p>
        /// <c/>
        /// (s, 1, x,
        /// ), (s, 1, x', {p})}</p>
        /// <p>Before testing these configurations against others, we have to merge
        /// <c>x</c>
        /// and
        /// <c>x'</c>
        /// (without modifying the existing configurations).
        /// For example, we test
        /// <c>(x+x')==x''</c>
        /// when looking for conflicts in
        /// the following configurations.</p>
        /// <p>
        /// <c/>
        /// (s, 1, x,
        /// ), (s, 1, x', {p}), (s, 2, x'', {})}</p>
        /// <p>If the configuration set has predicates (as indicated by
        /// <see cref="ATNConfigSet.hasSemanticContext"/>
        /// ), this algorithm makes a copy of
        /// the configurations to strip out all of the predicates so that a standard
        /// <see cref="ATNConfigSet"/>
        /// will merge everything ignoring predicates.</p>
        /// </remarks>
        public static bool HasSLLConflictTerminatingPrediction(PredictionMode mode, ATNConfigSet configSet)
        {
            if (AllConfigsInRuleStopStates(configSet.configs))
            {
                return(true);
            }
            // pure SLL mode parsing
            if (mode == PredictionMode.SLL)
            {
                // Don't bother with combining configs from different semantic
                // contexts if we can fail over to full LL; costs more time
                // since we'll often fail over anyway.
                if (configSet.hasSemanticContext)
                {
                    // dup configs, tossing out semantic predicates
                    ATNConfigSet dup = new ATNConfigSet();
                    foreach (ATNConfig c in configSet.configs)
                    {
                        dup.Add(new ATNConfig(c, SemanticContext.NONE));
                    }
                    configSet = dup;
                }
            }
            // now we have combined contexts for configs with dissimilar preds
            // pure SLL or combined SLL+LL mode parsing
            ICollection <BitSet> altsets = GetConflictingAltSubsets(configSet.configs);
            bool heuristic = HasConflictingAltSet(altsets) && !HasStateAssociatedWithOneAlt(configSet.configs);

            return(heuristic);
        }
Ejemplo n.º 3
0
        /// <summary>Computes the SLL prediction termination condition.</summary>
        /// <remarks>
        /// Computes the SLL prediction termination condition.
        /// <p>
        /// This method computes the SLL prediction termination condition for both of
        /// the following cases.</p>
        /// <ul>
        /// <li>The usual SLL+LL fallback upon SLL conflict</li>
        /// <li>Pure SLL without LL fallback</li>
        /// </ul>
        /// <p><strong>COMBINED SLL+LL PARSING</strong></p>
        /// <p>When LL-fallback is enabled upon SLL conflict, correct predictions are
        /// ensured regardless of how the termination condition is computed by this
        /// method. Due to the substantially higher cost of LL prediction, the
        /// prediction should only fall back to LL when the additional lookahead
        /// cannot lead to a unique SLL prediction.</p>
        /// <p>Assuming combined SLL+LL parsing, an SLL configuration set with only
        /// conflicting subsets should fall back to full LL, even if the
        /// configuration sets don't resolve to the same alternative (e.g.
        /// <c/>
        ///
        /// 1,2}} and
        /// <c/>
        ///
        /// 3,4}}. If there is at least one non-conflicting
        /// configuration, SLL could continue with the hopes that more lookahead will
        /// resolve via one of those non-conflicting configurations.</p>
        /// <p>Here's the prediction termination rule them: SLL (for SLL+LL parsing)
        /// stops when it sees only conflicting configuration subsets. In contrast,
        /// full LL keeps going when there is uncertainty.</p>
        /// <p><strong>HEURISTIC</strong></p>
        /// <p>As a heuristic, we stop prediction when we see any conflicting subset
        /// unless we see a state that only has one alternative associated with it.
        /// The single-alt-state thing lets prediction continue upon rules like
        /// (otherwise, it would admit defeat too soon):</p>
        /// <p>
        /// <c>[12|1|[], 6|2|[], 12|2|[]]. s : (ID | ID ID?) ';' ;</c>
        /// </p>
        /// <p>When the ATN simulation reaches the state before
        /// <c>';'</c>
        /// , it has a
        /// DFA state that looks like:
        /// <c>[12|1|[], 6|2|[], 12|2|[]]</c>
        /// . Naturally
        /// <c>12|1|[]</c>
        /// and
        /// <c>12|2|[]</c>
        /// conflict, but we cannot stop
        /// processing this node because alternative to has another way to continue,
        /// via
        /// <c>[6|2|[]]</c>
        /// .</p>
        /// <p>It also let's us continue for this rule:</p>
        /// <p>
        /// <c>[1|1|[], 1|2|[], 8|3|[]] a : A | A | A B ;</c>
        /// </p>
        /// <p>After matching input A, we reach the stop state for rule A, state 1.
        /// State 8 is the state right before B. Clearly alternatives 1 and 2
        /// conflict and no amount of further lookahead will separate the two.
        /// However, alternative 3 will be able to continue and so we do not stop
        /// working on this state. In the previous example, we're concerned with
        /// states associated with the conflicting alternatives. Here alt 3 is not
        /// associated with the conflicting configs, but since we can continue
        /// looking for input reasonably, don't declare the state done.</p>
        /// <p><strong>PURE SLL PARSING</strong></p>
        /// <p>To handle pure SLL parsing, all we have to do is make sure that we
        /// combine stack contexts for configurations that differ only by semantic
        /// predicate. From there, we can do the usual SLL termination heuristic.</p>
        /// <p><strong>PREDICATES IN SLL+LL PARSING</strong></p>
        /// <p>SLL decisions don't evaluate predicates until after they reach DFA stop
        /// states because they need to create the DFA cache that works in all
        /// semantic situations. In contrast, full LL evaluates predicates collected
        /// during start state computation so it can ignore predicates thereafter.
        /// This means that SLL termination detection can totally ignore semantic
        /// predicates.</p>
        /// <p>Implementation-wise,
        /// <see cref="ATNConfigSet"/>
        /// combines stack contexts but not
        /// semantic predicate contexts so we might see two configurations like the
        /// following.</p>
        /// <p>
        /// <c/>
        /// (s, 1, x,
        /// ), (s, 1, x', {p})}</p>
        /// <p>Before testing these configurations against others, we have to merge
        /// <c>x</c>
        /// and
        /// <c>x'</c>
        /// (without modifying the existing configurations).
        /// For example, we test
        /// <c>(x+x')==x''</c>
        /// when looking for conflicts in
        /// the following configurations.</p>
        /// <p>
        /// <c/>
        /// (s, 1, x,
        /// ), (s, 1, x', {p}), (s, 2, x'', {})}</p>
        /// <p>If the configuration set has predicates (as indicated by
        /// <see cref="ATNConfigSet.HasSemanticContext()"/>
        /// ), this algorithm makes a copy of
        /// the configurations to strip out all of the predicates so that a standard
        /// <see cref="ATNConfigSet"/>
        /// will merge everything ignoring predicates.</p>
        /// </remarks>
        public static bool HasSLLConflictTerminatingPrediction(PredictionMode mode, [NotNull] ATNConfigSet configs)
        {
            /* Configs in rule stop states indicate reaching the end of the decision
             * rule (local context) or end of start rule (full context). If all
             * configs meet this condition, then none of the configurations is able
             * to match additional input so we terminate prediction.
             */
            if (AllConfigsInRuleStopStates(configs))
            {
                return(true);
            }
            // pure SLL mode parsing
            if (mode == PredictionMode.Sll)
            {
                // Don't bother with combining configs from different semantic
                // contexts if we can fail over to full LL; costs more time
                // since we'll often fail over anyway.
                if (configs.HasSemanticContext)
                {
                    // dup configs, tossing out semantic predicates
                    ATNConfigSet dup = new ATNConfigSet();
                    foreach (ATNConfig c in configs)
                    {
                        ATNConfig config = c.Transform(c.State, SemanticContext.None, false);
                        dup.Add(c);
                    }
                    configs = dup;
                }
            }
            // now we have combined contexts for configs with dissimilar preds
            // pure SLL or combined SLL+LL mode parsing
            ICollection <BitSet> altsets = GetConflictingAltSubsets(configs);
            bool heuristic = HasConflictingAltSet(altsets) && !HasStateAssociatedWithOneAlt(configs);

            return(heuristic);
        }
Ejemplo n.º 4
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);
        }