void DefaultErrorStrategy::sync(Parser *recognizer) { atn::ATNState *s = recognizer->getInterpreter<atn::ATNSimulator>()->atn.states[recognizer->getState()]; // If already recovering, don't try to sync if (inErrorRecoveryMode(recognizer)) { return; } TokenStream *tokens = recognizer->getTokenStream(); size_t la = tokens->LA(1); // try cheaper subset first; might get lucky. seems to shave a wee bit off if (recognizer->getATN().nextTokens(s).contains(la) || la == Token::EOF) { return; } // Return but don't end recovery. only do that upon valid token match if (recognizer->isExpectedToken((int)la)) { return; } switch (s->getStateType()) { case atn::ATNState::BLOCK_START: case atn::ATNState::STAR_BLOCK_START: case atn::ATNState::PLUS_BLOCK_START: case atn::ATNState::STAR_LOOP_ENTRY: // report error and recover if possible if (singleTokenDeletion(recognizer) != nullptr) { return; } throw InputMismatchException(recognizer); case atn::ATNState::PLUS_LOOP_BACK: case atn::ATNState::STAR_LOOP_BACK: { reportUnwantedToken(recognizer); misc::IntervalSet expecting = recognizer->getExpectedTokens(); misc::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; } }