/** This code is factored out from mismatched token and mismatched set * recovery. It handles "single token insertion" error recovery for * both. No tokens are consumed to recover from insertions. Return * true if recovery was possible else return false. */ static ANTLR3_BOOLEAN recoverFromMismatchedElement (pANTLR3_BASE_RECOGNIZER recognizer, pANTLR3_BITSET follow) { pANTLR3_BITSET viableToksFollowingRule; pANTLR3_BITSET newFollow; pANTLR3_PARSER parser; pANTLR3_TREE_PARSER tparser; pANTLR3_INT_STREAM is; switch (recognizer->type) { case ANTLR3_TYPE_PARSER: parser = (pANTLR3_PARSER) (recognizer->super); tparser = NULL; is = parser->tstream->istream; break; case ANTLR3_TYPE_TREE_PARSER: tparser = (pANTLR3_TREE_PARSER) (recognizer->super); parser = NULL; is = tparser->ctnstream->tnstream->istream; break; default: fprintf(stderr, "Base recognizerfunction recover called by unknown paresr type - provide override for this function\n"); return ANTLR3_FALSE; break; } newFollow = NULL; if (follow == NULL) { /* The follow set is NULL, which means we don't know what can come * next, so we "hit and hope" by just signifying that we cannot * recover, which will just cause the next token to be consumed, * which might dig us out. */ return ANTLR3_FALSE; } /* We have a bitmap for the follow set, hence we can compute * what can follow this grammar element reference. */ if (follow->isMember(follow, ANTLR3_EOR_TOKEN_TYPE) == ANTLR3_TRUE) { /* First we need to know which of the available tokens are viable * to follow this reference. */ viableToksFollowingRule = recognizer->computeCSRuleFollow(recognizer); /* Knowing that, we can or in the follow set */ newFollow = follow->or(follow, viableToksFollowingRule); /* Remove the EOR token, which we do not wish to compute with */ newFollow->remove(follow, ANTLR3_EOR_TOKEN_TYPE); viableToksFollowingRule->free(viableToksFollowingRule); /* We now have the computed set of what can follow the current token */ follow = newFollow; } /* We can now see if the current token works with the set of tokens * that could follow the current grammar reference. If it looks like it * is consistent, then we can "insert" that token by not throwing * an exception and assumimng that we saw it. */ if ( follow->isMember(follow, is->_LA(is, 1)) == ANTLR3_TRUE) { /* report the error, but don't cause any rules to abort and stuff */ recognizer->reportError(recognizer); if (newFollow != NULL) { newFollow->free(newFollow); } recognizer->error = ANTLR3_FALSE; recognizer->failed = ANTLR3_FALSE; return ANTLR3_TRUE; /* Success in recovery */ } if (newFollow != NULL) { newFollow->free(newFollow); } /* We could not find anything viable to do, so this is going to * cause an exception. */ return ANTLR3_FALSE; }