I'm trying to create a grammar for expression evaluation that differentiates between String, Boolean, and Numeric expressions.
Here's the relevant grammar so far:
functionInvocation: IDENTIFIER '(' ( IDENTIFIER '=' expression ( ',' IDENTIFIER '=' expression )* )? ')' ;
expression
: stringExpression
| booleanExpression
| numericExpression
;
stringExpression
: '(' stringExpression ')'
| stringExpression '+' stringExpression
| <assoc=right> booleanExpression '?' stringExpression ':' stringExpression
| STRING_LITERAL
| IDENTIFIER
| functionInvocation
;
booleanExpression
: '(' booleanExpression ')'
| NOT booleanExpression
| booleanExpression LOGICAL_AND booleanExpression
| booleanExpression LOGICAL_OR booleanExpression
| numericExpression ( LESS_THAN | LESS_THAN_OR_EQUAL_TO | GREATER_THAN | GREATER_THAN_OR_EQUAL_TO ) numericExpression
| stringExpression ( LESS_THAN | LESS_THAN_OR_EQUAL_TO | GREATER_THAN | GREATER_THAN_OR_EQUAL_TO ) stringExpression
| numericExpression ( IS_EQUAL_TO | NOT_EQUAL_TO ) numericExpression
| stringExpression ( IS_EQUAL_TO | NOT_EQUAL_TO ) stringExpression
| <assoc=right> booleanExpression '?' booleanExpression ':' booleanExpression
| stringExpression '=~' 'm/' REGEX_PATTERN '/' REGEX_OPTIONS
| BOOLEAN_TRUE
| BOOLEAN_FALSE
| IDENTIFIER
| functionInvocation
;
numericExpression
: '(' numericExpression ')' #mathSubExpression
| ( PLUS | MINUS | NOT )? mathAtom #unaryOperation
| numericExpression POWER numericExpression #binaryOperation
| numericExpression ( MULTIPLY | DIVIDE | MODULO ) numericExpression #binaryOperation
| numericExpression ( ADD | SUBTRACT ) numericExpression #binaryOperation
| numericExpression ( SHIFT_LEFT | SHIFT_RIGHT ) numericExpression #binaryOperation
| numericExpression BITWISE_AND numericExpression #binaryOperation
| numericExpression BITWISE_XOR numericExpression #binaryOperation
| numericExpression BITWISE_OR numericExpression #binaryOperation
;
mathAtom
: BINARY_LITERAL
| FLOAT_LITERAL
| HEX_LITERAL
| INTEGER_LITERAL
| OCTAL_LITERAL
| SCIENTIFIC_NOTATION_LITERAL
| IDENTIFIER
| functionInvocation
;
I'm ending up with stringExpression
and booleanExpression
being mutually left-recursive because of the ternary operator in stringExpression
.
Is there a way of expressing the intent that is not mutually left-recursive?