看看有没有写BNF文法表达式部分的理论

Find out if there is a theory fow writing expression section of BNF Grammar

我想为数学程序编写一个新的解析器。当我为此编写 BNF 语法时,我陷入了表达式。这是我写的BNF符号。

program : expression*

expression: additive_expression

additive_expression : multiplicative_expression
                    | additive_expression '+' multiplicative_expression
                    | additive_expression '-' multiplicative_expression

multiplicative_expression : number
                          | number '*' multiplicative_expression
                          | number '/' multiplicative_expression

但是我无法理解如何为 ++, --, +=, -=, &&, || etc. 这个运算符编写 BNF 表达式语法。我指的是 C、C++、C#、Python、Java 等语言中的运算符

我知道在使用+, -, *, /运算符时,语法应该按照BODMAS理论来写。

我想知道的是,写其他运算符的语法是否应该用到什么理论?

我仔细看了 C++ 语言 语法(表达式部分)。但是我看不懂。

<expression> ::= <assignment_expression>
               | <assignment_expression> <expression>

<assignment_expression> ::= <logical_or_expression> "=" <assignment_expression>
                          | <logical_or_expression> "+=" <assignment_expression>
                          | <logical_or_expression> "-=" <assignment_expression>
                          | <logical_or_expression> "*=" <assignment_expression>
                          | <logical_or_expression> "/=" <assignment_expression>
                          | <logical_or_expression> "%=" <assignment_expression>
                          | <logical_or_expression> "<<=" <assignment_expression>
                          | <logical_or_expression> ">>=" <assignment_expression>
                          | <logical_or_expression> "&=" <assignment_expression>
                          | <logical_or_expression> "|=" <assignment_expression>
                          | <logical_or_expression> "^=" <assignment_expression>
                          | <logical_or_expression>

<constant_expression> ::= <conditional_expression>

<conditional_expression> ::= <logical_or_expression>

<logical_or_expression> ::= <logical_or_expression> "||" <logical_and_expression>
                          | <logical_and_expression>

<logical_and_expression> ::= <logical_and_expression> "&&" <inclusive_or_expression>
                           | <inclusive_or_expression>

<inclusive_or_expression> ::= <inclusive_or_expression> "|" <exclusive_or_expression>
                            | <exclusive_or_expression>

<exclusive_or_expression> ::= <exclusive_or_expression> "^" <and_expression>
                            | <and_expression>

<and_expression> ::= <and_expression> "&" <equality_expression>
                   | <equality_expression>

<equality_expression> ::= <equality_expression> "==" <relational_expression>
                        | <equality_expression> "!=" <relational_expression>
                        | <relational_expression>

<relational_expression> ::= <relational_expression> ">" <shift_expression>
                          | <relational_expression> "<" <shift_expression>
                          | <relational_expression> ">=" <shift_expression>
                          | <relational_expression> "<=" <shift_expression>
                          | <shift_expression>

<shift_expression> ::= <shift_expression> ">>" <addictive_expression>
                     | <shift_expression> "<<" <addictive_expression>
                     | <addictive_expression>

<addictive_expression> ::= <addictive_expression> "+" <multiplicative_expression>
                         | <addictive_expression> "-" <multiplicative_expression>
                         | <multiplicative_expression>

<multiplicative_expression> ::= <multiplicative_expression> "*" <unary_expression>
                              | <multiplicative_expression> "/" <unary_expression>
                              | <multiplicative_expression> "%" <unary_expression>
                              | <unary_expression>

<unary_expression> ::= "++" <unary_expression>
                     | "--" <unary_expression>
                     | "+" <unary_expression>
                     | "-" <unary_expression>
                     | "!" <unary_expression>
                     | "~" <unary_expression>
                     | "size" <unary_expression>
                     | <postfix_expression>

<postfix_expression> ::= <postfix_expression> "++"
                       | <postfix_expression> "--"
                       | <primary_expression>

<primary_expression> ::= <integer_literal>
                       | <floating_literal>
                       | <character_literal>
                       | <string_literal>
                       | <boolean_literal>
                       | "(" <expression> ")"
                       | IDENTIFIER

<integer_literal> ::= INTEGER

<floating_literal> ::= FLOAT

<character_literal> ::= CHARACTER

<string_literal> ::= STRING

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

你能帮我理解一下吗?我在互联网上搜索了很多关于这个的内容。但是我找不到合适的解决方案。

谢谢

我想问题不在于你不知道如何编写 BNF 语法。相反,您不知道应该编写哪种语法。换句话说,如果有人告诉您运算符的优先顺序,您可以毫不费力地写下解析具有该特定优先顺序的运算符的语法。但是您不知道应该使用哪种优先顺序。

不幸的是,没有关于运算符优先级的国际高级委员会,我所知道的任何宗教也没有提供精神参考,包括神圣启发的运算符优先级规则。

对于某些运算符,优先顺序相当明确:例如,采用 BODMAS 是有充分理由的,但主要原因是大多数人已经根据这些规则编写了算术。你当然可以根据群论提出一个看似合理的数学论证,说明为什么乘法优先于加法似乎很自然,但总会有人怀疑这个论证是根据 post facto 来证明 already-made 决定的合理性。尽管如此,使乘法绑定比加法更紧密的论点也适用于 bitwise-and 优先于 bitwise-or,或 boolean-and 优先于 boolean-or。 (尽管我注意到 C 编译器编写者不相信程序员会有那种特殊的直觉,因为如果您在此类表达式中省略多余的括号,大多数现代编译器都会发出警告。)

我认为几乎每个人都会同意的一个优先关系是直观的,即算术运算符优先于比较运算符,比较运算符优先于运算符优先于布尔运算符。大多数程序员会发现一种语言选择将 a > b + 7 解释为意思是“将 ab 进行比较的布尔值加七”。同样,以 (a > 0) || (b > 0) 以外的任何方式解释 a > 0 || b > 0 可能被认为是离谱的。但是其他优先级选择似乎更加随意,并且并非所有语言都使它们相同。 (例如“不等于”和“大于”的相对优先级,或者“异或”和“异或”的相对优先级。

那么语言设计新手应该做什么呢?好吧,首先求助于您自己的直觉,特别是如果您经常使用相关运算符。此外,询问您的朋友、联系人和潜在的语言用户他们的想法。看看其他语言做了什么,但要用批判的眼光看待。在 language-specific 论坛上搜索投诉。很可能是最初的语言设计者做出了一个不幸的(甚至是愚蠢的)选择,现在不能改变这个选择,因为它会破坏太多现有的程序。 (这就是为什么您担心运算符优先级是一件好事:弄错可能会带来严重的未来问题。)

直接实验也有帮助,尤其是对于很少一起使用的运算符。使用运算符定义一个似是而非的表达式,然后根据各种可能的规则将其写出两次(或更多次),省略括号。哪一个看起来更容易理解? (再次招募你的朋友并问他们同样的问题。)

如果最后实在无法决定某对运算符之间的优先顺序是什么,可以考虑另一种解决方案:让这些运算符必须有括号。 (这是 C 编译器抱怨在布尔表达式中省略多余括号的意图。)