我正在上面的链接中使用 Bison 语法(它是旧版本开源 flasm 项目的分叉副本的一部分,我不会详细说明为什么要修改它)
使用此功能,我的一个文件出现以下错误: 检测到歧义。
Option 1,
statements -> <Rule 116, tokens 509 .. 516>
statements -> <Rule 113, tokens 509 .. 514>
statements <tokens 509 .. 512>
statement -> <Rule 127, tokens 513 .. 514>
opcode -> <Rule 301, tokens 513 .. 514>
PUSH <tokens 513 .. 513>
@24 -> <Rule 300, empty>
push_list -> <Rule 217, tokens 514 .. 514>
push_item -> <Rule 178, tokens 514 .. 514>
STRING <tokens 514 .. 514>
statementOptimized -> <Rule 128, tokens 515 .. 516>
opcodeOptimized -> <Rule 254, tokens 515 .. 516>
CALLMETHOD <tokens 515 .. 515>
POP <tokens 516 .. 516>
Option 2,
statements -> <Rule 116, tokens 509 .. 516>
statements <tokens 509 .. 512>
statementOptimized -> <Rule 128, tokens 513 .. 516>
opcodeOptimized -> <Rule 238, tokens 513 .. 516>
PUSH <tokens 513 .. 513>
STRING <tokens 514 .. 514>
CALLMETHOD <tokens 515 .. 515>
POP <tokens 516 .. 516>
我已经在涉及的各种规则上尝试了 dprec 运算符的各种组合,但我找不到有效的组合。我怎样才能以某种方式让野牛解析器在看到该组合时支持选项 2,而不是抱怨它无法决定使用哪一个?
由于一些我不会详细说明的原因,我在这个项目中一直使用 Bison 2.1,所以无论我需要什么解决方案都必须使用该版本的 Bison。
无论 Bison 版本如何,我认为这里都没有简单的解决方案。您不能使用
%dprec
,因为同一规则的两个不同应用之间存在歧义。您不能使用 %merge
,因为在调用自定义合并函数之前会评估两种可能的产生式操作函数,这在一次性编译器中是致命的。
了解您所做的哪些更改导致了此问题将会很有用。您可能可以对特定的更改进行特殊处理,但我怀疑唯一可扩展的更改是将窥视孔优化分离到后解析阶段。
而不是
statements :
statement { $$ = $1; } %dprec 5
| statements statement { $$ = $1 + $2; } %dprec 1
| statementOptimized { $$ = $1; } %dprec 20
| statementScanned { $$ = $1; } %dprec 15
| statements statementOptimized { $$ = $1 + $2; } %dprec 10
| statements statementScanned { $$ = $1 + $2; } %dprec 8
;
尝试:
one_or_more_generic_statements:
generic_statement ';'
| one_or_more_generic_statements generic_statement ';'
generic_statement :
statement %dprec 1
| statementScanned %dprec 2
| statementOptimized %dprec 3
我不是 100% 确定这会解决歧义错误(因为没有提供会触发错误的输入,如果这不是解决办法,请提前道歉)。为了支持我的观点,说明为什么这可能是解决方案,关于使用 glr 解决歧义的文章提供了一个这样的示例,其中歧义块被“包装”在它自己的非终结符中。