为什么 1*2+3 被解析为 1*(2+3) 即使没有声明运算符优先级或结合性?
Why 1*2+3 is parsed as 1*(2+3) even though operator precedence or associativity is not declared?
我使用 fsyacc(yacc for fsharp)编写了一个小型解析器。语法类似于
Expr:=
| INT { Cst }
| Expr PLUS Expr { Op("+", , ) }
| Expr TIMES Expr { Op("*", , ) }
然后,在没有声明优先级或结合性的情况下,我将“1*2+3”解析为
Op ("*",Cst 1,Op ("+",Cst 2,Cst 3)
为什么?
如果您没有像您所描述的那样在歧义语法中为您的标记声明优先级和关联性,则默认情况下 yacc 将解决由此产生的 shift/reduce 冲突,如果移位。这具有使规则向右递归的效果,因此运算符将显示为从右到左分组。
如果您 定义优先规则,它们所做的是解决 shift/reduce 有利于更高优先级(令牌或规则)的冲突,或者,如果相同优先级,支持 %right
的移位和 %left
的减少。这基本上就是优先级设置所做的全部工作,因此如果您想这样做的话,有时可以使用它们以与“优先级”无关的方式解决冲突。但是对于一个简单的中缀表达式语法,它们基本上就是你想要的。
我使用 fsyacc(yacc for fsharp)编写了一个小型解析器。语法类似于
Expr:=
| INT { Cst }
| Expr PLUS Expr { Op("+", , ) }
| Expr TIMES Expr { Op("*", , ) }
然后,在没有声明优先级或结合性的情况下,我将“1*2+3”解析为
Op ("*",Cst 1,Op ("+",Cst 2,Cst 3)
为什么?
如果您没有像您所描述的那样在歧义语法中为您的标记声明优先级和关联性,则默认情况下 yacc 将解决由此产生的 shift/reduce 冲突,如果移位。这具有使规则向右递归的效果,因此运算符将显示为从右到左分组。
如果您 定义优先规则,它们所做的是解决 shift/reduce 有利于更高优先级(令牌或规则)的冲突,或者,如果相同优先级,支持 %right
的移位和 %left
的减少。这基本上就是优先级设置所做的全部工作,因此如果您想这样做的话,有时可以使用它们以与“优先级”无关的方式解决冲突。但是对于一个简单的中缀表达式语法,它们基本上就是你想要的。