【问题标题】:Bison: If/Else reduce/reduce conflictBison:如果/否则减少/减少冲突
【发布时间】:2018-11-29 10:52:25
【问题描述】:

我是 Bison 的新手。我收到减少/减少冲突错误,但没有得到它发生的地方。错误消息是“冲突:1 减少/减少”。这是我的语法规则。

%token INT FLOAT CHAR EXIT V_MAIN BS BE NL EQU CM ADD SUB MUL DIV LT GT LP RP PRINT IF ELSE THN HH
%token <VarNm> V_NM
%token <num> NUMBER
%token <flt> R_NUM
%type <num> EXP TERM FACTOR CON STATEMENTS 
%type <VarNm> X
%nonassoc THN
%nonassoc ELSE 
%start STRT
%left LT GT
%left PLUS MINUS
%left MULT DIV 

%%
STRT : V_MAIN BS CODE BE            {printf("Compilation complete. :)\n");}
    | EXIT                          {exit(EXIT_SUCCESS);}
    ;
CODE : /* empty */
    |   CODE STATEMENTS NL          {printf("Statements complete\n");}
    |   CODE DECLARATION NL         {printf("Declaration complete\n");} 
    |   STMNT 
    ;
DECLARATION :  TYPE V               {printf("D\n");}
    ;
TYPE : INT                          {printf("I\n");}
    | FLOAT                         {printf("F\n");}
    | CHAR
    ;
V : V CM V_NM                       {AddNewVar($3);printf("V\n");}              
    | V_NM                          {AddNewVar($1);printf("Vn %s\n",$1);}               
    | /* empty */                   {printf("E\n");}
    ;
STATEMENTS :                        { $$ = 0; }
    | EXP EQU X                     {AsgnVal($3,$1);}
    | PRINT EXP                     {printf("Output: %d\n",$2);}
    | EXP                           { $$ = $1 ;}                                                                
    ;
STMNT : MIF NL
    | UIF NL
    ;
MIF : IF CON THN HH MIF HH ELSE HH MIF HH   {printf("MIF1\n");}
    | CODE STATEMENTS NL
    ;
UIF : IF CON THN HH STMNT HH                {printf("UIF1\n");}
    | IF CON THN HH MIF HH ELSE HH UIF HH   {printf("UIF2\n");}
    ;
CON : EXP GT EXP                    { $$ =  $1 > $3? 1: 0 ; }
    | EXP LT EXP                    { $$ =  $1 < $3? 1: 0 ; }
    | EXP EQU EXP                   { $$ = $1 == $3? 1: 0 ; }
    ;
X : V_NM                            { $$=$1;CheckIfFound($1);}
    ;
EXP : TERM 
    | EXP ADD TERM                  { $$ = $1 + $3; }
    | EXP SUB TERM                  { $$ = $1 - $3; }
    ;
TERM : TERM MUL FACTOR              { $$ = $1 * $3; }
    | TERM DIV FACTOR               { if($3){$$ = $1 / $3;}
                                      else {printf("Division by zero\n");}   
                                    }
    | FACTOR                        { $$ = $1; }
    | X                             { $$=VarVal($1); }
    ;
FACTOR : NUMBER                     { $$ = $1; }
    | LP EXP RP                     { $$ = $2; }
    ; 

当我插入 IF/ELSE 的语法时,冲突错误开始了。 排除那部分我的代码工作得很好。我还想知道是否有任何方法可以使用 command 检测这种冲突发生在哪里。

【问题讨论】:

    标签: bison flex-lexer


    【解决方案1】:
    1. 问题确实是由您的if 作品触发的。它是这样的(省略其他不相关的产品):

      MIF  : CODE STATEMENTS NL
      CODE : STMNT
           | CODE STATEMENTS NL
      STATEMENTS: %empty
      STMNT: MIF NL
      

      请注意,NL 始终是CODE 的可能前瞻,因为CODE: CODE STATEMENTS NLSTATEMENTS: %empty,这意味着CODE 可以派生CODE NL。)

      CODE NL⇒ CODE STATEMENTS NL NL     (CODE: CODE STATEMENTS NL)
             ⇒ STMNT STATEMENTS NL NL    (CODE: STMNT)
             ⇒ MIF NL STATEMENTS NL NL   (STMNT: MIF NL)
             ⇒ MIF NL STATEMENTS NL NL   (MIF: CODE STATEMENTS NL)
             ⇒ CODE STATEMENTS NL NL STATEMENTS NL NL
      

      这当然是一个减少-减少冲突。当解析器找到CODE STATEMENTS NL 并将NL 视为前瞻时,它可以使用缩减CODE: CODE STATEMENTS NLMIF: CODE STATEMENTS NL

    2. 如果您使用 Wikipedia dangling-else page 作为指南(或者即使您没有使用),请仔细查看生产版 closed_statement: non_if_statement。 (closed_statement 相当于您的MIF)。

    3. 虽然没有魔术命令where_is_my_error,但使用bison 将在请求时生成的报告文件(使用-v--report 选项)很容易看出该问题。请参阅bison manual debugging chapter 中的完整示例。 bison 的 trace facility 也非常有用,它可以让您不必在整个解析器中分散 printf 语句(然后删除它们)。

    4. 如果您遵守通常的风格准则,您的语法(对您以外的人)会更易读:

      1. 对令牌使用UPPER_CASE,对非终端使用lower_casecamelCase
      2. 完整地写出单词。 Rmvng vwls frm dntfrs mks yr cd nrdbl.
      3. 使用bison的别名功能将关键字写成关键字本身(用引号引起来):

        %token T_THEN "then" T_IF "if" T_ELSE "else"
        %%
        matchedIf: "if" condition "then" HH matchedIf HH "else" HH matchedIf HH
        

        bison manual chapter on Symbols

      4. 您还可以使用单引号字符标记来简化语法。这些甚至不需要声明:

        term: term '*' factor
        factor: '(' expression ')'
        

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多