public override 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 ////Console.WriteLine("2Consuming: " + recognizer.CurrentToken.Text); ////recognizer.Consume(); IntervalSet expecting = recognizer.GetExpectedTokens(); IntervalSet whatFollowsLoopIterationOrRule = expecting.Or(GetErrorRecoverySet(recognizer)); Console.WriteLine("From Recover"); ConsumeUntil(recognizer, whatFollowsLoopIterationOrRule); return(matchedSymbol); } // SINGLE TOKEN INSERTION if (SingleTokenInsertion(recognizer)) { return(GetMissingSymbol(recognizer)); } // even that didn't work; must throw the exception throw new InputMismatchException(recognizer); }
/// <summary> /// The default implementation of /// <see cref="IAntlrErrorStrategy.Sync(Parser)">IAntlrErrorStrategy.Sync(Parser)</see> /// makes sure /// that the current lookahead symbol is consistent with what were expecting /// at this point in the ATN. You can call this anytime but ANTLR only /// generates code to check before subrules/loops and each iteration. /// <p/> /// Implements Jim Idle's magic sync mechanism in closures and optional /// subrules. E.g., /// <pre> /// a : sync ( stuff sync )* ; /// sync : {consume to what can follow sync} ; /// </pre> /// At the start of a sub rule upon error, /// <see cref="Sync(Parser)">Sync(Parser)</see> /// performs single /// token deletion, if possible. If it can't do that, it bails on the current /// rule and uses the default error recovery, which consumes until the /// resynchronization set of the current rule. /// <p/> /// If the sub rule is optional ( /// <code>(...)?</code> /// , /// <code>(...)*</code> /// , or block /// with an empty alternative), then the expected set includes what follows /// the subrule. /// <p/> /// During loop iteration, it consumes until it sees a token that can start a /// sub rule or what follows loop. Yes, that is pretty aggressive. We opt to /// stay in the loop as long as possible. /// <p/> /// <strong>ORIGINS</strong> /// <p/> /// Previous versions of ANTLR did a poor job of their recovery within loops. /// A single mismatch token or missing token would force the parser to bail /// out of the entire rules surrounding the loop. So, for rule /// <pre> /// classDef : 'class' ID '{' member* '}' /// </pre> /// input with an extra token between members would force the parser to /// consume until it found the next class definition rather than the next /// member definition of the current class. /// <p/> /// This functionality cost a little bit of effort because the parser has to /// compare token set at the start of the loop and at each iteration. If for /// some reason speed is suffering for you, you can turn off this /// functionality by simply overriding this method as a blank { }. /// </summary> /// <exception cref="Antlr4.Runtime.RecognitionException"></exception> public virtual void Sync(Parser recognizer) { ATNState s = recognizer.Interpreter.atn.states[recognizer.State]; // System.err.println("sync @ "+s.stateNumber+"="+s.getClass().getSimpleName()); // If already recovering, don't try to sync if (InErrorRecoveryMode(recognizer)) { return; } ITokenStream tokens = ((ITokenStream)recognizer.InputStream); int la = tokens.La(1); // try cheaper subset first; might get lucky. seems to shave a wee bit off if (recognizer.Atn.NextTokens(s).Contains(la) || la == TokenConstants.Eof) { return; } // Return but don't end recovery. only do that upon valid token match if (recognizer.IsExpectedToken(la)) { return; } switch (s.StateType) { case StateType.BlockStart: case StateType.StarBlockStart: case StateType.PlusBlockStart: case StateType.StarLoopEntry: { // report error and recover if possible if (SingleTokenDeletion(recognizer) != null) { return; } throw new InputMismatchException(recognizer); } case StateType.PlusLoopBack: case StateType.StarLoopBack: { // System.err.println("at loop back: "+s.getClass().getSimpleName()); ReportUnwantedToken(recognizer); IntervalSet expecting = recognizer.GetExpectedTokens(); IntervalSet whatFollowsLoopIterationOrRule = expecting.Or(GetErrorRecoverySet(recognizer )); ConsumeUntil(recognizer, whatFollowsLoopIterationOrRule); break; } default: { // do nothing if we can't identify the exact kind of ATN state break; } } }
public override void Sync(Parser recognizer) { //Console.WriteLine("\t" + recognizer.CurrentToken.Text); ATNState s = recognizer.Interpreter.atn.states[recognizer.State]; // System.err.println("sync @ "+s.stateNumber+"="+s.getClass().getSimpleName()); // If already recovering, don't try to sync if (InErrorRecoveryMode(recognizer)) { return; } ITokenStream tokens = ((ITokenStream)recognizer.InputStream); int la = tokens.La(1); // try cheaper subset first; might get lucky. seems to shave a wee bit off var nextTokens = recognizer.Atn.NextTokens(s); if (nextTokens.Contains(TokenConstants.Epsilon) || nextTokens.Contains(la)) { return; } switch (s.StateType) { case StateType.BlockStart: case StateType.StarBlockStart: case StateType.PlusBlockStart: case StateType.StarLoopEntry: /*{ No special treatment for the first token * // report error and recover if possible * if (SingleTokenDeletion(recognizer) != null) { * return; * } * throw new InputMismatchException(recognizer); * }*/ case StateType.PlusLoopBack: case StateType.StarLoopBack: { // System.err.println("at loop back: "+s.getClass().getSimpleName()); //ReportUnwantedToken(recognizer); IntervalSet expecting = recognizer.GetExpectedTokens(); IntervalSet whatFollowsLoopIterationOrRule = expecting.Or(GetErrorRecoverySet(recognizer)); ConsumeUntil(recognizer, expecting); break; } default: { // do nothing if we can't identify the exact kind of ATN state break; } } }
/// <summary> /// The default implementation of /// <see cref="IAntlrErrorStrategy.Sync(Parser)"/> /// makes sure /// that the current lookahead symbol is consistent with what were expecting /// at this point in the ATN. You can call this anytime but ANTLR only /// generates code to check before subrules/loops and each iteration. /// <p>Implements Jim Idle's magic sync mechanism in closures and optional /// subrules. E.g.,</p> /// <pre> /// a : sync ( stuff sync )* ; /// sync : {consume to what can follow sync} ; /// </pre> /// At the start of a sub rule upon error, /// <see cref="Sync(Parser)"/> /// performs single /// token deletion, if possible. If it can't do that, it bails on the current /// rule and uses the default error recovery, which consumes until the /// resynchronization set of the current rule. /// <p>If the sub rule is optional ( /// <c>(...)?</c> /// , /// <c>(...)*</c> /// , or block /// with an empty alternative), then the expected set includes what follows /// the subrule.</p> /// <p>During loop iteration, it consumes until it sees a token that can start a /// sub rule or what follows loop. Yes, that is pretty aggressive. We opt to /// stay in the loop as long as possible.</p> /// <p><strong>ORIGINS</strong></p> /// <p>Previous versions of ANTLR did a poor job of their recovery within loops. /// A single mismatch token or missing token would force the parser to bail /// out of the entire rules surrounding the loop. So, for rule</p> /// <pre> /// classDef : 'class' ID '{' member* '}' /// </pre> /// input with an extra token between members would force the parser to /// consume until it found the next class definition rather than the next /// member definition of the current class. /// <p>This functionality cost a little bit of effort because the parser has to /// compare token set at the start of the loop and at each iteration. If for /// some reason speed is suffering for you, you can turn off this /// functionality by simply overriding this method as a blank { }.</p> /// </summary> /// <exception cref="Antlr4.Runtime.RecognitionException"/> public virtual void Sync(Parser recognizer) { ATNState s = recognizer.Interpreter.atn.states[recognizer.State]; // System.err.println("sync @ "+s.stateNumber+"="+s.getClass().getSimpleName()); // If already recovering, don't try to sync if (InErrorRecoveryMode(recognizer)) { return; } ITokenStream tokens = ((ITokenStream)recognizer.InputStream); int la = tokens.LA(1); // try cheaper subset first; might get lucky. seems to shave a wee bit off var nextTokens = recognizer.Atn.NextTokens(s); if (nextTokens.Contains(la)) { nextTokensContext = null; nextTokensState = ATNState.InvalidStateNumber; return; } if (nextTokens.Contains(TokenConstants.EPSILON)) { if (nextTokensContext == null) { // It's possible the next token won't match; information tracked // by sync is restricted for performance. nextTokensContext = recognizer.Context; nextTokensState = recognizer.State; } return; } switch (s.StateType) { case StateType.BlockStart: case StateType.StarBlockStart: case StateType.PlusBlockStart: case StateType.StarLoopEntry: { // report error and recover if possible if (SingleTokenDeletion(recognizer) != null) { return; } throw new InputMismatchException(recognizer); } case StateType.PlusLoopBack: case StateType.StarLoopBack: { // System.err.println("at loop back: "+s.getClass().getSimpleName()); ReportUnwantedToken(recognizer); IntervalSet expecting = recognizer.GetExpectedTokens(); IntervalSet whatFollowsLoopIterationOrRule = expecting.Or(GetErrorRecoverySet(recognizer)); ConsumeUntil(recognizer, whatFollowsLoopIterationOrRule); break; } default: { // do nothing if we can't identify the exact kind of ATN state break; } } }