我是野牛新手。我得到的是减少/减少冲突错误,但没有得到它发生的地方。错误消息是“冲突: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检测此冲突在哪里发生。
答案 0 :(得分:2)
问题确实是由您的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 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 NL
或MIF: CODE STATEMENTS NL
。
如果您使用Wikipedia dangling-else page作为指导(甚至没有使用),请仔细查看产品closed_statement: non_if_statement
。 (closed_statement
相当于您的MIF
)。
尽管没有魔术命令where_is_my_error
,但很容易使用bison如果需要生成报告文件(使用-v
或--report
选项来查看该问题)。请参见bison manual debugging chapter中的完整示例。野牛的trace facility也是非常有用的,它将使您不必在整个解析器中分散printf
语句(然后将其删除)。
如果您遵循通常的样式准则,那么您的语法(对您以外的其他人)将更具可读性:
UPPER_CASE
用于令牌,将lower_case
或camelCase
用于非终端。使用野牛的别名功能将关键字写为关键字本身(用引号引起来):
%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 ')'