/** * Attempt to recover from a single missing or extra token. * * <p>EXTRA TOKEN * * <p>LA(1) is not what we are looking for. If LA(2) has the right token, however, then assume * LA(1) is some extra spurious token. Delete it and LA(2) as if we were doing a normal match(), * which advances the input. * * <p>MISSING TOKEN * * <p>If current token is consistent with what could come after ttype then it is ok to "insert" * the missing token, else throw exception For example, Input "i=(3;" is clearly missing the ')'. * When the parser returns from the nested call to expr, it will have call chain: * * <p>stat → expr → atom * * <p>and it will be trying to match the ')' at this point in the derivation: * * <p>=> ID '=' '(' INT ')' ('+' atom)* ';' ^ match() will see that ';' doesn't match ')' and * report a mismatched token error. To recover, it sees that LA(1)==';' is in the set of tokens * that can follow the ')' token reference in rule atom. It can assume that you forgot the ')'. */ protected Object recoverFromMismatchedToken(IntStream input, int ttype, BitSet follow) throws RecognitionException { RecognitionException e = null; // if next token is what we are looking for then "delete" this token if (mismatchIsUnwantedToken(input, ttype)) { e = new UnwantedTokenException(ttype, input); /* System.err.println("recoverFromMismatchedToken deleting "+ ((TokenStream)input).LT(1)+ " since "+((TokenStream)input).LT(2)+" is what we want"); */ beginResync(); input.consume(); // simply delete extra token endResync(); reportError(e); // report after consuming so AW sees the token in the exception // we want to return the token we're actually matching Object matchedSymbol = getCurrentInputSymbol(input); input.consume(); // move past ttype token as if all were ok return matchedSymbol; } // can't recover with single token deletion, try insertion if (mismatchIsMissingToken(input, follow)) { Object inserted = getMissingSymbol(input, e, ttype, follow); e = new MissingTokenException(ttype, input, inserted); reportError(e); // report after inserting so AW sees the token in the exception return inserted; } // even that didn't work; must throw the exception e = new MismatchedTokenException(ttype, input); throw e; }
/** * Recover from an error found on the input stream. Mostly this is NoViableAlt exceptions, but * could be a mismatched token that the match() routine could not recover from. */ public void recover(IntStream input, RecognitionException re) { if (lastErrorIndex == input.index()) { // uh oh, another error at same token index; must be a case // where LT(1) is in the recovery token set so nothing is // consumed; consume a single token so at least to prevent // an infinite loop; this is a failsafe. input.consume(); } lastErrorIndex = input.index(); BitSet followSet = computeErrorRecoverySet(); beginResync(); consumeUntil(input, followSet); endResync(); }
/** * Attempt to recover from a single missing or extra token. * * <p>EXTRA TOKEN * * <p>LA(1) is not what we are looking for. If LA(2) has the right token, however, then assume * LA(1) is some extra spurious token. Delete it and LA(2) as if we were doing a normal match(), * which advances the input. * * <p>MISSING TOKEN * * <p>If current token is consistent with what could come after ttype then it is ok to "insert" * the missing token, else throw exception For example, Input "i=(3;" is clearly missing the ')'. * When the parser returns from the nested call to expr, it will have call chain: * * <p>stat -> expr -> atom * * <p>and it will be trying to match the ')' at this point in the derivation: * * <p>=> ID '=' '(' INT ')' ('+' atom)* ';' ^ match() will see that ';' doesn't match ')' and * report a mismatched token error. To recover, it sees that LA(1)==';' is in the set of tokens * that can follow the ')' token reference in rule atom. It can assume that you forgot the ')'. */ public void recoverFromMismatchedToken( IntStream input, RecognitionException e, int ttype, BitSet follow) throws RecognitionException { // if next token is what we are looking for then "delete" this token if (input.LA(2) == ttype) { reportError(e); /* * System.err.println("recoverFromMismatchedToken deleting "+input.LT * (1)+ " since "+input.LT(2)+" is what we want"); */ beginResync(); input.consume(); // simply delete extra token endResync(); input.consume(); // move past ttype token as if all were ok return; } if (!recoverFromMismatchedElement(input, e, follow)) { throw e; } }