为什么 YACC 不产生 shift-reduce 冲突?

Why doesn't YACC generate shift-reduce conflict?

试图理解 shift-reduce 冲突并解决它们。

我有以下 YACC 代码,我期待它发生 shift-reduce 冲突,但 Bison 没有生成任何此类警告

%%

lang_cons: /* empty */
         | declaraion // SEMI_COLON
         | func
    ;

declaraion : keyword ID
    ; 

func : keyword ID SEMI_COLON
    ; 

keyword : INT
    | FLOAT
    ;

%%

但是如果我在第二条规则(即 | declaraion SEMI_COLON )中取消注释 SEMI_COLON ,我会遇到 shift-reduce 冲突。在这种情况下,我期待减少减少冲突。请帮助我理解这个烂摊子!

PS:考虑输入,

    1) int varName
    2) int func; 

如果您给 bison -v 命令行标志,它将生成一个 .output 文件,其中包含生成的状态机,这可能会帮助您了解发生了什么。

请注意,bison 实际上解析了增强语法,它由带有附加规则的语法组成

start': start END

其中 END 是一个特殊标记,其代码为 0,表示输入结束,而 start 是您的语法用作开始符号的任何内容。 (这确保了 bison 解析器不会静默地忽略有效输入末尾的垃圾。)

这使您的原始语法明确无误;在看到 varName 之后,前瞻将是 END,在这种情况下 declaration 减少,或者 ';',这将被移动(随后减少 func当看到下面的END时)。

在您的第二个语法中,冲突涉及减少 declaration 或移动分号之间的选择。如果分号是 declaration 的一部分,那么您会看到 reduce/reduce 冲突。