我正在使用 Menhir 创建解析器,并且有一种行为总是让我感到困惑,我不明白。我创建了以下最小示例来演示它;这显示了在 Go 语言( http://golang.org/ref/spec#Method_declarations )的方法声明中接收器参数的声明:
%{
%}
%token <string> T_identifier
%token T_star
%start <unit> demo
%%
(* This rule has a shift/reduce conflict
demo:
| option(T_identifier) option(T_star) T_identifier { () }
*)
(* This rule is okay. *)
demo:
| T_identifier T_star T_identifier { () }
| T_identifier T_identifier { () }
| T_star T_identifier { () }
| T_identifier { () }
据我所知,这两个规则在语义上是等价的:我们正在寻找一个可选的标识符(接收者的名称)、一个可选的星号(指针与否)和一个强制的类型名称(接收者的类型)。但是,第一条规则(注释掉的那条)给出了移位/减少冲突,而第二条规则工作正常。
每当发生这种情况时,我都可以通过替换多个规则来在我的解析器中取得进展option
,但它一直在唠叨我,我不明白为什么会发生这种情况。
(如果您不了解 menhir,它是一个 LR(1) 解析器生成器,因此可能需要了解其他类似工具的工作原理。)