MuffinTheMan
MuffinTheMan

Reputation: 1581

Force semantic error (failed predicate) in ANTLR4

Basically, I've extended the BaseErrorListener, and I need to know when the error is semantic and when it's syntactic. So I want the following to give me a failed predicate exception, but I'm getting a NoViableAltException instead (I know the counting is working, because I can print out the value of things, and it's correct). Is there a way I can re-work it to do what I want? In my example below, I want there to be a failed predicate exception if we don't end up with 6 things.

grammar Test;

@parser::members {
    int things = 0;
}
.
.
.
samplerule : THING { things++; } ;
.
.
.
// Want this to be a failed predicate instead of NoViableAltException
anotherrule : ENDTOKEN { things == 6 }? ;
.
.
.

I'm already properly getting failed predicate exceptions with the following (for a different scenario):

somerule : { Integer.valueOf(getCurrentToken().getText()) < 256 }? NUMBER ;
.
.
.
NUMBER : [0-9]+ ;

Upvotes: 0

Views: 1572

Answers (2)

MuffinTheMan
MuffinTheMan

Reputation: 1581

Due to 280Z28's answer and the apparent fact that predicates should not be used for what I was trying to do, I went a different route.

If you know what you're looking for, ANTLR4's documentation is actually pretty useful--visit Parser.getCurrentToken()'s documentation and poke around further to see what more you can do with my implementation below.

My driver ended up looking something like the following:

// NameOfMyGrammar.java
public class NameOfMyGrammar {

    public static void main(String[] args) throws Exception {

        String inputFile = args[0];

        try {
            ANTLRInputStream input = new ANTLRFileStream(inputFile);

            NameOfMyGrammarLexer lexer = new NameOfMyGrammarLexer(input);

            CommonTokenStream tokens = new CommonTokenStream(lexer);

            MyCustomParser parser = new MyCustomParser(tokens);

            try {
                // begin parsing at "start" rule
                ParseTree tree = parser.start();
                // can print out parse tree if you want..
            } catch (RuntimeException e) {
                // Handle errors if you want..
            }
        } catch (IOException e) {
            System.err.println("Error: " + e);
        }   
    }

    // extend ANTLR-generated parser
    private static class MyCustomParser extends NameOfMyGrammarParser {

        // Constructor (my understanding is that you DO need this)
        public MyCustomParser(TokenStream input) {
            super(input);
        }

        @Override
        public Token getCurrentToken() {
            // Do your semantic checking as you encounter tokens here..
            // Depending on how you want to handle your errors, you can
            // throw exceptions, print out errors, etc.

            // Make sure you end by returning the current token
            return _input.LT(1);
        }
    }
}

Upvotes: 0

Sam Harwell
Sam Harwell

Reputation: 99989

In ANTLR 4, predicates should only be used in cases where your input leads to two different possible parse trees (ambiguous grammar) and the default handling is producing the wrong parse tree. You should create a listener or visitor implementation containing your logic for semantic validation of the source.

Upvotes: 1

Related Questions