如何处理表达式解析器中的一元减法和求幂
How to deal with unary minus and exponentiation in an expression parser
我知道取幂比一元负有更高的优先级。但是,如果我基于它构建一个表达式解析器,我仍然无法解析像 2---3 这样的表达式。为了处理这些,我发现我还需要向因子生产规则添加一元减法处理,该规则的优先级高于求幂。这是通常处理一元减法和取幂的方式吗?我没有在网上或书中找到任何关于这种特殊情况的内容。我想知道让求幂运算符和一元运算符具有相同的优先级对你有帮助吗?
我正在手工制作递归下降解析器,我尝试将幂和一元产生式规则合并在一起,但它似乎没有用。起作用的是以下 EBNF
factor = '(' expression ')' | variable | number | '-' factor
power = factor { '^' factor }
unaryTerm = ['-' | '+'] power
term = unaryTerm { factorOp unaryTerm }
expression = term { termOp term }
termOp = '+' | '-'
factorOp = '*' | '/'
除非您有特殊要求,否则将一元减法和求幂放在同一个非终结符中会很好,因为求幂是右结合的:(Yacc/bison 语法)
atom: ID
| '(' expr ')'
factor
: atom
| '-' factor
| atom '^' factor
term: factor
| term '*' factor
expr: term
| expr '+' term
| expr '-' term
实际上,要使此语法有意义,实际上需要求幂是右结合的。考虑替代方案,使用左结合运算符。
假设我们有两个运算符,⊕ 和 ≀,其中 ⊕ 具有结合性并且比 ≀ 绑定得更紧密,因此 ≀ a ⊕ b
是 ≀(a ⊕ b)
。
因为 ⊕ 是左结合的,我们希望 a ⊕ b ⊕ c
被解析为 (a ⊕ b) ⊕ c
。但随后我们发现了一个奇怪的现象。 a ⊕ ≀ b ⊕ c
与 (a ⊕ ≀b) ⊕ c)
相同还是与 a ⊕ ≀(b ⊕ c))
相同?这两个选项似乎都违反了简单模式。 [注1]
当然,可以为每种情况编写明确的语法,但对于只看优先级图表的程序员来说,哪一种语法不那么令人惊讶?最有可能的结果是风格要求 ≀表达式总是完全用括号括起来,即使括号是多余的。 (C 风格指南中充满了此类建议,许多编译器会责备您使用正确但 "unintuitive" 的表达式。)
备注:
- 如果您使用优先级声明,您将得到
a ⊕ ≀(b ⊕ c))
,这可能直观也可能不直观,具体取决于您的直觉。
我知道取幂比一元负有更高的优先级。但是,如果我基于它构建一个表达式解析器,我仍然无法解析像 2---3 这样的表达式。为了处理这些,我发现我还需要向因子生产规则添加一元减法处理,该规则的优先级高于求幂。这是通常处理一元减法和取幂的方式吗?我没有在网上或书中找到任何关于这种特殊情况的内容。我想知道让求幂运算符和一元运算符具有相同的优先级对你有帮助吗?
我正在手工制作递归下降解析器,我尝试将幂和一元产生式规则合并在一起,但它似乎没有用。起作用的是以下 EBNF
factor = '(' expression ')' | variable | number | '-' factor
power = factor { '^' factor }
unaryTerm = ['-' | '+'] power
term = unaryTerm { factorOp unaryTerm }
expression = term { termOp term }
termOp = '+' | '-'
factorOp = '*' | '/'
除非您有特殊要求,否则将一元减法和求幂放在同一个非终结符中会很好,因为求幂是右结合的:(Yacc/bison 语法)
atom: ID
| '(' expr ')'
factor
: atom
| '-' factor
| atom '^' factor
term: factor
| term '*' factor
expr: term
| expr '+' term
| expr '-' term
实际上,要使此语法有意义,实际上需要求幂是右结合的。考虑替代方案,使用左结合运算符。
假设我们有两个运算符,⊕ 和 ≀,其中 ⊕ 具有结合性并且比 ≀ 绑定得更紧密,因此 ≀ a ⊕ b
是 ≀(a ⊕ b)
。
因为 ⊕ 是左结合的,我们希望 a ⊕ b ⊕ c
被解析为 (a ⊕ b) ⊕ c
。但随后我们发现了一个奇怪的现象。 a ⊕ ≀ b ⊕ c
与 (a ⊕ ≀b) ⊕ c)
相同还是与 a ⊕ ≀(b ⊕ c))
相同?这两个选项似乎都违反了简单模式。 [注1]
当然,可以为每种情况编写明确的语法,但对于只看优先级图表的程序员来说,哪一种语法不那么令人惊讶?最有可能的结果是风格要求 ≀表达式总是完全用括号括起来,即使括号是多余的。 (C 风格指南中充满了此类建议,许多编译器会责备您使用正确但 "unintuitive" 的表达式。)
备注:
- 如果您使用优先级声明,您将得到
a ⊕ ≀(b ⊕ c))
,这可能直观也可能不直观,具体取决于您的直觉。