C++ 野牛转移/减少冲突无法修复

C++ 野牛转移/减少冲突无法修复,c++,compiler-construction,bison,shift-reduce-conflict,C++,Compiler Construction,Bison,Shift Reduce Conflict,我正在尝试为这件事添加更多的规则,它不断地给我这种转变/减少冲突,我不明白为什么会这样,我在过去的24小时里一直在尝试修复它 FuncDecl : RetType ID LPAREN Formals { //code here function($1, $2, $4); } RPAREN LBRACE Statements RBRACE {

我正在尝试为这件事添加更多的规则,它不断地给我这种转变/减少冲突,我不明白为什么会这样,我在过去的24小时里一直在尝试修复它

FuncDecl        : RetType ID LPAREN Formals {
                    //code here
                    function($1, $2, $4);

                } RPAREN LBRACE Statements RBRACE {
                    //some code here
                    function($1, $2, $4);
                }   
                | RetType ID LPAREN Formals RPAREN SC 
                {
                    // some code here
                    function($1, $2, $4);
                }
                ;
有人能给我解释一下发生了什么事吗?我怎样才能把这东西修好?? 注意:我需要在第一条规则中的
RBRACE
之前有代码


非常感谢各位,作为一种锻炼,让我们从中受益,就像SO帮助经常建议的那样。其实没那么难。由于使用bison处理代码段时遇到问题,因此在本例中,没有必要实际编译或运行MRE

这是文件(
conan.c
):

我已经删除了与问题无关的所有内容,但我仍然可以使用bison处理一个文件:

  • 不相关的非端子已转换为端子。(第2行)(如果它们是相关的,那么将它们转换为终端将使问题消失。因为它不是相关的,所以我们知道它们是无关的。)

  • 可以自由使用单字符标记,以使语法更具可读性,并避免将它们声明为标记。(出于同样的原因,我会将多字符标记(如
    T_FOR
    )转换为带引号的字符串(
    “FOR”

因此,这就给我留下了一个可读的六行代码段,现在可以用bison处理它(我需要添加bison调用以及由此产生的错误,以便使这个代码重复和完整)。错误消息现在具有预期的行号:

$ bison -o conan.c conan.y
conan.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
conan.y:4.34-58: warning: rule useless in parser due to conflicts [-Wother]
 FuncDecl: RetType ID '(' Formals { funcdecl($1, $2, $4); } ')' 
                                  ^^^^^^^^^^^^^^^^^^^^^^^^^
现在,解决问题。确实存在移位/减少冲突,因为在解析器到达以下位置后:

RetType ID ( Formals   )
                     ^
                     |------- lookahead
它必须决定是否执行中间规则操作(
fundecl($1,$2,$4);
)。但它还不知道这两个备选方案中的哪一个适用。第一种要求执行MRA;第二个没有。但是编译器直到看到右括号后面的标记才会知道,到那时就太晚了(根据LALR(1)算法)

如片段中所示,第一个备选方案中的MRA与第二个备选方案中的最终操作完全相同。如果真的是这样,那么解析器实际上不必做出决定。它可以在稍早的时候运行第二个备选方案的最终操作。但这个简单的解决方案并不像看上去那么简单,因为bison并没有试图查看两个MRA是否是相同的代码。它只是假设它们都是不同的,这将导致它仍然必须做出改变

另一方面,有一个简单得多的解决方案,因为不管是在右括号之前还是之后调用MRA,都没有任何区别。读取令牌时不会发生任何情况(除了推进行计数器之外,如果这是一个问题,则应该使用位置对象)。移动MRA将导致:

%token RetType Formals Statements
%token ID
%%
FuncDecl: RetType ID '(' Formals ')'  { funcdecl($1, $2, $4); }
                     '{' Statements '}' { funcdef($1, $2, $4, $8); }
        | RetType ID '(' Formals ')' ';'  { funcdecl($1, $2, $4) }
现在冲突消失了:

$ bison -o conan.c conan.y
$
这是因为MRA决策是在解析到达的点上做出的

RetType ID ( Formals )   {
                       ^
                       |----- lookahead

现在,展望就足以做出决定。(在另一种选择中,前瞻是
)。

非常感谢您的时间和解释,它成功了
$ bison -o conan.c conan.y
$
RetType ID ( Formals )   {
                       ^
                       |----- lookahead