在yacc中的%left和%right

16
{%
#include<stdio.h>
#include<stdlib.h>
%}
  
%token ID NUM IF THEN LE GE EQ NE OR AND ELSE

%right '='
%left AND OR
%left '<' '>' LE GE EQ NE
%left '+''-'
%left '*''/'
%right UMINUS
%left '!'

%%

上面提到的代码是一个简单的IF ELSE程序的yacc部分。

%right%left是什么意思?

2个回答

28

我知道这是一个老问题,但如果有人正在寻找这些信息:

%left%right%nonassoc定义了yacc如何解决运算符的重复。 如果你有:

1 + 2 + 3

这两个运算符具有相同的优先级(它们是相同的 :)),在这种情况下,yacc可以解决:

// using %left
(1 + 2) + 3
或者:
// using %right
1 + (2 + 3)

最后:

//using %nonassoc
1 + 2 + 3 is considered illegal and a syntax error!

您可以在这里阅读更多内容。


12

%left%right 指定了一个运算符的结合性。一个运算的结合性决定了同一优先级下两个运算符中哪一个先进行。

假设我们有以下语法规则:

exp ::= exp + exp
exp ::= ID
假设我们要解析表达式 x+y-z。由于加法和减法的优先级相同,所以这个表达式可以被解释为 (x+y)-z 或 x+(y-z)。这似乎不是什么大问题,但它会导致语法上的歧义。
除了解析问题和理论之外,假设我们正在解析表达式 6+5-7,并且我们的语言只能使用自然数,并在下溢时抛出异常。结果 (6+5)-7(4)将不等于6 +(5-7) (异常),因此我们无法预测结果——除非我们通过指定运算符的结合性来定义计算顺序。还考虑操作数是可能具有副作用的函数的表达式,如 f()+g()+h()

4
由于 %left '+' '-' 在下方,所以 %left '*' '/' 的优先级高于 + 和 - - Ani

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接