0

I have an RSQL grammar defined:

grammar Rsql;

statement
    : L_PAREN wrapped=statement R_PAREN
    | left=statement op=( AND_OPERATOR | OR_OPERATOR ) right=statement
    | node=comparison
    ;

comparison
    : single_comparison
    | multi_comparison
    | bool_comparison
    ;

single_comparison
    : key=IDENTIFIER op=( EQ | NE | GT | GTE | LT | LTE ) value=single_value
    ;

multi_comparison
    : key=IDENTIFIER op=( IN | NIN ) value=multi_value
    ;

bool_comparison
    : key=IDENTIFIER op=EX value=boolean_value
    ;

boolean_value
    : BOOLEAN
    ;

single_value
    : boolean_value
    | ( STRING_LITERAL | IDENTIFIER )
    | NUMERIC_LITERAL
    ;

multi_value
    : L_PAREN single_value ( COMMA single_value )* R_PAREN
    | single_value
    ;

TRUE: 'true';
FALSE: 'false';
AND_OPERATOR: ';';
OR_OPERATOR: ',';
L_PAREN: '(';
R_PAREN: ')';
COMMA: ',';
EQ: '==';
NE: '!=';
IN: '=in=';
NIN: '=out=';
GT: '=gt=';
LT: '=lt=';
GTE: '=ge=';
LTE: '=le=';
EX: '=ex=';

IDENTIFIER
 : [a-zA-Z_] [a-zA-Z_0-9]*
 ;

BOOLEAN
    : TRUE
    | FALSE
    ;

NUMERIC_LITERAL
    : DIGIT+ ( '.' DIGIT* )? ( [-+]? DIGIT+ )?
    | '.' DIGIT+ ( [-+]? DIGIT+ )?
    ;

STRING_LITERAL
    : '\'' ( STRING_ESCAPE_SEQ | ~[\\\r\n'] )* '\''
    | '"' ( STRING_ESCAPE_SEQ | ~[\\\r\n"] )* '"'
    ;

STRING_ESCAPE_SEQ
    : '\\' .
    ;

fragment DIGIT : [0-9];

No matter how I attempt to parse this (listener/visitor), the statements with parenthesis always get evaluated in order. It is my understanding that the order in the rule would be the precedence. However, the parse tree for a statement like "name==foo,(name==bar;age=gt=35)" is always

enter image description here

no matter where the parenthesis appear. Please help me discover what I'm missing. Thanks!

Todd
  • 35
  • 6
  • So how do you want it to be parsed? – Raven Aug 03 '17 at 07:32
  • @raven, Ideally the parenthesized AND would appear first in the tree so that when I walk it I can evaluate it first. As it stands, when visiting or walking, I meet the OR, then the name==foo expression first. However, this shouldn't be evaluated first. – Todd Aug 03 '17 at 12:12
  • So you'd want the parse tree mirrored at the vertical axis? – Raven Aug 03 '17 at 14:15
  • @Raven yea. That sounds about right. – Todd Aug 03 '17 at 18:04
  • Hm actually I don't think thisis possible... However you can write your own visitor that visits the right node before the left one... That should have the same overall effect... – Raven Aug 03 '17 at 18:16
  • @Raven how would one go about this? It is quite possible that the parenthesized expression is quite deep. I would need to traverse the entire tree and rebuild my own tree in the desired precedence to be sure that it gets evaluated. Is this what one is expected to do? If so, why use antlr since I would need to end up writing my own parser anyway? – Todd Aug 03 '17 at 20:06
  • I have never worked with visitors myself but looking at this https://stackoverflow.com/questions/19472986/how-to-use-antlr4-visitor I would say you create a visitor and override the visit-method for your AND statement and in there you say you first visit the right node and the left one after that. Then you can override the respective sub-node-visit-methods (just the same as you'd do in the listener) and do your processing stuff in there. Like this you should get the desired result of first processing the right node (with the parenthesis) and afterwards the left one... – Raven Aug 04 '17 at 08:04
  • @Raven That's kind of my point. For one (known) situation it is easy. To do it generically for an arbitrarily nested tree this becomes cumbersome. `name==foo,((color==red;age=lt=55),color==green)` would create a deeper tree. – Todd Aug 04 '17 at 11:20
  • Hm okay... What about using the normal listener and using the enter-method for processing the right node and the exit-method for processing the left one? That should work for nested trees as well... – Raven Aug 04 '17 at 13:16

0 Answers0