Chris Farmer
Chris Farmer

Reputation: 25396

ANTLR grammar problem with parenthetical expressions

I'm using ANTLRWorks 1.4.2 to create a simple grammar for the purpose of evaluating an user-provided expression as boolean result. This ultimately will be part of a larger grammar, but I have some questions about this current fragment. I want users to be able to use expressions such as:

  1. 2 > 1
  2. 2 > 1 and 3 < 1
  3. (2 > 1 or 1 < 3) and 4 > 1
  4. (2 > 1 or 1 < 3) and (4 > 1 or (2 < 1 and 3 > 1))

The first two expressions are legal in my grammar, but the last two are not, and I am not sure why. Also, ANTLRworks seems to suggest that input such as ((((1 > 2) with mismatched parentheses is legal, and I am not sure why. So, I seem to be missing out on some insight into the right way to handle parenthetical grouping in a grammar.

How can I change my grammar to properly handle parentheses?

My grammar is below:

grammar conditional_test;

boolean
    :   boolean_value_expression
        EOF
    ;

boolean_value_expression
    :   boolean_term (OR boolean_term)*
        EOF
    ;

boolean_term
    :   boolean_factor (AND boolean_factor)*
    ;

boolean_factor
    :   (NOT)?  boolean_test
    ;

boolean_test
    :   predicate
    ;

predicate
    :   expression relational_operator expression
    |   LPAREN boolean_value_expression RPAREN
    ;

relational_operator
    :   EQ
    |   LT
    |   GT
    ;   

expression
    :   NUMBER
    ;


LPAREN      :   '(';
RPAREN      :   ')';
NUMBER      :   '0'..'9'+;

EQ          :   '=';
GT          :   '>';
LT          :   '<';

AND         :   'and';
OR          :   'or' ;
NOT         :   'not';

Upvotes: 1

Views: 750

Answers (1)

Bart Kiers
Bart Kiers

Reputation: 170158

Chris Farmer wrote:

The first two expressions are legal in my grammar, but the last two are not, and I am not sure why. ...

You should remove the EOF token from:

boolean_value_expression
    :   boolean_term (OR boolean_term)*
        EOF
    ;

You normally only use the EOF after the entry point of your grammar (boolean in your case). Be careful boolean is a reserved word in Java and can therefor not be used as a parser rule!

So the first two rules should look like:

bool
    :   boolean_value_expression
        EOF
    ;

boolean_value_expression
    :   boolean_term (OR boolean_term)*
    ;

And you may also want to ignore literal spaces by adding the following lexer rule:

SPACE : ' ' {$channel=HIDDEN;};

(you can include tabs an line breaks, of course)

Now all of your example input matches properly (tested with ANTLRWorks 1.4.2 as well).

Chris Farmer wrote:

Also, ANTLRworks seems to suggest that input such as ((((1 > 2) with mismatched parentheses is legal, ...

No, ANTLRWorks does produce errors, perhaps not very noticeable ones. The parse tree ANTLRWorks produces has a NoViableAltException as a leaf, and there are some errors on the "Console" tab.

Upvotes: 4

Related Questions