Antlr4.Runtime.Atn.ParserATNSimulator.ComputeReachSet C# (CSharp) Method

ComputeReachSet() protected method

protected ComputeReachSet ( ATNConfigSet closure, int t, bool fullCtx ) : ATNConfigSet
closure ATNConfigSet
t int
fullCtx bool
return ATNConfigSet
        protected virtual ATNConfigSet ComputeReachSet(ATNConfigSet closure, int t, bool fullCtx)
        {
            if (debug)
                Console.WriteLine("in computeReachSet, starting closure: " + closure);

            if (mergeCache == null)
            {
                mergeCache = new MergeCache();
            }

            ATNConfigSet intermediate = new ATNConfigSet(fullCtx);

            /* Configurations already in a rule stop state indicate reaching the end
             * of the decision rule (local context) or end of the start rule (full
             * context). Once reached, these configurations are never updated by a
             * closure operation, so they are handled separately for the performance
             * advantage of having a smaller intermediate set when calling closure.
             *
             * For full-context reach operations, separate handling is required to
             * ensure that the alternative matching the longest overall sequence is
             * chosen when multiple such configurations can match the input.
             */
            List<ATNConfig> skippedStopStates = null;

            // First figure out where we can reach on input t
            foreach (ATNConfig c in closure.configs)
            {
                if (debug) Console.WriteLine("testing " + GetTokenName(t) + " at " + c.ToString());

                if (c.state is RuleStopState)
                {
                    if (fullCtx || t == IntStreamConstants.EOF)
                    {
                        if (skippedStopStates == null)
                        {
                            skippedStopStates = new List<ATNConfig>();
                        }

                        skippedStopStates.Add(c);
                    }

                    continue;
                }

                int n = c.state.NumberOfTransitions;
                for (int ti = 0; ti < n; ti++)
                {               // for each transition
                    Transition trans = c.state.Transition(ti);
                    ATNState target = GetReachableTarget(trans, t);
                    if (target != null)
                    {
                        intermediate.Add(new ATNConfig(c, target), mergeCache);
                    }
                }
            }

            // Now figure out where the reach operation can take us...

            ATNConfigSet reach = null;

            /* This block optimizes the reach operation for intermediate sets which
             * trivially indicate a termination state for the overall
             * adaptivePredict operation.
             *
             * The conditions assume that intermediate
             * contains all configurations relevant to the reach set, but this
             * condition is not true when one or more configurations have been
             * withheld in skippedStopStates, or when the current symbol is EOF.
             */
            if (skippedStopStates == null && t != TokenConstants.EOF)
            {
                if (intermediate.Count == 1)
                {
                    // Don't pursue the closure if there is just one state.
                    // It can only have one alternative; just add to result
                    // Also don't pursue the closure if there is unique alternative
                    // among the configurations.
                    reach = intermediate;
                }
                else if (GetUniqueAlt(intermediate) != ATN.INVALID_ALT_NUMBER)
                {
                    // Also don't pursue the closure if there is unique alternative
                    // among the configurations.
                    reach = intermediate;
                }
            }

            /* If the reach set could not be trivially determined, perform a closure
             * operation on the intermediate set to compute its initial value.
             */
            if (reach == null)
            {
                reach = new ATNConfigSet(fullCtx);
                HashSet<ATNConfig> closureBusy = new HashSet<ATNConfig>();
                bool treatEofAsEpsilon = t == TokenConstants.EOF;
                foreach (ATNConfig c in intermediate.configs)
                {
                    Closure(c, reach, closureBusy, false, fullCtx, treatEofAsEpsilon);
                }
            }

            if (t == IntStreamConstants.EOF)
            {
                /* After consuming EOF no additional input is possible, so we are
                 * only interested in configurations which reached the end of the
                 * decision rule (local context) or end of the start rule (full
                 * context). Update reach to contain only these configurations. This
                 * handles both explicit EOF transitions in the grammar and implicit
                 * EOF transitions following the end of the decision or start rule.
                 *
                 * When reach==intermediate, no closure operation was performed. In
                 * this case, removeAllConfigsNotInRuleStopState needs to check for
                 * reachable rule stop states as well as configurations already in
                 * a rule stop state.
                 *
                 * This is handled before the configurations in skippedStopStates,
                 * because any configurations potentially added from that list are
                 * already guaranteed to meet this condition whether or not it's
                 * required.
                 */
                reach = RemoveAllConfigsNotInRuleStopState(reach, reach == intermediate);
            }

            /* If skippedStopStates is not null, then it contains at least one
             * configuration. For full-context reach operations, these
             * configurations reached the end of the start rule, in which case we
             * only add them back to reach if no configuration during the current
             * closure operation reached such a state. This ensures adaptivePredict
             * chooses an alternative matching the longest overall sequence when
             * multiple alternatives are viable.
             */
            if (skippedStopStates != null && (!fullCtx || !PredictionMode.HasConfigInRuleStopState(reach.configs)))
            {
                foreach (ATNConfig c in skippedStopStates)
                {
                    reach.Add(c, mergeCache);
                }
            }

            if (reach.Empty)
                return null;
            return reach;
        }