【问题标题】:ANTLR3 rule eval has non-LL(*) decisionANTLR3 规则评估具有非 LL(*) 决定
【发布时间】:2014-10-09 21:41:20
【问题描述】:

这是我的语法:

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;

这对测试用例很有用:

$exists($(id)) && (($(pagetype) == 'roster') || ($(pagetype) == 'cheerleaders') || ($(pagetype) == 'coaches') || ($(pagetype) == 'staff'))

但是,我还需要让它能够识别:

$(REQUEST_PATH) matches '''(matchup)/([^/]*)/([^/]*)/([^/]*)/([^/]*)'''

语法规则如下:

varOrLiteral MATCH_FUNC matchValue

应该匹配它并产生正确解析的语法。该规则在早期版本中有效,但在我修改语法以支持在表达式中包含括号时被删除。

我已经读到启用回溯应该能够在这些情况下提供帮助,但是文档似乎表明通常应该避免回溯。

如何在没有 LL 和/或左递归问题的情况下添加它?

【问题讨论】:

    标签: antlr3 ll


    【解决方案1】:

    您可以预测您期望的作为规则开始的内容,以便指定一种方式。

    你为什么不试试这个?

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

    这样,您就是在告诉语法,只有当 varOrLiteral 以 QUOTE 开头时,它才是literalExpr。等等。

    你可以预测你想要多少。

    最后一条规则,默认选项。

    祝你好运!

    【讨论】:

    • 这如何帮助将“MATCH_FUNC matchValue”实现/集成到语法中?
    • 刚刚尝试了重构,得到了一个 FailedPredicateException。这不会通过现有工作案例的回归。
    • 我编辑了我的答案。我试图帮助你,但我错过了信息。非常抱歉。试试这个。只用头脑编译语法很复杂,但我现在还没有我的“开发工具包”:p
    • 非常感谢您的帮助。这对我的第一个问题更有意义。尽管如此,这仍然会导致 FailedPredicateException 的回归失败。关于 FailedPredicate 有什么想法吗?
    • 我已经修复了一件事。 matchValue 应该是骆驼风格,就像你的规则:')
    【解决方案2】:

    终于想通了,只需将比较表达式更改为:

    :   varOrLiteral (EQUALS varOrLiteral | MATCH_FUNC matchValue)*
    

    现在已经足够了。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-09-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-03-23
      相关资源
      最近更新 更多