Parsing Shift减少以操作开始的规则在YACC中的冲突

Parsing Shift减少以操作开始的规则在YACC中的冲突,parsing,yacc,lex,shift-reduce-conflict,shift-reduce,Parsing,Yacc,Lex,Shift Reduce Conflict,Shift Reduce,我的书中说,当令牌是一个变量时,会有一个shift-reduce冲突,因为yacc将代码转换为这个变量 %token A B %% start: {printf("Starting…\n");} A A | A B; 我不明白。这里是第二条开始移位的规则,空规则减少。start的第一个规则也会发生变化,因此第一个输入需要A,而第二个规则需要B。这怎么会有冲突?据我所知,一条规则必须减少,另一条规则应该改变,而这两条规则对于此类冲突的输入应该使用相同的标记。但是,有一条规则在这里同时移动和减

我的书中说,当令牌是一个变量时,会有一个shift-reduce冲突,因为yacc将代码转换为这个变量

%token A B
%%
start:  {printf("Starting…\n");} A A
 | A B;

我不明白。这里是第二条开始移位的规则,空规则减少。start的第一个规则也会发生变化,因此第一个输入需要A,而第二个规则需要B。这怎么会有冲突?据我所知,一条规则必须减少,另一条规则应该改变,而这两条规则对于此类冲突的输入应该使用相同的标记。但是,有一条规则在这里同时移动和减少(第一条规则),而第二条规则只移动,而且它们在这些操作之后期望不同的toke。

冲突在于,在移动A之前,它不知道是否减少空规则(运行操作)。两条规则都期望A作为第一个标记,因此,您可以改变/减少冲突。应该做什么取决于第二个标记,这样语法就不会模棱两可,冲突可以通过使用更多的前瞻(使用GLR或回溯解析器)来解决。

那么,当任何两个规则同时需要相同的标记时,shift/reduce总是会发生冲突吗?这里不应该有一个规则减少和一个规则转移的关系吗?因为我相信如果printf声明不存在,即使他们期望相同的标记,也不会有冲突@只有当他们需要做不同的动作时——如果他们都需要转换,那么就没有问题(也没有冲突)。如果从第一条规则中删除初始操作,则两者都需要转换。我可以在哪里学习此主题?我找不到任何好书,他们几乎没有描述它@ChrisThe classic有一个关于LR shift/reduce解析的部分。请注意,在转换后代码中,操作按照
empty
规则进行——这就是转换的要点;它将所有操作移动到规则的末尾。
%token A B
%%
start: empty A A
 | A B;
empty: {printf("Starting…\n");} ;