【问题标题】:Shift/reduce conflict with C-like grammar under BisonBison 下 Shift/reduce 与类 C 语法的冲突
【发布时间】:2010-01-15 00:35:44
【问题描述】:

我一直在研究类似 C 的语法,以供个人娱乐。但是,我遇到了 shift/reduce 冲突,我很确定它们可以得到解决。

现在我的expressions 看起来像这样,以简化的形式,没有操作:

%left '+' '-'

%%
expr
 : NUMBER
 | IDENTIFIER
 | expr '+' expr
 | expr '-' expr
 /* other operators like '*', '/', etc. */
 | expr '(' expr ')' /* function call */
%%

但是,这会导致移位/归约冲突:解析器不确定如何处理括号。从-v 告诉我的内容来看,尚不清楚像expr '+' expr '(' 这样的表达式是否应该将expr '+' expr 减少为expr 或移动括号。

显然,我希望括号移动。 foo % bar(4) 不应该最终成为 (foo % bar)(4)。但是,我没有成功使用 %prec 指令来表示这个意思。在规则之后添加%left FUNCALL%prec FUNCALL 不会产生任何变化。

我知道 Bison 的 LALR 解析器在遇到 shift/reduce 时的默认路径是 shift,我可以使用 %expectfix 解决这个问题。但是,每个表达式都会产生一个冲突,我是否需要更改该列表,我还需要更改 %expect 声明,这对我来说似乎是一个相当丑陋的解决方案。此外,我相信你们中的一个聪明的孩子有解决这个问题的办法。

我的目标是有一个类似于上面的规则,Bison 会知道,每当它遇到函数调用规则中的'(' 时,它就会移动括号,而不会发生移位/减少冲突。作为记录,我对%prec 指令的使用如下,所以如果我做错了,你可以纠正我。它确实存在移位/减少冲突。

%left '+' '-'
%left FUNCALL

%%

expr
    : NUMBER
    | IDENTIFIER
    | expr '+' expr
    | expr '-' expr
    /* other operators like '*', '/', etc. */
    | expr '(' expr ')' %prec FUNCALL /* function call */

%%

【问题讨论】:

    标签: bison


    【解决方案1】:

    您需要将%left '(' 添加到您的优先规则中(或者%nonassoc '(' 可能会更好)。

    优先级在 yacc/bison 中解决移位/减少冲突的方法是将要减少的 规则 的优先级与 token 的优先级进行比较被转移。在您的示例中,冲突是减少expr: expr '+' expr 和移动'(' 之间的冲突,因此要解决它,您需要'(' 的优先级(并且您希望它高于来自'+' 的规则)

    %prec 指令只是设置规则的优先级,覆盖它的默认优先级,它来自其 rhs 上的第一个标记。它不会以任何方式影响规则中出现的标记的优先级。

    【讨论】:

    • 哦,我明白了。我真的买不起%nonassoc '(',因为它会完全打破嵌套括号,除非我遗漏了其他东西,但我明白你的意思。谢谢。
    • 嵌套的括号不应该涉及任何冲突,所以%nonassoc 不应该是一个问题——优先规则只对解决冲突很重要
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多