Bison 野牛LALR转移/减少冲突

Bison 野牛LALR转移/减少冲突,bison,yacc,lalr,Bison,Yacc,Lalr,我最近又拿起了野牛,但我仍在为优先权的工作方式以及如何解决基本的转换/减少冲突而斗争。我对编写语法规则和递归的工作原理等都很熟悉,但我仍然无法理解优先规则 我非常感谢对以下例子的一些评论,以及我对它们的问题和理解 test1.y %token ID %token TYPE_NAME %token ASTERIX %nonassoc F_T %nonassoc P_T %% f

我最近又拿起了野牛,但我仍在为优先权的工作方式以及如何解决基本的转换/减少冲突而斗争。我对编写语法规则和递归的工作原理等都很熟悉,但我仍然无法理解优先规则

我非常感谢对以下例子的一些评论,以及我对它们的问题和理解

test1.y

%token              ID
%token              TYPE_NAME
%token              ASTERIX

%nonassoc           F_T
%nonassoc           P_T

%%
f_type:
                    ID type         %prec F_T
;

type:
                    TYPE_NAME
|                   type ASTERIX    %prec P_T
|                   f_type
;
%%
test1.1输出

State 5

     1 f_type: ID type .
     3 type: type . ASTERIX

     ASTERIX  shift, and go to state 7

     ASTERIX   [reduce using rule 1 (f_type)]
     $default  reduce using rule 1 (f_type)
本例产生一个移位-减少冲突,因为状态机无法确定它是否应该减少ID-type*->type*->typeID-type*->ID-type->type。后者才是理想的结果。我试图通过给规则类型:type ASTERIX一个高于f_type:ID type的优先级来解决这个冲突,但这似乎不起作用。我也不希望为终端ASTERIX分配任何优先级,因为我希望在其他上下文中使用它

​ test2.y

test2.0输出

State 4

    2 exp: exp . DOUBLE_PLUS
    3    | DOUBLE_PLUS exp .

    DOUBLE_PLUS  shift, and go to state 6

    DOUBLE_PLUS  [reduce using rule 3 (exp)]
    $default     reduce using rule 3 (exp)
本例产生移位/减少冲突,因为DOUBLE\u PLUS exp DOUBLE\u PLUS的减少存在歧义。因此,我试图给DOUBLE\u PLUS exp分配比exp DOUBLE\u PLUS更高的优先级,但这也不起作用。可以通过为终端分配左或右优先级来解决此冲突,我猜分配左优先级意味着exp DOUBLE\u PLUS首先减少,右优先级意味着DOUBLE\u PLUS首先减少,但我也希望通过使用%prec注释可以实现这一点

我也不确定我是否正确理解.output文件。规则中的指示堆栈上的内容以及前瞻标记是什么,但是为什么后面的示例中甚至提到了规则2?我的意思是exp:exp。DOUBLE\u PLUS不应该有任何冲突吗?

这里引用了我写的关于yacc/bison优先算法的一段话。我不知道它是否比龙之书中的文档或描述更清晰,但这是迄今为止我所能做到的最好的。如果您感到困惑,请告诉我:

回想一下,优先关系是在生产和生产之间定义的 终点站。它不涉及两个终端或两个产品(和 因此不能用于解决(减少冲突)。比较 在可减少的生产优先级和 前瞻终端确定是减少还是移位。 为了便于注释,产品用以下名称表示: 终端,通常是生产中唯一的终端;这 对应于一个常见的用例,但有时会令人困惑。在里面 特别是,
%prec
声明仅用于为规则命名 用于优先级声明,最好考虑 以这种方式而不是作为一种“明确”的声明

由于优先级比较从不在两个规则之间进行——它们总是在一个规则和一个先行标记之间——优先级顺序声明必须同时包括规则(隐式或显式)和标记名。因此,在第一个示例中,
F_T
P_T
之间的优先顺序没有任何影响。类似地,在第二个示例中,
PREFIX_OP
POSTFIX_OP
是仅与规则相关联的先例,因此优先顺序没有效果

如果shift和reduce都是可能的,并且规则和先行标记之间的比较表明该规则具有更高的优先级,那么将生成reduce操作。如果先行标记具有更高的优先级,则将生成移位操作。但只有在转移和减少都有可能的情况下,才会参考这些声明。如果语法只能执行一个操作,那么不管怎样,它都将执行该操作。(例外情况:
%nonassoc
声明实际上将禁止某些削减。)

如果比较结果相等(规则和标记都在同一优先组中),则对于
%left
组,shift优先,而对于
%right
组,shift优先。这种情况通常不适用于一元运算符,无论是前缀还是后缀,因为在这种情况下,只能执行一个操作

如果在优先规则中插入标记会与语法另一部分中的优先顺序产生冲突,那么不能使用优先声明作为捷径;你只需写下语法就可以明确优先级。这通常并不难。另一方面,在两种不同的语法语境中,相互冲突的先例可能会让人非常困惑,所以你可能需要重新考虑


对于
.output
文件中的状态机输出,将打印整个状态,而不仅仅是导致冲突的部分。冲突在行动中表现出来;
[…]
中包含的操作与其他操作冲突,并由bison的默认冲突解决机制消除(首选shift to reduce;首选reduce,其规则在文件中较早)。粗略地说,移位规则在标记之前有
;reduce规则在规则的末尾有

这非常有帮助:)我猜如果有多个,生产的优先级是由优先级最高的终端定义的?@qwerasdf:除非被
%prec
声明覆盖,否则它始终是最后一个终端。
State 4

    2 exp: exp . DOUBLE_PLUS
    3    | DOUBLE_PLUS exp .

    DOUBLE_PLUS  shift, and go to state 6

    DOUBLE_PLUS  [reduce using rule 3 (exp)]
    $default     reduce using rule 3 (exp)