问题描述
我想为数学程序编写一个新的解析器。当我为此编写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出于充分的理由而被采用,但是主要原因是大多数人已经按照这些规则编写了算术运算。当然,您可以基于群论提出一个合理的数学论证,即为什么在乘法运算上优先于加法看起来很自然,但始终会怀疑该论证是在事后产生的,以证明已经存在做出决定。尽管如此,使乘法绑定比加法绑定更紧密的论点也适用于赋予按位和优先于按位或,或使布尔优先于布尔或。 (尽管我注意到,C编译器作者不相信程序员会有这种特殊的直觉,因为如果您在此类表达式中省略多余的括号,则大多数现代编译器都会发出警告。)
我认为几乎每个人都会同意的一种优先关系是直观的,即给予算术运算符优先于比较运算符,并且比较运算符优先运算符优先于布尔运算符。大多数程序员会发现一种语言,该语言选择将a > b + 7
解释为“将a
与b
比较的布尔值加7”。同样,以a > 0 || b > 0
以外的任何方式解释(a > 0) || (b > 0)
可能被认为是荒唐的。但是其他优先级选择似乎更加随意,并且并非所有语言都使它们相同。 (例如,“不等于”和“大于”或“排他性或”和“包含性或”的相对优先级。
那么新手语言设计师该做什么?好吧,首先请诉诸于您自己的直觉,尤其是如果您经常使用有问题的运算符。另外,询问您的朋友,联系人和潜在的语言用户他们的想法。看看其他语言做了什么,但是要用批判的眼光来看。在特定语言的论坛上搜索投诉。最初的语言设计者很可能做出了不幸的(甚至是愚蠢的)选择,并且现在无法更改该选择,因为这会破坏太多现有的程序。 (这就是为什么您担心操作符优先级是一件好事:弄错它会带来严重的未来问题。)
直接实验也可以提供帮助,尤其是对于很少一起使用的运算符。使用运算符定义一个合理的表达式,然后根据各种可能的规则将其写出两次(或更多次),并省略括号。哪个看起来更容易理解? (再次,招募您的朋友,然后问他们同样的问题。)
最后,如果您真的不能确定一对特定运算符之间的优先顺序是什么,则可以考虑另外一种解决方案:对这些运算符强制使用括号。 (这是C编译器抱怨删除布尔表达式中多余的括号的目的。)