%%
%token IDENTIFIER NUMBER SIZEOF
%token PTR DOT
%token TYPEDEF INT FLOAT VOID STRUCT
%token IF ELSE WHILE RETURN FOR DO SWITCH CASE BREAK DEFAULT CONTINUE
%token PRINTF SCANF
%token STRING
%token PREPROC
%left GT LT LE GE NE EQ
%left AND OR
%right '='
%left '+' '-'
%left '*' '/'
%%
start: Function
| Declaration
;
Function: Type IDENTIFIER '(' ArgList ')' CompoundStmt
| Type IDENTIFIER '('')' CompoundStmt
;
ArgList: ArgList ',' Arg
| Arg
;
Arg: Type IDENTIFIER
;
Type: INT
| FLOAT
| VOID
;
CompoundStmt: '{' StmtList '}'
| '{''}'
;
StmtList: StmtList Stmt
| Stmt
;
Stmt: WhileStmt
| Declaration
| ForStmt
| IfStmt
| PrintStmt
| ScanStmt
| ';'
;
WhileStmt: WHILE '(' Expr ')' Stmt
| WHILE '(' Expr ')' CompoundStmt
;
ForStmt: FOR '(' Expr ';' Expr ';' Expr ')' Stmt
| FOR '(' Expr ';' Expr ';' Expr ')' CompoundStmt
;
IfStmt: IF '(' Expr ')' Stmt
| IF '(' Expr ')' CompoundStmt
;
PrintStmt: PRINTF '(' Expr ')' ';'
;
ScanStmt: SCANF '(' Expr ')' ';'
;
Expr: Expr LE Expr
| Expr GE Expr
| Expr GT Expr
| Expr LT Expr
| Expr NE Expr
| Expr EQ Expr
| Assignment
| ArrayUsage
;
ArrayUsage: IDENTIFIER '[' Assignment ']'
;
Declaration: Type Assignment ';'
| Assignment ';'
| FunctionCall ';'
| ArrayUsage ';'
| Type ArrayUsage ';'
| StructStmt ';'
;
StructStmt: STRUCT IDENTIFIER '{' Type Assignment '}'
;
FunctionCall: IDENTIFIER '('')'
| IDENTIFIER '(' Assignment ')'
;
Assignment: IDENTIFIER '=' Assignment
| IDENTIFIER '=' FunctionCall
| IDENTIFIER '=' ArrayUsage
| ArrayUsage '=' Assignment
| IDENTIFIER ',' Assignment
| NUMBER ',' Assignment
| IDENTIFIER '+' Assignment
| IDENTIFIER '-' Assignment
| IDENTIFIER '*' Assignment
| IDENTIFIER '/' Assignment
| NUMBER '+' Assignment
| NUMBER '-' Assignment
| NUMBER '*' Assignment
| NUMBER '/' Assignment
| '\'' Assignment '\''
| '(' Assignment ')'
| '-' Assignment
| '-' NUMBER
| '-' IDENTIFIER
| NUMBER
| IDENTIFIER
;
%%
include"lex.yy.c"
int main(int argc,char *argv[])
{
FILE *file;
file = fopen(argv[1], "r");
if (!file)
{
fprintf(stderr, "Could not open %s\n", argv[1]);
exit(1);
}
yyin = file;
if(!yyparse())
printf("\nParsing done");
else
printf("\nParsing failed");
fclose(yyin);
return 0;
}
跑步时:
yacc scanner.y // scanner.y being by yacc code
我收到以下错误:
yacc: 22 reduce/reduce conflicts.
如果有两个或更多规则适用于相同的输入序列,则会发生减少/减少冲突。这通常表明语法中存在严重错误。
这里有什么错误?
答案 0 :(得分:2)
问题来自规则中的含糊不清
Assignment: '-' Assignment
| '-' NUMBER
| '-' IDENTIFIER
| NUMBER
| IDENTIFIER
如果您有输入- IDENTIFIER
或(- NUMBER
),您可以在一步(上面的第2或第3规则)或两步(第4或第5步)中将其缩小为Assignment
规则,然后是第1条规则)。最简单的解决方法是删除上面的第2和第3条规则,这将迫使它总是减少两步。您可能还希望通过定义假'-' Assignment
标记(优先级高于所有二元运算符)来赋予UNARY
规则更高的优先级,lexer永远不会返回,但允许您说
Assignment: '-' Assignment %prec UNARY
赋予该规则更高的优先权。
答案 1 :(得分:0)
你可以使用带有-v选项的bison,你会得到详细的输出。我收到了
State 32 conflicts: 11 reduce/reduce
State 33 conflicts: 11 reduce/reduce
这些州看起来像这样:
State 32
38 ArrayUsage: IDENTIFIER . '[' Assignment ']'
48 Assignment: IDENTIFIER . '=' Assignment
49 | IDENTIFIER . '=' FunctionCall
50 | IDENTIFIER . '=' ArrayUsage
52 | IDENTIFIER . ',' Assignment
54 | IDENTIFIER . '+' Assignment
55 | IDENTIFIER . '-' Assignment
56 | IDENTIFIER . '*' Assignment
57 | IDENTIFIER . '/' Assignment
66 | '-' IDENTIFIER .
68 | IDENTIFIER .
'=' shift, and go to state 18
'+' shift, and go to state 19
'-' shift, and go to state 20
'*' shift, and go to state 21
'/' shift, and go to state 22
',' shift, and go to state 24
'[' shift, and go to state 25
GT reduce using rule 66 (Assignment)
GT [reduce using rule 68 (Assignment)]
LT reduce using rule 66 (Assignment)
LT [reduce using rule 68 (Assignment)]
LE reduce using rule 66 (Assignment)
LE [reduce using rule 68 (Assignment)]
GE reduce using rule 66 (Assignment)
GE [reduce using rule 68 (Assignment)]
NE reduce using rule 66 (Assignment)
NE [reduce using rule 68 (Assignment)]
EQ reduce using rule 66 (Assignment)
EQ [reduce using rule 68 (Assignment)]
')' reduce using rule 66 (Assignment)
')' [reduce using rule 68 (Assignment)]
'}' reduce using rule 66 (Assignment)
'}' [reduce using rule 68 (Assignment)]
';' reduce using rule 66 (Assignment)
';' [reduce using rule 68 (Assignment)]
']' reduce using rule 66 (Assignment)
']' [reduce using rule 68 (Assignment)]
'\'' reduce using rule 66 (Assignment)
'\'' [reduce using rule 68 (Assignment)]
$default reduce using rule 66 (Assignment)
State 33
53 Assignment: NUMBER . ',' Assignment
58 | NUMBER . '+' Assignment
59 | NUMBER . '-' Assignment
60 | NUMBER . '*' Assignment
61 | NUMBER . '/' Assignment
65 | '-' NUMBER .
67 | NUMBER .
'+' shift, and go to state 26
'-' shift, and go to state 27
'*' shift, and go to state 28
'/' shift, and go to state 29
',' shift, and go to state 30
GT reduce using rule 65 (Assignment)
GT [reduce using rule 67 (Assignment)]
LT reduce using rule 65 (Assignment)
LT [reduce using rule 67 (Assignment)]
LE reduce using rule 65 (Assignment)
LE [reduce using rule 67 (Assignment)]
GE reduce using rule 65 (Assignment)
GE [reduce using rule 67 (Assignment)]
NE reduce using rule 65 (Assignment)
NE [reduce using rule 67 (Assignment)]
EQ reduce using rule 65 (Assignment)
EQ [reduce using rule 67 (Assignment)]
')' reduce using rule 65 (Assignment)
')' [reduce using rule 67 (Assignment)]
'}' reduce using rule 65 (Assignment)
'}' [reduce using rule 67 (Assignment)]
';' reduce using rule 65 (Assignment)
';' [reduce using rule 67 (Assignment)]
']' reduce using rule 65 (Assignment)
']' [reduce using rule 67 (Assignment)]
'\'' reduce using rule 65 (Assignment)
'\'' [reduce using rule 67 (Assignment)]
$default reduce using rule 65 (Assignment)
正如您所看到的,这两种状态下的相同令牌可以减少使用不同的规则。
问题在于分配规则:
Assignment: IDENTIFIER '=' Assignment
| IDENTIFIER '=' FunctionCall
| IDENTIFIER '=' ArrayUsage
| ArrayUsage '=' Assignment
| IDENTIFIER ',' Assignment
| NUMBER ',' Assignment
| IDENTIFIER '+' Assignment
| IDENTIFIER '-' Assignment
| IDENTIFIER '*' Assignment
| IDENTIFIER '/' Assignment
| NUMBER '+' Assignment
| NUMBER '-' Assignment
| NUMBER '*' Assignment
| NUMBER '/' Assignment
| '\'' Assignment '\''
| '(' Assignment ')'
| '-' Assignment
| '-' NUMBER
| '-' IDENTIFIER
| NUMBER
| IDENTIFIER
;
我猜你应该使用特殊的一元减号和重写规则,如下所示:
Assignment: IDENTIFIER '=' Assignment
| IDENTIFIER '=' FunctionCall
| IDENTIFIER '=' ArrayUsage
| ArrayUsage '=' Assignment
| IDENTIFIER ',' Assignment
| NUMBER ',' Assignment
| IDENTIFIER '+' Assignment
| IDENTIFIER '-' Assignment
| IDENTIFIER '*' Assignment
| IDENTIFIER '/' Assignment
| NUMBER '+' Assignment
| NUMBER '-' Assignment
| NUMBER '*' Assignment
| NUMBER '/' Assignment
| '\'' Assignment '\''
| '(' Assignment ')'
| '-' Assignment
| UMINUS NUMBER
| UMINUS IDENTIFIER
| NUMBER
| IDENTIFIER
;
定义如下:
%token IDENTIFIER NUMBER SIZEOF UMINUS
并且做到了
%nonassoc UMINUS