1

这是 [filename].output state 94 的摘录

   32 expr: expr . opt_at_type '.' TYPEID '(' opt_expr_list ')'
   39     | expr . '+' expr
   40     | expr . '-' expr
   41     | expr . '*' expr
   42     | expr . '/' expr
   42     | expr '/' expr .
   44     | expr . '<' expr
   45     | expr . LE expr
   46     | expr . '=' expr

    '@'  shift, and go to state 73

    '.'       reduce using rule 23 (opt_at_type)
    '.'       [reduce using rule 42 (expr)]
    $default  reduce using rule 42 (expr)

    opt_at_type  go to state 74

opt_at_type 定义为:

    opt_at_type:
            { $$ = idtable.add_string("SELF_TYPE"); }
            |       '@' TYPEID
            { $$ = $2;   }
            ;

你能告诉我为什么会这样吗?

4

2 回答 2

1

您遇到的问题是 yacc 优先级仅用于解决移位/减少冲突,而不是减少/减少。在这种情况下,opt_at_type规则可以匹配一个空字符串(它是可选的),从而导致减少/减少冲突。

要修复它,您需要分解规则以摆脱 epsilon 生产:

expr: expr '.' TYPEID '(' opt_expr_list ')'
    | expr '@' TYPEID '.' TYPEID '(' opt_expr_list ')'
    | expr '+' expr
       :

没有 epsilon 生产,它不需要提前减少,因此冲突变成了 shift/reduce 冲突,可以通过 yacc 优先级正常解决。

于 2012-11-13T17:32:09.067 回答
0

当 Bison 看到以下内容时:

expr '/' expr '.'

它不知道这是否等同于:

1) expr opt_at_type '.'

或者

2) expr '/' expr opt_at_type '.'

对于 1) 它将减少expr '/' exprexprfirst 并且对于 2) 它会将 /* Empty */ 减少到opt_at_typefirst。

所以我们发现了歧义,要解决它,你必须确定你想要什么语法。一种解决方案是使第一个 expr 规则成为单独的规则,以便它不能在其他表达式中使用,如下所示:

typeexpr: expr opt_at_type '.' TYPEID '(' opt_expr_list ')'
于 2012-11-13T17:14:46.827 回答