无法解决以下reduce-reduce错误(LALR解析)

时间:2017-11-04 02:24:09

标签: parsing bison yacc lalr bisonc++

我目前正在实现Decaf(编程语言)语法的一部分。以下是 bison 代码的相关摘要:

type:
  INT
  | ID
  | type LS RS
  ;

local_var_decl:
  type ID SEMICOLON
  ;

name:
  THIS
  | ID
  | name DOT ID
  | name LS expression RS
  ;

然而,只要我开始处理名称生产规则,我的解析器就会提供 reduce-reduce 警告。

这里的内容是 .output 文件(由野牛生成):

State 84

   23 type: ID .
   61 name: ID .

    ID        reduce using rule 23 (type)
    LS        reduce using rule 23 (type)
    LS        [reduce using rule 61 (name)]
    $default  reduce using rule 61 (name)

因此,如果我们提供以下输入{ abc[1] = abc; },则表示syntax error, unexpected NUMBER, expected RS NUMBER 来自表达式规则(基本上,它必须如何解析它),尽管它尝试通过 local_var_decl 规则解析它。

为了解决这个问题,您认为应该改变什么?花了大约2个小时,尝试了不同的东西,没有工作。

谢谢!!

PS。以下是完整 .y 源代码

link

1 个答案:

答案 0 :(得分:1)

这是一个常见问题的特定实例,其中解析器在有足够信息之前被迫做出决定。在某些情况下,例如这个,所需的信息并不遥远,如果可能的话,增加前瞻就足够了。 (不幸的是,很少有解析器生成器生成LR(k)解析器,k> 1,而bison也不例外。)通常的解决方案是简单地允许解析继续而不必决定。使用bison(但仅在C模式下)的另一个解决方案是要求%glr-parser,这对于何时需要以额外处理时间为代价来解决缩减更为灵活。

在这种情况下,上下文允许typename,这两者都可以以ID后跟[开头(LS })。对于name[必须后跟一个数字;对于type[必须后跟]。因此,如果我们能够在ID之后看到第二个令牌,我们可以立即做出决定。

但是我们前面只能看到一个令牌,即]。语法坚持认为我们能够立即做出决定,因为在一种情况下,我们必须将ID缩减为name,而在另一种情况下,缩小为type。所以我们有一个减少 - 减少冲突,通过始终使用语法文件中的第一个减少来解决这个问题。

一种解决方案是避免强制这种选择,代价是重复制作。例如:

type_other:
  INT
  | ID LS RS
  | type_other LS RS
  ;
type: ID
  | type_other
  ;

name_other:
  THIS
  | ID LS expression RS
  | name_other DOT ID
  | name_other LS expression RS
  ;
name: ID
  | name_other
  ;