Parsing Bison-移位/减少冲突标识符

Parsing Bison-移位/减少冲突标识符,parsing,compiler-construction,bison,shift-reduce-conflict,Parsing,Compiler Construction,Bison,Shift Reduce Conflict,我在19号州有1个班次/减少冲突。我认为“标识符”的不同出现可能有问题,但我正在努力理解野牛报告并解决冲突。下面是我的语法,后面是野牛报告和州信息: %{ #include <cstdio> #include <iostream> using namespace std; extern "C" int yylex(); extern "C" int yyparse(); void yyerror(const char *s

我在19号州有1个班次/减少冲突。我认为“标识符”的不同出现可能有问题,但我正在努力理解野牛报告并解决冲突。下面是我的语法,后面是野牛报告和州信息:

%{
    #include <cstdio>
    #include <iostream>
    using namespace std;

    extern "C" int yylex();
    extern "C" int yyparse();
    void yyerror(const char *s);
%}

%union{
    int int_val;
    double d_val;
    char *strng;
}

%token TLINEC TBLOCKC TPRINT
%token TASSIGN TCPA TOB TCB TCOMMA TSEMIC
%token TIF TELSE TFOR
%token TINT TFLOAT TD TCHAR
%token TPLUS TMINUS TDIV TMULT
%token TLT TGT TAND TOR TEQUAL TNE
%token<int_val> TINTEGER
%token<d_val> TDOUBLE
%token<strng> TID
%token TOPA

%start program

%%

program : command_list

command_list : declaration
    | command_list declaration

declaration : function_dec
| variable_dec
    | expression

variable_dec : type identifier TSEMIC
| type assignment TSEMIC

assignment : identifier TASSIGN expression

var_list : expression
    | var_list TCOMMA expression
    |

function_dec : type identifier TOPA p_list TCPA scope

p_list : variable_dec
    | p_list TCOMMA variable_dec

type : TINT
    | TD
    | TFLOAT
    | TCHAR


/* inside function scope */

scope : TOB command_list TCB
| TOB TCB


function_call : identifier TOPA var_list TCPA TSEMIC

/* expression rules */

expression : assignment
    | function_call
    | TOPA expression TCPA
    | constant arithmetic_op expression
    | constant logical_op expression
    | constant


constant : identifier
    | num

identifier : TID

num : TINTEGER
| TDOUBLE

arithmetic_op : TPLUS | TMINUS | TDIV | TMULT

logical_op : TLT | TGT | TAND | TOR | TEQUAL | TNE

%%

int main(int, char**){
    int y=0;
    do{
        y=yyparse();
    }while(y);
}

void yyerror(const char *s){
    cout << "parse error! Message: " << s << endl;
    exit(-1);
}

根据bison的输出,从状态19开始,可以提前减少
expression
。这怎么可能?换句话说,在什么情况下
expression
后面可以加一个括号

在语法中搜索只会发现
TOPA
的三种用法。其中两种用法(函数声明和函数调用)跟在
identifier
后面,而
identifier
无法派生
表达式,因此它必须是第三种用法:

expression: TOPA expression TCPA;
但是,
expression
的减少可以在(的)实例之前立即发生的唯一方法是两个
expression
可以连续发生。通常,在类C语言中,通过要求a;分隔语句来消除这种可能性(可能是以表达式开始,也可能以表达式结束),我想这就是你的意图

然而,我们看到:

command_list: declaration
            | command_list declaration

declaration: expression
它允许两个连续的表达式而不插入分号


一如既往,我鼓励在野牛语法中使用更具可读性的标记。
(“
TOPA
更容易理解,老实说,我不知道
COB
可能是什么。但这是一个风格问题

command_list: declaration
            | command_list declaration

declaration: expression