冲突:2 shift/reduce

conflicts: 2 shift/reduce

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

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

查看带有 -v 参数的 yacc 或 bison 生成的 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 之后有一个 '(' —— 这是语法中的歧义,它可能是一个调用表达式,或者它可能是一个简单的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 后跟一元否定。

如果您在语句之间添加一个分隔符(例如 ;),这些冲突都会消失。