【问题标题】:ANTLR grammar problem with parenthetical expressions括号表达式的ANTLR语法问题
【发布时间】:2011-05-04 19:24:11
【问题描述】:

我正在使用 ANTLRWorks 1.4.2 创建一个简单的语法,用于将用户提供的表达式评估为布尔结果。这最终将成为更大语法的一部分,但我对当前的片段有一些疑问。我希望用户能够使用以下表达式:

  1. 2 > 1
  2. 2 > 1 and 3 < 1
  3. (2 > 1 or 1 < 3) and 4 > 1
  4. (2 > 1 or 1 < 3) and (4 > 1 or (2 < 1 and 3 > 1))

前两个表达式在我的语法中是合法的,但后两个不是,我不知道为什么。此外,ANTLRworks 似乎暗示 ((((1 > 2) 等括号不匹配的输入是合法的,我不知道为什么。所以,我似乎错过了一些关于在语法中处理括号分组的正确方法的见解。

如何更改语法以正确处理括号?

我的语法如下:

grammar conditional_test;

boolean
    :   boolean_value_expression
        EOF
    ;

boolean_value_expression
    :   boolean_term (OR boolean_term)*
        EOF
    ;

boolean_term
    :   boolean_factor (AND boolean_factor)*
    ;

boolean_factor
    :   (NOT)?  boolean_test
    ;

boolean_test
    :   predicate
    ;

predicate
    :   expression relational_operator expression
    |   LPAREN boolean_value_expression RPAREN
    ;

relational_operator
    :   EQ
    |   LT
    |   GT
    ;   

expression
    :   NUMBER
    ;


LPAREN      :   '(';
RPAREN      :   ')';
NUMBER      :   '0'..'9'+;

EQ          :   '=';
GT          :   '>';
LT          :   '<';

AND         :   'and';
OR          :   'or' ;
NOT         :   'not';

【问题讨论】:

    标签: antlr grammar


    【解决方案1】:

    克里斯·法默写道:

    前两个表达式在我的语法中是合法的,但后两个不是,我不知道为什么。 ...

    您应该从以下位置删除 EOF 令牌:

    boolean_value_expression
        :   boolean_term (OR boolean_term)*
            EOF
        ;
    

    您通常只在语法入口点之后使用EOF(在您的情况下为boolean)。注意boolean 是Java 中的保留字,因此不能用作解析器规则!

    所以前两条规则应该是这样的:

    bool
        :   boolean_value_expression
            EOF
        ;
    
    boolean_value_expression
        :   boolean_term (OR boolean_term)*
        ;
    

    您可能还想通过添加以下词法分析器规则来忽略文字空格:

    SPACE : ' ' {$channel=HIDDEN;};
    

    (当然,您可以包含制表符和换行符)

    现在您的所有示例输入都正确匹配(也使用 ANTLRWorks 1.4.2 进行了测试)。

    克里斯·法默写道:

    此外,ANTLRworks 似乎暗示诸如 ((((1 > 2) 之类的带有不匹配括号的输入是合法的,...

    不,ANTLRWorks确实产生错误,也许不是很明显的错误。 ANTLRWorks 生成的解析树有一个 NoViableAltException 作为叶子,并且“控制台”选项卡上有一些错误。

    【讨论】:

    • 谢谢!我不确定额外的 EOF 是如何进入那里的,但它确实让一些事情感到困惑。谢谢你看看这个。您的建议很有效。
    • @Chris,请注意,您的语法不允许在数字周围使用括号,例如:1 &lt; (2)。您可能是故意这样做的,但也可能不是,在这种情况下,您应该将 LPAREN boolean_value_expression RPAREN 移动到 expression 规则并将 predicate 更改为:predicate : expression (relational_operator expression)? ;
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-07
    相关资源
    最近更新 更多