警告:"rule useless in parser due to conflicts" 在 Bison 中

Warning: "rule useless in parser due to conflicts" in Bison

我正在尝试制作一个 C 词法分析器,但我有一些警告:

rule useless in parser due to conflicts: sentenceList: sentenceList sentence
rule useless in parser due to conflicts: sentSelection: IF '(' expression ')' sentence
rule useless in parser due to conflicts: sentSelection: IF '(' expression ')' sentence ELSE sentence
rule useless in parser due to conflicts: sentSelection: SWITCH '(' expression ')' sentence
rule useless in parser due to conflicts: sentIteration: WHILE '(' expression ')' sentence
rule useless in parser due to conflicts: sentIteration: FOR '(' expression ';' expression ';' expression ')' sentence

这是警告来自的代码部分:

input:    /* nothing */
        | input line
;

line:     '\n'
        | sentence '\n' 
;
sentence :       sentComposed
                |sentSelection
                |sentExpression
                |sentIteration
;

sentComposed:     statementsList
                 |sentenceList
;

statementsList:      statement
                   | statementsList statement
;

sentenceList:    sentence
                |sentenceList sentence
;

sentExpression: expression ';'
              |';'
;

sentSelection: IF '(' expression ')' sentence
              |IF '(' expression ')' sentence ELSE sentence
              |SWITCH '(' expression ')' sentence
;

sentIteration: WHILE '(' expression ')' sentence
              |DO sentence WHILE '(' expression ')' ';' 
              |FOR '(' expression ';' expression ';' expression ')' sentence
;

statement: DATATYPE varList                
;

varList:     aVar
            |varList ',' aVar
;

aVar:     variable inicial                           
;

variable: IDENTIFIER                                 
;

initial: '=' NUM                                         
;

我刚刚添加了更多信息 大写字母中的每个单词都是标记。 如果您需要任何其他信息,请告诉我

这里是您的语法的相当简化(但完整)的摘录。我已将 expression 声明为终端,以避免必须定义它:

%token expression IF
%%
sentence :       sentComposed
                |sentSelection
                |sentExpression
sentComposed:    sentenceList
sentenceList:    sentence
                |sentenceList sentence
sentExpression:  expression ';'
                |';'
sentSelection:   IF '(' expression ')' sentence

当我 运行 通过 bison 时,它报告:

ez.y: warning: 4 shift/reduce conflicts [-Wconflicts-sr]
ez.y: warning: 8 reduce/reduce conflicts [-Wconflicts-rr]

这些冲突是实际问题,如以下警告 ("due to conflicts") 所示:

ez.y:8.18-38: warning: rule useless in parser due to conflicts [-Wother]
                 |sentenceList sentence
                  ^^^^^^^^^^^^^^^^^^^^^
ez.y:11.18-47: warning: rule useless in parser due to conflicts [-Wother]
 sentSelection:   IF '(' expression ')' sentence
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

当 bison 发现语法冲突时,它会根据一个简单的过程解决冲突:

  • shift-reduce 冲突已解决,有利于 shift
  • 化简-化简冲突的解决有利于语法中较早发生的产生式。

一旦这样做,可能会发现某些产品再也无法使用,因为它已从可能已减少的所有上下文中删除。这是语法有问题的明显迹象。 [注1]

这里的基本问题是 sentComposed 意味着语句可以只是 st运行g 在一起形成一个更长的语句。那么如果你写会发生什么:

IF (e) statement1 statement2

可能 statement1 statement2 是为了简化为单个 sentComposed,这是 IF 的目标,所以这两个语句仅在 [=24= 时执行] 是真的。或者可能是 sentComposed 由带有目标 statement1IF 语句组成,后跟 statement2。在 C 术语中,区别在于:

if (e) { statement1; statement2; }

{ if (e) { statement1; } statement2; }

所以这是一个真正的歧义,您可能需要重新考虑缺少大括号才能修复它。

但这不是唯一的问题;你也有一堆减少减少冲突。这些以更简单的方式出现,因为上述语法的一部分是以下循环:

sentence:     sentComposed
sentComposed: sentenceList
sentenceList: sentence

该循环意味着您的语法允许将单个 sentence 包装在任意数量的单位缩减中。你当然不是故意的;我确定您的意图是 sentComposed 仅在实际需要时使用。但是野牛不知道你的意图;它只知道你说什么。

同样,当您弄清楚您实际想要如何识别 sentComposed 的边界时,您可能会解决这个问题。

备注:

  1. 在某些情况下,冲突实际上并不是问题。例如,这两个产生式之间存在 shift-reduce 冲突;所谓"dangling-else"歧义:

    sentSelection: IF '(' expression ')' sentence
                  |IF '(' expression ')' sentence ELSE sentence
    

    在嵌套的 IF 语句中:

    IF (e) IF (f) s1 ELSE s2
    

    不清楚 ELSE 应该应用于内部还是外部 IF。如果它适用于内部 IF,则必须将其移位以允许 sentSelection 的第二次产生。如果它适用于外部 IF,则必须先执行归约以完成内部(else-less)IF,然后再将 ELSE 移入外部 IF。 Bison 的默认操作 ("prefer shift") 在这种情况下完全正确,即立即移动 ELSE。 (事实上​​,这就是为什么选择默认值 "prefer shift")。