/// <summary> /// <inheritDoc/> /// <p>The default implementation resynchronizes the parser by consuming tokens /// until we find one in the resynchronization set--loosely the set of tokens /// that can follow the current rule.</p> /// </summary> public virtual void Recover(Parser recognizer, RecognitionException e) { // System.out.println("recover in "+recognizer.getRuleInvocationStack()+ // " index="+recognizer.getInputStream().index()+ // ", lastErrorIndex="+ // lastErrorIndex+ // ", states="+lastErrorStates); if (lastErrorIndex == ((ITokenStream)recognizer.InputStream).Index && lastErrorStates != null && lastErrorStates.Contains(recognizer.State)) { // uh oh, another error at same token index and previously-visited // state in ATN; must be a case where LT(1) is in the recovery // token set so nothing got consumed. Consume a single token // at least to prevent an infinite loop; this is a failsafe. // System.err.println("seen error condition before index="+ // lastErrorIndex+", states="+lastErrorStates); // System.err.println("FAILSAFE consumes "+recognizer.getTokenNames()[recognizer.getInputStream().LA(1)]); recognizer.Consume(); } lastErrorIndex = ((ITokenStream)recognizer.InputStream).Index; if (lastErrorStates == null) { lastErrorStates = new IntervalSet(); } lastErrorStates.Add(recognizer.State); IntervalSet followSet = GetErrorRecoverySet(recognizer); ConsumeUntil(recognizer, followSet); }
protected internal virtual IToken SingleTokenDeletion([NotNull] Parser recognizer) { int nextTokenType = ((ITokenStream)recognizer.InputStream).La(2); IntervalSet expecting = GetExpectedTokens(recognizer); if (expecting.Contains(nextTokenType)) { ReportUnwantedToken(recognizer); /* * System.err.println("recoverFromMismatchedToken deleting "+ * ((TokenStream)recognizer.getInputStream()).LT(1)+ * " since "+((TokenStream)recognizer.getInputStream()).LT(2)+ * " is what we want"); */ recognizer.Consume(); // simply delete extra token // we want to return the token we're actually matching IToken matchedSymbol = recognizer.CurrentToken; ReportMatch(recognizer); // we know current token is correct return(matchedSymbol); } return(null); }
/// <summary> /// <inheritDoc/> /// <p>The default implementation attempts to recover from the mismatched input /// by using single token insertion and deletion as described below. If the /// recovery attempt fails, this method throws an /// <see cref="InputMismatchException"/> /// .</p> /// <p><strong>EXTRA TOKEN</strong> (single token deletion)</p> /// <p> /// <c>LA(1)</c> /// is not what we are looking for. If /// <c>LA(2)</c> /// has the /// right token, however, then assume /// <c>LA(1)</c> /// is some extra spurious /// token and delete it. Then consume and return the next token (which was /// the /// <c>LA(2)</c> /// token) as the successful result of the match operation.</p> /// <p>This recovery strategy is implemented by /// <see cref="SingleTokenDeletion(Parser)"/> /// .</p> /// <p><strong>MISSING TOKEN</strong> (single token insertion)</p> /// <p>If current token (at /// <c>LA(1)</c> /// ) is consistent with what could come /// after the expected /// <c>LA(1)</c> /// token, then assume the token is missing /// and use the parser's /// <see cref="ITokenFactory"/> /// to create it on the fly. The /// "insertion" is performed by returning the created token as the successful /// result of the match operation.</p> /// <p>This recovery strategy is implemented by /// <see cref="SingleTokenInsertion(Parser)"/> /// .</p> /// <p><strong>EXAMPLE</strong></p> /// <p>For example, Input /// <c>i=(3;</c> /// is clearly missing the /// <c>')'</c> /// . When /// the parser returns from the nested call to /// <c>expr</c> /// , it will have /// call chain:</p> /// <pre> /// stat → expr → atom /// </pre> /// and it will be trying to match the /// <c>')'</c> /// at this point in the /// derivation: /// <pre> /// => ID '=' '(' INT ')' ('+' atom)* ';' /// ^ /// </pre> /// The attempt to match /// <c>')'</c> /// will fail when it sees /// <c>';'</c> /// and /// call /// <see cref="RecoverInline(Parser)"/> /// . To recover, it sees that /// <c>LA(1)==';'</c> /// is in the set of tokens that can follow the /// <c>')'</c> /// token reference /// in rule /// <c>atom</c> /// . It can assume that you forgot the /// <c>')'</c> /// . /// </summary> /// <exception cref="Antlr4.Runtime.RecognitionException"/> public virtual IToken RecoverInline(Parser recognizer) { // SINGLE TOKEN DELETION IToken matchedSymbol = SingleTokenDeletion(recognizer); if (matchedSymbol != null) { // we have deleted the extra token. // now, move past ttype token as if all were ok recognizer.Consume(); return(matchedSymbol); } // SINGLE TOKEN INSERTION if (SingleTokenInsertion(recognizer)) { return(GetMissingSymbol(recognizer)); } // even that didn't work; must throw the exception //throw new InputMismatchException(recognizer); InputMismatchException e; if (nextTokensContext == null) { e = new InputMismatchException(recognizer); } else { e = new InputMismatchException(recognizer, nextTokensState, nextTokensContext); } throw e; }
/// <summary>Consume tokens until one matches the given token set.</summary> /// <remarks>Consume tokens until one matches the given token set.</remarks> protected internal virtual void ConsumeUntil(Parser recognizer, IntervalSet set) { // System.err.println("consumeUntil("+set.toString(recognizer.getTokenNames())+")"); int ttype = ((ITokenStream)recognizer.InputStream).La(1); while (ttype != TokenConstants.Eof && !set.Contains(ttype)) { //System.out.println("consume during recover LA(1)="+getTokenNames()[input.LA(1)]); // recognizer.getInputStream().consume(); recognizer.Consume(); ttype = ((ITokenStream)recognizer.InputStream).La(1); } }
/// <summary> /// Multiple token deletion resynchronization strategy /// </summary> protected override void ConsumeUntil(Antlr4.Runtime.Parser recognizer, IntervalSet set) { Token lastConsumedToken = (Token)((ITokenStream)recognizer.InputStream).Lt(-1); Token nextToken = (Token)((ITokenStream)recognizer.InputStream).Lt(1); int ttype = nextToken.Type; while (ttype != TokenConstants.Eof && !set.Contains(ttype) && !ErrorStrategyShouldNotConsumeThisToken(lastConsumedToken, nextToken)) { recognizer.Consume(); lastConsumedToken = nextToken; nextToken = (Token)((ITokenStream)recognizer.InputStream).Lt(1); ttype = nextToken.Type; } }
protected internal virtual IToken SingleTokenDeletion(Parser recognizer) { int nextTokenType = ((ITokenStream)recognizer.InputStream).La(2); IntervalSet expecting = GetExpectedTokens(recognizer); if (expecting.Contains(nextTokenType)) { ReportUnwantedToken(recognizer); recognizer.Consume(); // simply delete extra token // we want to return the token we're actually matching IToken matchedSymbol = recognizer.CurrentToken; ReportMatch(recognizer); // we know current token is correct return(matchedSymbol); } return(null); }
protected override void ConsumeUntil(Antlr4.Runtime.Parser recognizer, IntervalSet set) { int tokenType = ((ITokenStream)recognizer.InputStream).La(1); int indents = 1; while (tokenType != TokenConstants.Eof && indents > 0) { recognizer.Consume(); tokenType = ((ITokenStream)recognizer.InputStream).La(1); if (tokenType == MalinaLexer.INDENT) { indents++; } if (tokenType == MalinaLexer.DEDENT) { indents--; } } }
public override void Recover(Antlr4.Runtime.Parser recognizer, RecognitionException e) { int tokenType = ((ITokenStream)recognizer.InputStream).La(1); int indents = 1; while (tokenType != TokenConstants.Eof && indents > 0) { recognizer.Consume(); tokenType = ((ITokenStream)recognizer.InputStream).La(1); if (tokenType == MalinaLexer.INDENT) { indents++; } if (tokenType == MalinaLexer.DEDENT) { indents--; } } }