为什么1*2+3被解析为1*(2+3),即使没有声明运算符优先级或关联性



我使用fsyacc(用于fsharp的yacc(来编写一个小型解析器。语法有点像

Expr:=
| INT                              { Cst $1           }  
| Expr PLUS  Expr                     { Op("+", $1, $3) }  
| Expr TIMES Expr                     { Op("*", $1, $3) }

然后,在没有声明优先级或结合性的情况下,我得到了";1*2+3";解析为

Op ("*",Cst 1,Op ("+",Cst 2,Cst 3)

为什么?

如果您没有像您描述的那样在不明确的语法中声明令牌的优先级和关联性,默认情况下,yacc将在shift的情况下解决由此产生的shift/reduce冲突。这具有使规则向右递归的效果,因此运算符将显示为从右到左分组。

如果确实定义了优先级规则,它们所做的是解决shift/reduce冲突,以支持更高的优先级(令牌或规则(,或者,如果优先级相同,则支持%right的shift和%left的reduce。这基本上就是优先级设置所做的一切,所以它们有时可以用来解决冲突,而与"优先级"无关;优先级";但对于一个简单的中缀表达式语法来说,它们基本上就是你想要的。