/// <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; } } }
protected override DFAState CreateDFAState(DFA dfa, ATNConfigSet configs) { int t = _input.La(1); if (t == AntlrV4.CaretToken.CaretTokenType && !_computingStartState) { _caretToken = (ICaretToken)_input.Lt(1); throw NoViableAlt(_input, _outerContext, configs, _startIndex); } return(base.CreateDFAState(dfa, configs)); }
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; } } }
public override void Recover(Parser recognizer, RecognitionException e) { // This should should move the current position to the next 'END' token base.Recover(recognizer, e); ITokenStream tokenStream = (ITokenStream)recognizer.InputStream; // Verify we are where we expect to be if (tokenStream.La(1) == MyGrammarParser.END) { // Get the next possible tokens IntervalSet intervalSet = GetErrorRecoverySet(recognizer); // Move to the next token tokenStream.Consume(); // Move to the next possible token // If the errant element is the last in the set, this will move to the 'END' token in 'END MODULE'. // If there are subsequent elements in the set, this will move to the 'BEGIN' token in 'BEGIN module_element'. ConsumeUntil(recognizer, intervalSet); } }
/// <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 IntervalSet nextTokens = recognizer.Atn.NextTokens(s); //if (nextTokens.Contains(TokenConstants.Epsilon) || nextTokens.Contains(la)) if (nextTokens.Contains(la)) { // We are sure the token matches 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; } } }