I am currently creating a more or less simple expression evaluator using ANTLR.
My grammar is simple (at least I hope) and looks like this:
grammar SXLGrammar; options { language = Java; output = AST; } tokens { OR = 'OR'; AND = 'AND'; NOT = 'NOT'; GT = '>'; //greater then GE = '>='; //greater then or equal LT = '<'; //lower then LE = '<='; //lower then or equal EQ = '='; NEQ = '!='; //Not equal PLUS = '+'; MINUS = '-'; MULTIPLY = '*'; DIVISION = '/'; CALL; } @header { package somepackage; } @members { } @lexer::header { package rise.spics.sxl; } rule : ('='|':')! expression ; expression : booleanOrExpression ; booleanOrExpression : booleanAndExpression ('OR'^ booleanAndExpression)* ; booleanAndExpression : booleanNotExpression ('AND'^ booleanNotExpression)* ; booleanNotExpression : ('NOT'^)? booleanAtom ; booleanAtom : | compareExpression ; compareExpression : commonExpression (('<' | '>' | '=' | '<=' | '>=' | '!=' )^ commonExpression)? ; commonExpression : multExpr ( ( '+'^ | '-'^ ) multExpr )* | DATE ; multExpr : atom (('*'|'/')^ atom)* | '-'^ atom ; atom : INTEGER | DECIMAL | BOOLEAN | ID | '(' expression ')' -> expression | functionCall ; functionCall : ID '(' arguments ')' -> ^(CALL ID arguments?) ; arguments : (expression) (','! expression)* | WS ; BOOLEAN : 'true' | 'false' ; ID : ( 'a'..'z' | 'A'..'Z' )+ ; INTEGER : ('0'..'9')+ ; DECIMAL : ('0'..'9')+ ('.' ('0'..'9')*)? ; DATE : '!' '0'..'9' '0'..'9' '0'..'9' '0'..'9' '-' '0'..'9' '0'..'9' '-' '0'..'9' '0'..'9' (' ' '0'..'9' '0'..'9' ':''0'..'9' '0'..'9' (':''0'..'9' '0'..'9')?)? ; WS : (' '|'\t' | '\n' | '\r' | '\f')+ { $channel = HIDDEN; };
Now, if I try to parse an invalid expression, for example "= true NOT true," the eclipse plug-in graphical test tool throws a NoViableAltException: line 1: 6 there is no viable alternative to the input "NOT", which is correct and allowed.
Now, if I try to parse an expression in a Java program, nothing happens. Program
String expression = "=true NOT false"; CharStream input = new ANTLRStringStream(expression); SXLGrammarLexer lexer = new SXLGrammarLexer(input); TokenStream tokenStream = new CommonTokenStream(lexer); SXLGrammarParser parser = new SXLGrammarParser(tokenStream); CommonTree tree = (CommonTree) parser.rule().getTree(); System.out.println(tree.toStringTree()); System.out.println(parser.getNumberOfSyntaxErrors());
outputs:
true 0
this means that the AST created by the parser exists from one node and ignores the rest. I would like to handle syntax errors in my application, but this is not possible if the generated parser does not detect errors.
I also tried changing the parser by replacing the displayRecognitionError () method with something like this:
public void displayRecognitionError(String[] tokenNames, RecognitionException e) { String msg = getErrorMessage(e, tokenNames); throw new RuntimeException("Error at position "+e.index+" " + msg); }
but displayRecognitionError is never raised.
If I try something like "= 1 +", an error will appear. I think something is wrong with my grammar, but why does the eclipse plugin throw this error until the generated parser does?