0

我正在使用 Bison(AFAIK 他们LL(1)默认使用解析)。

我的语法是这样说的:

function_decl: ID '(' params ')' ':' TYPE ... // body may go here
function_call: ID '(' arguments ')'

params: ID ':' TYPE
     | params ',' ID ':' TYPE
     | %empty

arguments: ID
    | arguments ',' ID
    | %empty

现在,bison警告说reduce/reduce冲突,因为params两者arguments都可以为空(在零参数的情况下function())。

我的问题是,我怎样才能消除(而不是压制)这种冲突?

尽管有人建议使用不同的解析技术,但如果可能(我应该这样做),我想对自己说清楚,或者我应该忽略它。

4

1 回答 1

2

如果您忽略警告,您将得到一个解析器,它无法识别没有参数的函数调用。所以这可能不是一个好主意。

您完全正确,冲突是两者的结果paramsarguments产生了一个空字符串。)因为解析器在读取in时只能先看一个符号 a func(),所以它需要决定是减少一个空params(这将迫使它继续进行function_decl)还是一个空arguments(这将把它提交给function_call)。但是在读取下一个令牌之前无法知道。

最简单的解决方案是避免空归约,尽管它会使语法略显冗长。在下文中,既不params也不arguments产生空字符串,而额外的产生式function_declfunction_call用于识别这些情况。

function_decl: ID '(' params ')' ':' TYPE ... // body may go here
function_decl: ID '(' ')' ':' TYPE ... 
function_call: ID '(' arguments ')'
function_call: ID '(' ')'

params: ID ':' TYPE
     | params ',' ID ':' TYPE

arguments: ID
    | arguments ',' ID

这是有效的,因为它让解析器推迟调用和声明之间的决定。LR 解析器可以推迟决策,直到它必须减少;它可以同时保持多个生产开放,但它必须在生产结束时减少生产。


请注意,即使没有冲突,您的原始语法也是不正确的。如所写,它允许arguments(or params) 以任意数量的逗号开头。您的意图不是允许%empty作为替代的基本案例,而是作为替代的完整扩展。可选逗号分隔列表的正确语法需要两个非终结符:

arguments
    : %empty
    | argument_list
argument_list
    : argument
    | argument_list ',' argument
于 2019-02-28T21:10:29.650 回答