Question

If I have expressions like:

(name = Paul AND age = 16) OR country = china;

And I want to get:

          QUERY
            |
     |-------------|
     ()            |
     |             |
    AND           OR    
     |             |
 |-------|         |
name    age     country
 |       |         |
Paul    16       china

How can I print the () and the condition (AND/OR) before the fields name, age country?

My grammar file is something like this:

parse
    :  block EOF -> block
    ;

block
    :   (statement)* (Return ID ';')? 
    ->  ^(QUERY statement*)
    ;

statement
    :   assignment ';'  
    ->  assignment
    ;

assignment
    :   expression (condition expression)* 
    ->  ^(condition expression*)
    |   '(' expression (condition expression)* ')' (condition expression)*
    ->  ^(Brackets ^(condition expression*))
    ;

condition
    :   AND
    |   OR
    ;

Brackets:   '()'    ;
OR  :   'OR'    ;
AND :   'AND'   ;

..

But it only prints the first condition that appears in the expression ('AND' in this example), and I can't group what is between brackets, and what is not...

Was it helpful?

Solution

Your grammar looks odd to me, and there are errors in it: if the parser does not match "()", you can't use Brackets inside a rewrite rule. And why would you ever want to have the token "()" inside your AST?

Given your example input:

(name = Paul AND age = 16) OR country = china;

here's possible way to construct an AST:

grammar T;

options {
  output=AST;
}

query
 : expr ';' EOF -> expr
 ;

expr
 : logical_expr
 ;

logical_expr
 : equality_expr ( logical_op^ equality_expr )*
 ;

equality_expr
 : atom ( equality_op^ atom )*
 ;

atom
 : ID
 | INT
 | '(' expr ')' -> expr
 ;

equality_op
 : '='
 | 'IS' 'NOT'?
 ;

logical_op
 : 'AND'
 | 'OR'
 ;

ID  : ('a'..'z' | 'A'..'Z')+;
INT : '0'..'9'+;
WS  : (' ' | '\t' | '\r' | '\n')+ {skip();};

which would result in this:

enter image description here

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top