如何编写yacc规则



我是yacc的新手,并不真正了解如何编写规则,尤其是处理递归定义

%token NUMBER
%token VARIABLE
%left '+' '-'
%left '*' '/' '%'
%left '(' ')'
%%
S: VARIABLE'='E {
printf("nEntered arithmetic expression is Validnn");
return 0;
}
E    : E'+'E 
| E'-'E 
| E'*'E 
| E'/'E 
| E'%'E 
| '('E')' 
| NUMBER 
| VARIABLE
;
%%

上面的例子很好,但当我把它改成下面的时候,它得到了">5移位/减少冲突";。

%token NUMBER
%token VARIABLE
%token MINS
%token PULS
%token MUL
%token DIV
%token MOD
%token LP
%token RP
%left MINS PULS
%left MUL DIV MOD
%left LP RP
%%
S: VARIABLE'='E {
printf("nEntered arithmetic expression is Validnn");
return 0;
}
E   : E operator E 
| LP E RP 
| NUMBER 
| VARIABLE
;
operator:   MINS 
| PULS
| MUL 
| DIV 
| MOD
;
%%

有人能告诉我这些例子之间有什么区别吗?非常感谢。。

区别在于与非终端operator的附加间接性。这有助于挫败你的优先声明。

先例是直接的,不是透明的。也就是说,它只在包括终端在内的直接生产中发挥作用。在你的第二个语法中,这个结果是:

operator:   MINS 
| PULS
| MUL 
| DIV 
| MOD
;

但在这部作品中,没有任何歧义需要解决。所有这些终端都被明确地简化为CCD_ 2。模糊性在生产中

E   : E operator E

而且这种生产没有终端。

相比之下,在你的第一个语法中,生成

E    : E'+'E 
| E'-'E 
| E'*'E 
| E'/'E 
| E'%'E 

(如果有更多的空白,则更容易阅读(确实包括可以相互比较其先验的终端。


Bison手册中解释了优先级声明的精确工作。如果有用的话,下面是我几年前在这个网站上的另一个答案中写的算法的描述。

最新更新