bison - 如何解决减少减少冲突 :

标签 bison yacc lalr lr

以下(简化的)Bison 语法会产生 reduce reduce 冲突:

expr
    :    '(' expr ')'
    |    ID
    |    fn
    ;

arg_list
    :    ID
    |    arg_list ID
    ;

fn
    :    '(' ')' fnbody
    |    '(' arg_list ')' fnbody
    ;

fnbody
    :    '{' '}'
    ;

我看到了问题——只有一个前瞻标记,无法判断 (an_id'(' expr ')' 还是 fn。但是我该如何解决呢?

最佳答案

好吧,最简单的答案是在解析器中使用更多的前瞻性——要么使用类似 btyacc 的东西, 或者使用 bison 的 %glr-parser 选项。

第二种选择是在词法分析器中添加先行——在这种情况下,在返回 ')' 标记之前,查看下一个标记是否是 '{' 并返回一个特殊标记,告诉您这是一个您将要结束的 arg_list 而不是带括号的表达式,或者只是将两者作为单个标记返回并适当修改您的语法。

第三种选择是分解语法。这并不总是那么容易,并且可能会增加语法的大小。基本思想是识别冲突的规则并将它们组合成一个可以被解析器识别的单一规则,并推迟选择最终构造是什么,直到您看到足够多为止。

对于这个例子,您为冲突的情况添加了一个新规则:

expr_or_fnhead:  '(' ID ')'  ;

可以是表达式或 fn 的开头,然后修改其他规则以使用它。 fn 规则变为:

fn :  '(' ')' fnbody               /* 0 arg function */
   |  expr_or_fnhead fnbody        /* 1 arg function */
   |  '(' ID arg_list ')' fnbody   /* 2+ arg function */
   ;

expr 规则更复杂:

expr       : ID
           | non_ID_expr
           ;
non_ID_expr: '(' non_ID_expr ')'
           | expr_or_fnhead
           | fn
           ;

关于bison - 如何解决减少减少冲突 :,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10771437/

相关文章:

c++ - 即使函数存在,也出现 undefined reference 错误

parsing - 如何设置 flex/bison 规则来解析逗号分隔的参数列表

c++ - 什么是最好的 C++ LALR 解析器生成器,可以生成有意义的错误消息

c++ - 为什么不能使用 LEX/YACC 为编译器解析 C++?

grammar - 通过产生式规则向 LALR(1) 语法添加错误检查以处理所有输入

parsing - 用于 scala 的 LALR(1) 解析器生成器

c - 使用 Bison/Yacc 在 %union def 中包含结构

c++ - 在 C++(不是 C)中用 bison 和 flex 创建简单的计算器

parsing - yacc shift-reduce 用于不明确的 lambda 语法

parsing - 解析器/词法分析器忽略不完整的语法规则