1
votes

I was reading the URL (and trying to copy) and failed... (great article on antlr too).

https://supportweb.cs.bham.ac.uk/docs/tutorials/docsystem/build/tutorials/antlr/antlr.html

My solution before I added parenthesis stuff:

whereClause: WHERE expression -> ^(WHERE_CLAUSE expression);
expression: orExpr;
orExpr: andExpr (OR^ andExpr)*;
andExpr: primaryExpr (AND^ primaryExpr)*;
primaryExpr: parameterExpr | inExpr | compExpr;

My solution that failed due to infinite recursion (but I thought the LPAREN^ and RPAREN! where supposed to solve that???)....

whereClause: WHERE^ (expression | orExpr);
expression: LPAREN^ orExpr RPAREN!;
orExpr: andExpr (OR^ andExpr)*;
andExpr: primaryExpr (AND^ primaryExpr)*;
primaryExpr: parameterExpr | inExpr | compExpr | expression;

Notice primaryExpr at bottom has expression tacked back on which has LPAREN and RPAREN, but the WHERE can be an orExpr or expression (i.e. the first expression can use or not use parentheses).

I am sure this is probably a simple issue like a typo that I keep staring at for hours or something.

1

1 Answers

1
votes

I was reading the url(and trying to copy) and failed...(great article on antlr too)...

Note that the article explains ANTLR v2, which has a significant different syntax than v3. Better look for a decent ANTLR v3 tutorial here: https://stackguides.com/questions/278480/antlr-tutorials

My solution that failed due to infinite recursion (but I thought the LPAREN^ and RPAREN! where supposed to solve that???)....

It would have, if that were the only expression after the WHILE. However, the orExpr is causing the problem in your case (if you remove it, that recursion error will go away).

A parenthesized expression usually has the highest precedence, and should therefor be placed in your primaryExpr rule, like this:

grammar T;

options {
  output=AST;
}

parse       : whereClause EOF!;
whereClause : WHERE^ expression;
expression  : orExpr;
orExpr      : andExpr (OR^ andExpr)*;
andExpr     : primaryExpr (AND^ primaryExpr)*;
primaryExpr : bool | NUMBER | '('! expression ')'!;
bool        : TRUE | FALSE;

TRUE        : 'true';
FALSE       : 'false';
WHERE       : 'where';
LPAREN      : '(';
RPAREN      : ')';
OR          : '||';
AND         : '&&';
NUMBER      : '0'..'9'+ ('.' '0'..'9'*)?;
SPACE       : (' ' | '\t' | '\r' | '\n')+ {skip();};

Now both the input "where true || false" and "where (true || false)" will be parsed in the following AST:

enter image description here