修复给定代码中的冲突? “25 shift/reduce 冲突 [-Wconflicts-sr]”
Fixing conflict in given code? "25 shift/reduce conflicts [-Wconflicts-sr] "
// Lex 文件:for.l
alpha [A-Za-z]
digit [0-9]
%%
[\t \n]
for return FOR;
{digit}+ return NUM;
{alpha}({alpha}|{digit})* return ID;
"<=" return LE;
">=" return GE;
"==" return EQ;
"!=" return NE;
"||" return OR;
"&&" return AND;
. return yytext[0];
%%
// Yacc 文件: for.y
%{
#include<stdio.h>
#include<stdlib.h>
%}
%token ID NUM FOR LE GE EQ NE OR AND
%right "="
%left OR AND
%left '>' '<' LE GE EQ NE
%left '+' '-'
%left '*' '/'
%right UMINUS
%left '!'
%%
S : ST {printf("Input accepted\n"); exit(0);}
ST : FOR '(' E ';' E2 ';' E ')' DEF
;
DEF : '{' BODY '}'
| E';'
| ST
|
;
BODY : BODY BODY
| E ';'
| ST
|
;
E : ID '=' E
| E '+' E
| E '-' E
| E '*' E
| E '/' E
| E '<' E
| E '>' E
| E LE E
| E GE E
| E EQ E
| E NE E
| E OR E
| E AND E
| E '+' '+'
| E '-' '-'
| ID
| NUM
;
E2 : E'<'E
| E'>'E
| E LE E
| E GE E
| E EQ E
| E NE E
| E OR E
| E AND E
;
%%
#include "lex.yy.c"
main()
{
printf("Enter the expression:\n");
yyparse();
}
当我运行它时,它显示:
warning: 25 shift/reduce conflicts [-Wconflicts-sr]
warning: 4 reduce/reduce conflicts [-Wconflicts-rr]
我该如何解决?
编译方法:
$ lex c.l
$ yacc c.y
你的语法有很多问题;这是最明显的:
您允许 DEF
为空。也就是说
for (i=0;i<1;i++) for (j=0;j<1;j++)
可以是两个 for
具有空主体的语句,或者一个 for
语句,其主体是另一个 for
语句(其主体为空)。所以空产生式使语法有歧义。
BODY: BODY BODY
是指数级的歧义,没有优先级声明可以弥补。由于 BODY
.
有一个(也是不必要的)空生产这一事实使问题变得更糟
E '+' '+'
暗示 i++
中的两个 + 是单独的标记(事实上,您的 flex 定义没有将 ++ 识别为单个 tomen,unlime,例如 <=。这意味着您的语法会认为 i + +
是一个有效的 post 增量。也许那是故意的,但它肯定不同于我所知道的任何语言。无论如何,结果会证明 + 的优先级声明将适用,这是不正确的:3*j++
应该被解析为 3*(j++)
,而不是 (3*j)++
。(post-递减运算符也是如此。)
// Lex 文件:for.l
alpha [A-Za-z]
digit [0-9]
%%
[\t \n]
for return FOR;
{digit}+ return NUM;
{alpha}({alpha}|{digit})* return ID;
"<=" return LE;
">=" return GE;
"==" return EQ;
"!=" return NE;
"||" return OR;
"&&" return AND;
. return yytext[0];
%%
// Yacc 文件: for.y
%{
#include<stdio.h>
#include<stdlib.h>
%}
%token ID NUM FOR LE GE EQ NE OR AND
%right "="
%left OR AND
%left '>' '<' LE GE EQ NE
%left '+' '-'
%left '*' '/'
%right UMINUS
%left '!'
%%
S : ST {printf("Input accepted\n"); exit(0);}
ST : FOR '(' E ';' E2 ';' E ')' DEF
;
DEF : '{' BODY '}'
| E';'
| ST
|
;
BODY : BODY BODY
| E ';'
| ST
|
;
E : ID '=' E
| E '+' E
| E '-' E
| E '*' E
| E '/' E
| E '<' E
| E '>' E
| E LE E
| E GE E
| E EQ E
| E NE E
| E OR E
| E AND E
| E '+' '+'
| E '-' '-'
| ID
| NUM
;
E2 : E'<'E
| E'>'E
| E LE E
| E GE E
| E EQ E
| E NE E
| E OR E
| E AND E
;
%%
#include "lex.yy.c"
main()
{
printf("Enter the expression:\n");
yyparse();
}
当我运行它时,它显示:
warning: 25 shift/reduce conflicts [-Wconflicts-sr]
warning: 4 reduce/reduce conflicts [-Wconflicts-rr]
我该如何解决?
编译方法:
$ lex c.l
$ yacc c.y
你的语法有很多问题;这是最明显的:
您允许
DEF
为空。也就是说for (i=0;i<1;i++) for (j=0;j<1;j++)
可以是两个
for
具有空主体的语句,或者一个for
语句,其主体是另一个for
语句(其主体为空)。所以空产生式使语法有歧义。BODY: BODY BODY
是指数级的歧义,没有优先级声明可以弥补。由于BODY
. 有一个(也是不必要的)空生产这一事实使问题变得更糟
E '+' '+'
暗示i++
中的两个 + 是单独的标记(事实上,您的 flex 定义没有将 ++ 识别为单个 tomen,unlime,例如 <=。这意味着您的语法会认为i + +
是一个有效的 post 增量。也许那是故意的,但它肯定不同于我所知道的任何语言。无论如何,结果会证明 + 的优先级声明将适用,这是不正确的:3*j++
应该被解析为3*(j++)
,而不是(3*j)++
。(post-递减运算符也是如此。)