/// <summary>
        /// This method implements the single-token insertion inline error recovery
        /// strategy.
        /// </summary>
        /// <remarks>
        /// This method implements the single-token insertion inline error recovery
        /// strategy. It is called by
        /// <see cref="RecoverInline(Parser)"/>
        /// if the single-token
        /// deletion strategy fails to recover from the mismatched input. If this
        /// method returns
        /// <see langword="true"/>
        /// ,
        /// <paramref name="recognizer"/>
        /// will be in error recovery
        /// mode.
        /// <p>This method determines whether or not single-token insertion is viable by
        /// checking if the
        /// <c>LA(1)</c>
        /// input symbol could be successfully matched
        /// if it were instead the
        /// <c>LA(2)</c>
        /// symbol. If this method returns
        /// <see langword="true"/>
        /// , the caller is responsible for creating and inserting a
        /// token with the correct type to produce this behavior.</p>
        /// </remarks>
        /// <param name="recognizer">the parser instance</param>
        /// <returns>
        ///
        /// <see langword="true"/>
        /// if single-token insertion is a viable recovery
        /// strategy for the current mismatched input, otherwise
        /// <see langword="false"/>
        /// </returns>
        protected internal virtual bool SingleTokenInsertion(Parser recognizer)
        {
            int currentSymbolType = ((ITokenStream)recognizer.InputStream).La(1);
            // if current token is consistent with what could come after current
            // ATN state, then we know we're missing a token; error recovery
            // is free to conjure up and insert the missing token
            ATNState    currentState   = recognizer.Interpreter.atn.states[recognizer.State];
            ATNState    next           = currentState.Transition(0).target;
            ATN         atn            = recognizer.Interpreter.atn;
            IntervalSet expectingAtLL2 = atn.NextTokens(next, PredictionContext.FromRuleContext(atn, recognizer.RuleContext));

            //		System.out.println("LT(2) set="+expectingAtLL2.toString(recognizer.getTokenNames()));
            if (expectingAtLL2.Contains(currentSymbolType))
            {
                ReportMissingToken(recognizer);
                return(true);
            }
            return(false);
        }
Exemple #2
0
        public override IToken RecoverInline(Parser recognizer)
        {
            if (recognizer is ICodeCompletionParser &&
                ((ITokenStream)recognizer.InputStream).Lt(1) is ICaretToken)
            {
                ICodeCompletionParser parser = (ICodeCompletionParser)recognizer;
                ICaretToken           token  = (ICaretToken)((ITokenStream)recognizer.InputStream).Lt(1);

                CompletionParserATNSimulator interp = parser.Interpreter;
                int      stateNumber = recognizer.State;
                ATNState state       = interp.atn.states[stateNumber];

                PredictionContext context      = PredictionContext.FromRuleContext(interp.atn, recognizer.Context, false);
                ATNConfigSet      intermediate = new ATNConfigSet();
                ATNConfigSet      closure      = new ATNConfigSet();
                for (int i = 0; i < state.NumberOfTransitions; i++)
                {
                    Transition transition = state.Transition(i);
                    if (transition.IsEpsilon)
                    {
                        ATNState  target = transition.target;
                        ATNConfig config = ATNConfig.Create(target, i + 1, context);
                        intermediate.Add(config);
                    }
                }

                bool collectPredicates = false;
                bool hasMoreContext    = true;
                interp.ClosureHelper(intermediate, closure, collectPredicates, hasMoreContext, PredictionContextCache.Uncached, false);

                if (!state.OnlyHasEpsilonTransitions)
                {
                    for (int i = 0; i < state.NumberOfTransitions; i++)
                    {
                        closure.Add(ATNConfig.Create(state, i + 1, PredictionContext.FromRuleContext(interp.atn, recognizer.Context)));
                    }
                }

                Dictionary <ATNConfig, IList <Transition> > transitions = null;
                int ncl = closure.Count;
                // TODO: foreach
                for (int ci = 0; ci < ncl; ci++)
                {
                    ATNConfig c = closure[ci];

                    List <Transition> configTransitions = null;

                    int n = c.State.NumberOfTransitions;
                    for (int ti = 0; ti < n; ti++)
                    {               // for each transition
                        Transition trans  = c.State.Transition(ti);
                        ATNState   target = interp.GetReachableTargetHelper(c, trans, CaretToken.CaretTokenType);
                        if (target != null)
                        {
                            if (transitions == null)
                            {
                                transitions = new Dictionary <ATNConfig, IList <Transition> >();
                            }

                            if (configTransitions == null)
                            {
                                configTransitions = new List <Transition>();
                                transitions[c]    = configTransitions;
                            }

                            configTransitions.Add(trans);
                        }
                    }
                }

                /*
                 * This should be null if the intended token is not "wordlike", and
                 * should be a single transition from the current state.
                 */
                if (transitions != null)
                {
                    Debug.Assert(transitions.Count == 1);
                    Debug.Assert(transitions.Values.First().Count == 1);
                    Debug.Assert(state.NumberOfTransitions == 1);
                    Debug.Assert(transitions.Values.First()[0] == state.Transition(0));
                }

                throw new CaretReachedException(parser.Context, token, transitions, null);
            }

            return(base.RecoverInline(recognizer));
        }