Parsing 冲突:2班/减少

Parsing 冲突:2班/减少,parsing,gnu,bison,yacc,Parsing,Gnu,Bison,Yacc,我正试图用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> e

我正试图用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                           { $$ = $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); }
;
%token-FLO
%令牌名
%对“=”
%左'+''-'
%左'*''/''%
%左'&''|''x'
%左负非逻辑
%左“^”
%左ARG
%类型exp
%%
语言:/*无*/
|语言状态
声明:'\n'
|经验
|错误{yyerrok;}
;
exp:FLO{$$=$1;}
|名称“(“”){$$=ycall($1);}
|名称“('exp')”{$$=ycall($1,$3);}
|名称“('exp','exp')”{$$=ycall($1,$3,$5);}
|名称“=”exp{$$=1;ysetvar($1,$3);}
|名称%prec VAR{$$=ygetvar($1);}
|“u”exp%prec ARG{$$=YGETAG($2,args);}
|“('exp')”{$$=$2;}
/*1操作数*/
|“-”exp%prec NEG{$$=-$2;}
|“~”exp%prec NOT{$$=~static_cast($2);}
| '!' exp%prec LOGIC_NOT{$$=!static_cast($2);}
/*2个操作数*/
|exp'+'exp{$$=$1+$3;}
|exp'-'exp{$$=$1-$3;}
|exp'*'exp{$$=$1*$3;}
|exp'/'exp{$$=$1/$3;}
|exp“%”exp{$$=static_cast($1)%static_cast($3);}
|exp'^'exp{$$=pow($1,$3);}
|exp'&'exp{$$=static_cast($1)和static_cast($3);}
|exp'|'exp{$$=static_cast($1)| static_cast($3);}
|exp'x'exp{$$=static_cast($1)^ static_cast($3);}
;

查看yacc或bison使用-v参数生成的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)
在这种情况下,冲突发生在
'(“
名称
之后)——这是语法中的一种歧义,它可能是一个调用表达式,也可能是一个简单的
名称
表达式,后跟一个括号表达式,因为您的语言中的语句之间没有分隔符

第二个冲突是:

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
可能是一个二进制减法语句,也可能是两个语句--一个名称后跟一元否定


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

代码段中没有
%left
%right
,也没有解释您认为程序有问题的原因。我忘了共享一些代码(flo是双精度代码)。我现在已经更正了。