首页 > 解决方案 > 我如何修改我的 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+/ -like not +7- not true等混合的情况。有什么办法可以修改语法,所以not永远不能与+/混合-

够了吗?

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

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

标签: programming-languagesbnfebnf

解决方案


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

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

所以你有数字表达式:

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

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

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

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

一切都完成了。


推荐阅读