处理野牛中的歧义

问题描述 投票:0回答:2

https://pastebin.com/eMAJA9RV

我正在上面的链接中使用 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
2个回答
2
投票

无论 Bison 版本如何,我认为这里都没有简单的解决方案。您不能使用

%dprec
,因为同一规则的两个不同应用之间存在歧义。您不能使用
%merge
,因为在调用自定义合并函数之前会评估两种可能的产生式操作函数,这在一次性编译器中是致命的。

了解您所做的哪些更改导致了此问题将会很有用。您可能可以对特定的更改进行特殊处理,但我怀疑唯一可扩展的更改是将窥视孔优化分离到后解析阶段。


0
投票

而不是

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 解决歧义的文章提供了一个这样的示例,其中歧义块被“包装”在它自己的非终结符中。

© www.soinside.com 2019 - 2024. All rights reserved.