Question

I've got a rule like this:

declaration returns [RuntimeObject obj]: 
    DECLARE label value { $obj = new RuntimeObject($label.text, $value.text); };

Unfortunately, it throws an exception in the RuntimeObject constructor because $label.text is null. Examining the debug output and some other things reveals that the match against "label" actually failed, but the Antlr runtime "helpfully" continues with the match for the purpose of giving a more helpful error message (http://www.antlr.org/blog/antlr3/error.handling.tml).

Okay, I can see how this would be useful for some situations, but how can I tell Antlr to stop doing that? The defaultErrorHandler=false option from v2 seems to be gone.

Was it helpful?

Solution

I don't know much about Antlr, so this may be way off base, but the section entitled "Error Handling" on this migration page looks helpful.

It suggests you can either use @rulecatch { } to disable error handling entirely, or override the mismatch() method of the BaseRecogniser with your own implementation that doesn't attempt to recover. From your problem description, the example on that page seems like it does exactly what you want.

OTHER TIPS

You could also override the reportError(RecognitionException) method, to make it rethrow the exception instead of print it, like so:

@parser::members {
    @Override
    public void reportError(RecognitionException e) {
        throw new RuntimeException(e);
    }
}

However, I'm not sure you want this (or the solution by ire_and_curses), because you will only get one error per parse attempt, which you can then fix, just to find the next error. If you try to recover (ANTLR does it okay) you can get multiple errors in one try, and fix all of them.

You need to override the mismatch and recoverFromMismatchedSet methods to ensure an exception is thrown immediately (examples are for Java):

@members {
    protected void mismatch(IntStream input, int ttype, BitSet follow) throws RecognitionException {
        throw new MismatchedTokenException(ttype, input);
    }

    public Object recoverFromMismatchedSet(IntStream input, RecognitionException e, BitSet follow) throws RecognitionException {
        throw e;
    }
}

then you need to change how the parser deals with those exceptions so they're not swallowed:

@rulecatch {
    catch (RecognitionException e) {
        throw e;
    }
}

(The bodies of all the rule-matching methods in your parser will be enclosed in try blocks, with this as the catch block.)


For comparison, the default implementation of recoverFromMismatchedSet inherited from BaseRecognizer:

public Object recoverFromMismatchedSet(IntStream input, RecognitionException e, BitSet follow)  throws RecognitionException {
    if (mismatchIsMissingToken(input, follow)) {
        reportError(e);
        return getMissingSymbol(input, e, Token.INVALID_TOKEN_TYPE, follow);
    }

    throw e;
}

and the default rulecatch:

catch (RecognitionException re) {
    reportError(re);
    recover(input,re);
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top