我如何修改我的 EBNF 以处理诸如`- not 12`、`not + -1`

问题描述

我为下面的表达式创建了 EBNF

<expression> ::= <or_operand> [ "or" <or_operand> ]

<or_operand> ::= <and_operand> [ "and" <and_operand> ]

<and_operand> ::= <equality_operand> [ ( "=" | "!=" ) <equality_operand> ]

<equality_operand> ::= <simple_expression> [ <relational_operator> <simple_expression> ]

<relational_op> ::= "<" | ">" | "<=" | ">="

<simple_expression> ::= <term> [ ( "+" | "-" ) <term> ]

<term> ::= <factor> [ ( "*" | "/" ) <factor> ]

<factor> ::= <literal>
           | "(" <expression> ")"
           | "not" <factor>
           | ( "+" | "-" ) <factor>

<literal> ::= <boolean_literal> | <number>

<boolean_literal> ::= "true" | "false"

<number> ::= <digit> [ <digit> ]

<digit> ::= "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"

我的问题出在因子部分

<factor> ::= <literal>
           | "(" <expression> ")"
           | "not" <factor>
           | ( "+" | "-" ) <factor>

您可以看到我包含了三个一元运算符 not-+。它们适用于特定类型,例如 not 仅适用于布尔值,而 +/- 仅适用于数字。

我不知道如何处理 not+/- 混合使用的情况,例如 not +7- not true 等。有什么办法可以修改语法,使 not 永远不能与 +/- 混用吗?

够了吗?

<factor> ::= <literal>
           | "(" <expression> ")"
           | ( "not" | ( "+" | "-" ) ) <factor>

或者也许解析器的工作是解决这个问题?

解决方法

这很容易解决。你有两种不同风格的表达式,每种风格都有自己的语法,所以你不要混合它们,并保持它们的语法规则分开。

布尔表达式只能出现在某些地方,例如赋值或某种选择语句。数值表达式只能出现在比较或赋值中。这不是在语义层面处理的事情,如果看很多语言的语法,就是这样解决的。

所以你有数字表达式:

<simple_expression> ::= <term> [ ( "+" | "-" ) <term> ]

<term> ::= <factor> [ ( "*" | "/" ) <factor> ]

<factor> ::= <number>
           | "(" <expression> ")"
           | ( "+" | "-" ) <factor>

<number> ::= <digit> [ <digit> ]

<digit> ::= "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"

这现在是自包含的。我们现在可以将其构建为布尔表达式:

<boolean_expression> ::= "not" <boolean_expression>
                      | <logical_expression>
                      
<logical_expression> ::= <or_operand> [ "or" <or_operand> ]

<or_operand> ::= <and_operand> [ "and" <and_operand> ]

<and_operand> ::= <equality_operand> [ ( "=" | "!=" ) <equality_operand> ]
               
<equality_operand> ::= <simple_expression> [ <relational_operator> <simple_expression> ]
                 | <boolean_literal>

<relational_op> ::= "<" | ">" | "<=" | ">="

<boolean_literal> ::= "true" | "false"

请注意,我允许布尔文字的相等比较,但是如果您不想允许这样做,您可以更改规则以仅允许它们用于和操作数。

现在我们可以在另一个规则中使用这些,例如赋值:

<assignment> ::= <variable> ":=" ( <simple_expression> | <boolean_expression> )

一切都完成了。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...