Parsing 野牛消除减少/减少可空非终端之间的冲突?

Parsing 野牛消除减少/减少可空非终端之间的冲突?,parsing,bison,nullable,rules,reduce-reduce-conflict,Parsing,Bison,Nullable,Rules,Reduce Reduce Conflict,我使用的是Bison(他们默认使用LL(1)parsing) 我的语法是这样的: function_decl: ID '(' params ')' ':' TYPE ... // body may go here function_call: ID '(' arguments ')' params: ID ':' TYPE | params ',' ID ':' TYPE | %empty arguments: ID | arguments ',' ID

我使用的是Bison(他们默认使用
LL(1)
parsing)

我的语法是这样的:

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()

我的问题是,我如何消除(而不是压制)这场冲突


尽管有人建议使用不同的解析技术,但我想让自己清楚这是可能的(而且我应该这样做),还是应该忽略它。

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

您完全正确,冲突是由
params
arguments
生成空字符串的结果。因为解析器在读取
func()
中的
时只能向前看一个符号a,所以它需要决定是减少一个空的
参数(这将强制它继续执行
函数decl
)还是减少一个空的
参数(这将把它提交给
函数调用
)。但在读取下一个令牌之前,无法知道

最简单的解决方案是避免空的缩减,尽管它会使语法稍微冗长一些。在下面的例子中,
params
arguments
都不会生成空字符串,而
function_decl
function_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解析器可以推迟决策,直到必须减少;它可以同时打开多个产品,但必须在产品结束时减少生产


请注意,即使没有冲突,您的原始语法也是不正确的。如前所述,它允许
参数
(或
参数
)以任意数量的逗号开头。您的意图不是允许将
%empty
作为替代基本情况,而是作为替代完整扩展。可选逗号分隔列表的正确语法需要两个非端子:

arguments
    : %empty
    | argument_list
argument_list
    : argument
    | argument_list ',' argument

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

您完全正确,冲突是由
params
arguments
生成空字符串的结果。因为解析器在读取
func()
中的
时只能向前看一个符号a,所以它需要决定是减少一个空的
参数(这将强制它继续执行
函数decl
)还是减少一个空的
参数(这将把它提交给
函数调用
)。但在读取下一个令牌之前,无法知道

最简单的解决方案是避免空的缩减,尽管它会使语法稍微冗长一些。在下面的例子中,
params
arguments
都不会生成空字符串,而
function_decl
function_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解析器可以推迟决策,直到必须减少;它可以同时打开多个产品,但必须在产品结束时减少生产


请注意,即使没有冲突,您的原始语法也是不正确的。如前所述,它允许
参数
(或
参数
)以任意数量的逗号开头。您的意图不是允许将
%empty
作为替代基本情况,而是作为替代完整扩展。可选逗号分隔列表的正确语法需要两个非端子:

arguments
    : %empty
    | argument_list
argument_list
    : argument
    | argument_list ',' argument

Bison生成LR解析器,而不是LL。Bison生成LR解析器,而不是LL。