【问题标题】:Shift/reduce conflict in yacc due to look-ahead token limitation?由于前瞻令牌限制,yacc 中的移位/减少冲突?
【发布时间】:2011-06-09 02:24:14
【问题描述】:

我一直在尝试解决看似简单的 shift/reduce 冲突,但无济于事。当然,如果我忽略冲突,解析器工作正常,但如果我重新组织我的规则,我会感觉更安全。在这里,我将一个相对复杂的语法简化为单一冲突:

statement_list
  : statement_list statement 
  | 
  ;

statement
  : lvalue '=' expression
  | function
  ;

lvalue
  : IDENTIFIER
  | '(' expression ')'
  ;

expression
  : lvalue
  | function
  ;

function
  : IDENTIFIER '(' ')'
  ;

使用 yacc 中的详细选项,我得到这个输出文件,描述了具有上述冲突的状态:

state 2

    lvalue  ->  IDENTIFIER .   (rule 5)
    function  ->  IDENTIFIER . '(' ')'   (rule 9)

    '('  shift, and go to state 7

    '('  [reduce using rule 5 (lvalue)]
    $default reduce using rule 5 (lvalue)

感谢您的帮助。

【问题讨论】:

    标签: parsing yacc conflict shift-reduce


    【解决方案1】:

    问题是这需要 2-token 前瞻才能知道它何时到达语句的末尾。如果您输入了表单:

    ID = ID ( ID ) = ID
    

    解析器移动第二个 ID 后(前瞻为 (),它不知道这是第一个语句的结尾(( 是第二个语句的开头),还是这是一个函数。所以它发生了变化(继续解析一个函数),这与上面的示例输入是错误的。

    如果您扩展function 以允许括号内的参数和expression 以允许实际表达式,事情会变得更糟,因为所需的前瞻是无限的——解析器需要一直到达第二个@987654326 @判断这不是函数调用。

    这里的基本问题是没有辅助标点符号来帮助解析器找到语句的结尾。由于作为有效语句开头的文本也可能出现在有效语句的中间,因此很难找到语句边界。

    【讨论】:

    • 我没有考虑过这样的输入。好吧,我正在解析的语言需要如此模棱两可,所以我想我会忽略冲突。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-12-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多