Here is my grammer:
grammar esi_exp;
/* This will be the entry point of our parser. */
eval
: booleanExp
;
/* Addition and subtraction have the lowest precedence. */
booleanExp
: orExp
;
orExp
: andExpr (OR andExpr)*
;
andExpr
: notExpr (AND notExpr)*
;
notExpr
: NOT comparisonExpr
| comparisonExpr
;
comparisonExpr
: varOrLiteral ('==' varOrLiteral)*
;
varOrLiteral
: functionExpr
| literalExpr
| variableExpr
;
literalExpr : QUOTE VAR_ID QUOTE ;
variableExpr
: OPEN_VAR VAR_ID CLOSE_PAREN // $(HTTP_HOST)
| OPEN_VAR varWithArg CLOSE_PAREN // $(QUERY_STRING{param})
| OPEN_VAR varWithArgQuoted CLOSE_PAREN // $(QUERY_STRING{'param'})
| OPEN_PAREN booleanExp CLOSE_PAREN
;
varWithArg : VAR_ID OPEN_ARG VAR_ID CLOSE_ARG ;
varWithArgQuoted : VAR_ID OPEN_QUOTED_ARG VAR_ID CLOSE_QUOTED_ARG ;
matchValue : MATCH_VALUE_REGEX ;
functionExpr
: '$' FunctionName functionArgs;
FunctionName :
'exists'
| 'is_empty'
;
functionArgs
: '()'
| OPEN_PAREN VAR_ID CLOSE_PAREN
| OPEN_PAREN variableExpr CLOSE_PAREN
;
EQUALS : '==' ;
MATCH_FUNC : 'matches' ;
TRIPLE_QUOTE : '\'\'\'' ;
QUOTE : '\'' ;
OPEN_VAR : '$(' ;
OPEN_PAREN : '(' ;
CLOSE_PAREN : ')' ;
OPEN_ARG : '{' ;
CLOSE_ARG : '}' ;
OPEN_QUOTED_ARG : '{\'' ;
CLOSE_QUOTED_ARG : '\'}' ;
VAR_ID : ('a'..'z'|'A'..'Z'|'_')+ ; // match identifiers
AND : '&&' | '&' ;
OR : '|' | '||' ;
NOT : '!' ;
/* A number: can be an integer value */
Number
: ('0'..'9')+
;
WS
: (
' '
| '\r'
| '\t'
| '\u000C'
| '\n'
)
{
skip();
}
;
MATCH_VALUE_REGEX : TRIPLE_QUOTE ~(QUOTE)* TRIPLE_QUOTE;
which works great for the test case:
$exists($(id)) && (($(pagetype) == 'roster') || ($(pagetype) == 'cheerleaders') || ($(pagetype) == 'coaches') || ($(pagetype) == 'staff'))
However, I also need to have it be able to recognize:
$(REQUEST_PATH) matches '''(matchup)/([^/]*)/([^/]*)/([^/]*)/([^/]*)'''
A grammar rule like:
varOrLiteral MATCH_FUNC matchValue
should match it and result in a properly parsed grammar. That rule was working in an earlier version but was taken out when I reworked the grammar to support enclosing parens in an expression.
I've read that enabling backtracking should be able to help in these situations however the documentation seems to indicate that backtracking should be avoided in general.
How do I add this without having LL and/or Left Recursion issues?