3

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

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)

感谢您提供任何帮助。

4

1 回答 1

5

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

ID = ID ( ID ) = ID

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

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

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

于 2011-01-14T18:12:20.260 回答