带括号表达式的 ANTLR 语法问题

发布于 2024-11-04 23:10:52 字数 1267 浏览 0 评论 0原文

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

  1. 2 > 1
  2. 2 > 1和3< 1
  3. (2 > 1 或 1 < 3) 且 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';

I'm using ANTLRWorks 1.4.2 to create a simple grammar for the purpose of evaluating an user-provided expression as boolean result. This ultimately will be part of a larger grammar, but I have some questions about this current fragment. I want users to be able to use expressions such as:

  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))

The first two expressions are legal in my grammar, but the last two are not, and I am not sure why. Also, ANTLRworks seems to suggest that input such as ((((1 > 2) with mismatched parentheses is legal, and I am not sure why. So, I seem to be missing out on some insight into the right way to handle parenthetical grouping in a grammar.

How can I change my grammar to properly handle parentheses?

My grammar is below:

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';

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

入画浅相思 2024-11-11 23:10:52

克里斯·法默写道:

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

您应该从以下位置删除 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 作为叶子,并且“Console”选项卡上有一些错误。

Chris Farmer wrote:

The first two expressions are legal in my grammar, but the last two are not, and I am not sure why. ...

You should remove the EOF token from:

boolean_value_expression
    :   boolean_term (OR boolean_term)*
        EOF
    ;

You normally only use the EOF after the entry point of your grammar (boolean in your case). Be careful boolean is a reserved word in Java and can therefor not be used as a parser rule!

So the first two rules should look like:

bool
    :   boolean_value_expression
        EOF
    ;

boolean_value_expression
    :   boolean_term (OR boolean_term)*
    ;

And you may also want to ignore literal spaces by adding the following lexer rule:

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

(you can include tabs an line breaks, of course)

Now all of your example input matches properly (tested with ANTLRWorks 1.4.2 as well).

Chris Farmer wrote:

Also, ANTLRworks seems to suggest that input such as ((((1 > 2) with mismatched parentheses is legal, ...

No, ANTLRWorks does produce errors, perhaps not very noticeable ones. The parse tree ANTLRWorks produces has a NoViableAltException as a leaf, and there are some errors on the "Console" tab.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文