0

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?

nflearl
  • 131
  • 7

2 Answers2

0

You can anticipate what you expect as a beginning of a rule in order to specify a way.

Why don't you try this?

varOrLiteral
    :  
    (QUOTE QUOTE) => matchValue
    |(QUOTE) => literalExpr
    | variableExpr
    |functionExpr
    ;

With this, you are telling the grammar that only if only varOrLiteral begins by QUOTE, it is a literalExpr. Etc.

You can anticipate how many you want.

Last rule, default option.

Good luck!

Juan Aguilar Guisado
  • 1,687
  • 1
  • 12
  • 21
  • How does that help implement/integrating "MATCH_FUNC matchValue" into the grammar? – nflearl Oct 09 '14 at 22:51
  • Just tried that refactoring, getting a FailedPredicateException. This doesn't pass regression on the existing working case. – nflearl Oct 09 '14 at 23:00
  • I edited my answer. I was trying to help you but I missed information. Sorry very much. Try this one. Compile grammars only with mind is complicated but I haven't got available my "developer kit" right now :p – Juan Aguilar Guisado Oct 09 '14 at 23:08
  • I really appreciate the help. That makes more sense for my first question. Still, this fails regression with FailedPredicateException. Any ideas on the FailedPredicate? – nflearl Oct 09 '14 at 23:12
  • I've fixed one thing. matchValue should be camel style, like your rule :') – Juan Aguilar Guisado Oct 09 '14 at 23:15
  • I had already caught the camel case issue before attempting the regression. Using the Interpreter on AntlrWorks, it is not generating the resulting parse tree, instead I see the FailedPredicateException as part of the tree. – nflearl Oct 09 '14 at 23:22
  • Further clarification, AntlrWorks isn't handling it well. I ran the regression through another tool and get the expected results for the regression. I can see my way to the finish line with this hint. I just need tweak comparisonExpr to get the new behavior. – nflearl Oct 09 '14 at 23:50
  • Wasn't as easy as I thought getting to the finish line, unchecking for now as more is needed and I'm not there yet. – nflearl Oct 10 '14 at 01:03
0

Finally figured it out and was able to achieve the goal simply with changing the comparison Expression to:

:   varOrLiteral (EQUALS varOrLiteral | MATCH_FUNC matchValue)*

Good enough for now.

nflearl
  • 131
  • 7