我是Bison的新手。我收到reduce/reduce冲突错误,但没有得到它发生的位置。错误消息是"conflicts:1 reduce/reduce"。这是我的语法规则。
%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 completen");}
| CODE DECLARATION NL {printf("Declaration completen");}
| STMNT
;
DECLARATION : TYPE V {printf("Dn");}
;
TYPE : INT {printf("In");}
| FLOAT {printf("Fn");}
| CHAR
;
V : V CM V_NM {AddNewVar($3);printf("Vn");}
| V_NM {AddNewVar($1);printf("Vn %sn",$1);}
| /* empty */ {printf("En");}
;
STATEMENTS : { $$ = 0; }
| EXP EQU X {AsgnVal($3,$1);}
| PRINT EXP {printf("Output: %dn",$2);}
| EXP { $$ = $1 ;}
;
STMNT : MIF NL
| UIF NL
;
MIF : IF CON THN HH MIF HH ELSE HH MIF HH {printf("MIF1n");}
| CODE STATEMENTS NL
;
UIF : IF CON THN HH STMNT HH {printf("UIF1n");}
| IF CON THN HH MIF HH ELSE HH UIF HH {printf("UIF2n");}
;
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 zeron");}
}
| FACTOR { $$ = $1; }
| X { $$=VarVal($1); }
;
FACTOR : NUMBER { $$ = $1; }
| LP EXP RP { $$ = $2; }
;
当我插入IF/ELSE的语法时,冲突错误开始了。排除这一部分,我的代码工作得很好。我还想知道是否有任何方法可以使用命令来检测冲突发生在哪里。
-
问题确实是由
if
产品引发的。它是这样的(忽略了其他无关的制作(:MIF : CODE STATEMENTS NL CODE : STMNT | CODE STATEMENTS NL STATEMENTS: %empty STMNT: MIF NL
注意,
NL
始终是CODE
的可能前瞻,因为CODE: CODE STATEMENTS NL
和STATEMENTS: %empty
,这意味着CODE
可以导出CODE NL
。(CODE NL⇒CODE STATEMENTS NLNL (CODE: CODE STATEMENTS NL) ⇒STMNTSTATEMENTS NL NL (CODE: STMNT) ⇒MIF NLSTATEMENTS NL NL (STMNT: MIF NL) ⇒MIFNL STATEMENTS NL NL (MIF: CODE STATEMENTS NL) ⇒CODE STATEMENTS NLNL STATEMENTS NL NL
这当然是减少冲突。当解析器找到
CODE STATEMENTS NL
并将NL
视为前瞻时,它可以使用缩减CODE: CODE STATEMENTS NL
或MIF: CODE STATEMENTS NL
。 -
如果你正在使用维基百科的其他页面作为指南(或者即使你没有(,请仔细查看产品
closed_statement: non_if_statement
。(closed_statement
相当于您的MIF
(。 -
虽然没有神奇的命令
where_is_my_error
,但使用bison将在请求时生成的报告文件(使用-v
或--report
选项(很容易看到这个问题。请参阅bison手动调试一章中的完整示例。bison的跟踪功能也非常有用,它将使您不必在整个解析器中散布printf
语句(稍后再将其删除(。 -
如果你遵循通常的风格准则:,你的语法(对你以外的人(会可读得多
- 对令牌使用
UPPER_CASE
,对非终端使用lower_case
或camelCase
- 写出完整的单词。Rmvng vwls frm dntfrs mks yr cd nrdbl
-
使用bison的别名功能将关键字写为关键字本身(用引号括起来(:
%token T_THEN "then" T_IF "if" T_ELSE "else" %% matchedIf: "if" condition "then" HH matchedIf HH "else" HH matchedIf HH
参见野牛手册中关于符号的章节
-
您还可以使用单引号字符标记来简化语法。这些甚至不需要声明:
term: term '*' factor factor: '(' expression ')'
- 对令牌使用