转移/减少野牛冲突 [英] Shift/reduce conflicts in bison
问题描述
我是Bison
的新手,但遇到了shift/reduce冲突的问题...我正在尝试从文件加载到array data[]
:
I'm new to Bison
and I'm having trouble with shift/reduce conflicts... I'm trying to load from file to array data[]
:
struct _data
{
char name[50];
char surname[50];
int year;
} data[1000];
这是我的野牛代码的一部分:
Here is part of my bison code:
%token ID NUM NL EOF
%%
File : List EOF
;
List : Record
| List Record
;
Record : Name Surname Year NL { count++; }
| NL { count++; }
| /*empty*/
;
Name : ID { strcpy(data[count].name, yytext); }
;
Surname: ID { strcpy(data[count].surname, yytext); }
;
Year : NUM { data[count].year= atoi(yytext); }
;
%%
我收到此错误:
conflicts: 5 shift/reduce
知道我哪里出错了吗?
推荐答案
您可以使用-v
选项获取bison
来生成包含更多信息的.output
文件,这些信息可以帮助您诊断移位/减少冲突.特别是,它将显示每个解析器状态,包括项目列表,并指出哪些状态有冲突.
You can use the -v
option to get bison
to produce an .output
file containing a lot more information which can help you diagnose shift/reduce conflicts. In particular, it will show you every parser state, including the list of items, and also indicate which states have conflicts.
但是在这种情况下,问题非常简单.剥夺其要点,您将拥有:
But in this case, the problem is pretty simple. Stripped to its essentials you have:
List: Record
| List Record
;
Record: Something
| /* Nothing */
;
忽略Something
的定义是什么,问题是List
可以由任意数量的Records
组成,一个接一个,而Record
可以为空.这意味着没有什么可以像任何数量的空Records
一样被解析,这完全是模棱两可的.输入中的任何两个连续Somethings
可以用0、1、2、42或273个空Records
分隔.由于解析器不知道是开始解析新的Something
(移位)还是发出空的Record
(减少),因此它抱怨存在移位/减少冲突.
Ignoring what the definition of Something
is, the problem is that a List
can consist of any number of Records
, one after another, and a Record
can be empty. That means that nothing can be parsed as any number of empty Records
, which is totally ambiguous. Any two consecutive Somethings
in the input could be separated by 0, 1, 2, 42, or 273 empty Records
. Since the parser can't know whether to start parsing a new Something
(shift) or to emit an empty Record
(reduce), it complains that there is a shift/reduce conflict.
在这种情况下,解决方案非常简单.我们可以看到,非空的Something
必须以NL
结尾;大概的目的是File
由任意数量的Records
组成,每个Records
都在其自己的行上.这样我们可以重写:
In this case the solution is pretty simple. We can see that a non-empty Something
must end with a NL
; presumably the intent was that the File
consists of any number of Records
, each on its own line. So we can rewrite:
File: List EOF
;
List: Record
| List NL Record
;
Record: Name Surname Year
| /* Empty */
;
现在,Record
(是否为空)之后必须紧跟EOF
或NL
.不能直接跟随另一个Record
.
Now a Record
, empty or not, must be followed by either an EOF
or a NL
. It cannot be directly followed by another Record
.
这篇关于转移/减少野牛冲突的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!