冲突:2班次/减少

时间:2019-01-18 17:19:18

标签: parsing gnu bison yacc

我正在尝试用GNU野牛写一个小解释器。 我想问问是否有人可以解释%right和leftleft指令之间的区别以及我的错误在下面的代码中的位置。

%token <flo> FLO
%token <name> NAME
%right '='
%left '+' '-'
%left '*' '/' '%'
%left '&' '|' 'x'
%left NEG NOT LOGIC_NOT
%left '^'
%left ARG

%type <flo> exp

%%

language:     /* nothing */
            | language statment

statment:     '\n'
            | exp
            | error                     { yyerrok; }
;

exp:      FLO                           { $$ = $1; }
        | NAME '(' ')'                  { $$ = ycall($1); }
        | NAME '(' exp ')'              { $$ = ycall($1, $3); }
        | NAME '(' exp ',' exp ')'      { $$ = ycall($1, $3, $5); }
        | NAME '=' exp                  { $$ = 1; ysetvar($1, $3); }
        | NAME %prec VAR                { $$ = ygetvar($1); }
        | '_' exp %prec ARG             { $$ = ygetarg($2, args); }
        | '(' exp ')'                   { $$ = $2; }
        /* 1 Operand */
        | '-' exp %prec NEG             { $$ = - $2; }
        | '~' exp %prec NOT             { $$ = ~ static_cast<int>($2); }
        | '!' exp %prec LOGIC_NOT       { $$ = ! static_cast<int>($2); }
        /* 2 Operands */
        | exp '+' exp                   { $$ = $1 + $3; }
        | exp '-' exp                   { $$ = $1 - $3; }
        | exp '*' exp                   { $$ = $1 * $3; }
        | exp '/' exp                   { $$ = $1 / $3; }
        | exp '%' exp                   { $$ = static_cast<int>($1) % static_cast<int>($3); }
        | exp '^' exp                   { $$ = pow($1, $3); }
        | exp '&' exp                   { $$ = static_cast<int>($1) & static_cast<int>($3); }
        | exp '|' exp                   { $$ = static_cast<int>($1) | static_cast<int>($3); }
        | exp 'x' exp                   { $$ = static_cast<int>($1) ^ static_cast<int>($3); }
;

1 个答案:

答案 0 :(得分:1)

使用-v参数查看yacc或野牛产生的y.output文件。第一个冲突处于状态5:

State 5

    7 exp: NAME . '(' ')'
    8    | NAME . '(' exp ')'
    9    | NAME . '(' exp ',' exp ')'
   10    | NAME . '=' exp
   11    | NAME .

    '='  shift, and go to state 14
    '('  shift, and go to state 15

    '('       [reduce using rule 11 (exp)]
    $default  reduce using rule 11 (exp)

在这种情况下,冲突是'('后面有NAME时-这在语法上是模棱两可的,它可能是调用表达式,也可能是简单的{{ 1}}表达式后跟带括号的表达式,这是因为您使用的语言之间没有分隔符。

第二个冲突是:

NAME

本质上是相同的问题,这次是State 13 4 statment: exp . 17 exp: exp . '+' exp 18 | exp . '-' exp 19 | exp . '*' exp 20 | exp . '/' exp 21 | exp . '%' exp 22 | exp . '^' exp 23 | exp . '&' exp 24 | exp . '|' exp 25 | exp . 'x' exp '+' shift, and go to state 21 '-' shift, and go to state 22 '*' shift, and go to state 23 '/' shift, and go to state 24 '%' shift, and go to state 25 '&' shift, and go to state 26 '|' shift, and go to state 27 'x' shift, and go to state 28 '^' shift, and go to state 29 '-' [reduce using rule 4 (statment)] $default reduce using rule 4 (statment) -输入'-'可能是一个二进制减法语句,或者可能是两个语句– NAME后跟一元取反。

如果在语句之间添加分隔符(例如NAME - NAME),那么这两种冲突都会消失。