Bison解决跨规则时的转移/减少冲突



如果我的一个规则与另一个规则的一部分扩展相同,我将如何标记优先级?例如,我有一个expression IS type规则,它应该递归地将type扩展为type DOT identifier。但在相同的规则expression中,我有expression DOT identifier,野牛将其报告为冲突。很明显,我希望作为表达式类型部分的所有DOT一起减少为type,而不是作为表达式。Ie:a is b.c.d应该解析为(a is b.c.d),其中b.c.dtype而不是(a is b).c.d。以下是显示冲突的最小语法:

%require "3.0"
%defines
%define api.pure full
%define parse.trace
%token DOT '.'
%token IS "is"
%left DOT
%left IS
%%
example
: expression
;

expression
: expression DOT identifier
| expression IS type
| identifier
;

type
: fqtypename
;
fqtypename
: identifier
| fqtypename DOT identifier
;
identifier: 
"blah"
;
%%

和错误:

State 10
5 type: fqtypename •
7 fqtypename: fqtypename • DOT identifier
DOT  shift, and go to state 12
DOT       [reduce using rule 5 (type)]
$default  reduce using rule 5 (type)

从冲突状态中可以看出,冲突实际上与IS令牌无关。相反,冲突是在转移DOT和减少产量type: fqtypename之间,您希望将其解决为转移DOT

事实上,这是没有任何优先级声明的默认解决方案。Bison和Yacc一样,自动解决shift-release冲突以支持shift,并减少冲突以支持语法文件中较早出现的生产。您可以在粘贴的状态表中看到该分辨率(DOT在该状态下发生了偏移(。当然,每次生成解析器时都会看到野牛警告,这并不理想。您可以通过使用%expect声明来避免警告,该声明基本上告诉Bison预期自动解决的减少移位冲突的数量。对于最近的Bison版本,您可以将声明附加到产品本身,这使得期望更加精确。请参阅Bison手册的链接,其中显示了一个与您的语法有点相似的语法示例。

再做一点工作,就可以使用优先级声明来实现同样的效果,其优点是稍微更精确,但代价是使语法变得更神秘。下面是一个基于你问题中语法的例子。请注意,%prec声明附加到实际参与冲突的生产中。因为该产品根本没有终端符号,所以有必要使用伪令牌来表示优先级。

/* I removed the token names for '.' and "is" to make the grammar shorter. */
%left TYPE_UNIT
%left '.'
%%
example
: expression

expression
: expression '.' identifier
| expression "is" type
| identifier

type
: fqtypename             %prec TYPE_UNIT
fqtypename
: identifier
| fqtypename '.' identifier
identifier: 
"blah"

最新更新