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