Bison yyerror 忽略语法上的下一个标记
Bison yyerror ignore next token on grammar
所以我在我的 Bison 程序上遇到了一个小问题,首先要知道我的程序可以工作并且功能齐全,你在这里看到的只是一个摘录,足以帮助我。
基本上解析器读取“vector(x,2)”程序正在检查变量“” x”已经存在且如果元素个数2”更大然后 1. 当这种情况没有发生时,我会抛出 yyerror。问题是错误没有忽略令牌的其余部分。让我举个vector(x,1)的例子,你会看到它应该在reduce时忽略语句但不是。
Starting parse
Entering state 0
Stack now 0
Reducing stack by rule 1 (line 58):
-> $$ = nterm PROGRAM (1.1: )
Entering state 1
...
....
Entering state 24
Stack now 0 1 5 12 15 18 24
Next token is token PARENTSIS_RIGHT (1.1: )
Shifting token PARENTSIS_RIGHT (1.1: )
Entering state 33
Stack now 0 1 5 12 15 18 24 33
Reducing stack by rule 10 (line 87):
= token RESEV_VAR (1.1: )
= token PARENTSIS_LEFT (1.1: )
= token STRING (1.1: )
= token COMMA (1.1: )
= nterm ELEMENTS (1.1: )
= token PARENTSIS_RIGHT (1.1: )
Erro: blalalala.
-> $$ = nterm DEFINE_VECTOR (1.1: ) //here it should not run this one should skip it
Entering state 9
Stack now 0 1 9
Reducing stack by rule 6 (line 65):
= nterm DEFINE_VECTOR (1.1: )
VECTOR
-> $$ = nterm DECLARACAO (1.1: )
正如你在最后看到的那样,当我指定错误时,他是 运行 减少到 DEFINE_VECTOR。
%start PROGRAM
%%
PROGRAM:
| PROGRAM STATMENT
| PROGRAM error STATMENT
;
STATMENT: QUIT { fclose(yyin); printf("\nBYE\n"); exit('0');}
| DEFINE_VAR { printf("\tVAR\n"); }
| DEFINE_VECTOR { printf("\tVAR\n"); }
;
...
DEFINE_VECTOR: RESEV_VAR PARENTSIS_LEFT STRING COMMA ELEMENT PARENTSIS_RIGHT {
if(<=1){
yyerror("Vector to small");
}else{
if(check()==0){
createVar(, 2, );
}else{
yyerror("Variable alrady exists");
}
}
}
;
ELEMENTS: ELMENTINT
| ELMENTFLOAT{ $$ = ;}
;
解决方案:
%start PROGRAM
%%
PROGRAM:
| PROGRAM STATMENT
| PROGRAM error STATMENT
| PROGRAM error PARENTSIS_RIGHT STATMENT // added here
;
STATMENT: QUIT { fclose(yyin); printf("\nBYE\n"); exit('0');}
| DEFINE_VAR { printf("\tVAR\n"); }
| DEFINE_VECTOR { printf("\tVAR\n"); }
;
...
DEFINE_VECTOR: RESEV_VAR PARENTSIS_LEFT STRING COMMA ELEMENT PARENTSIS_RIGHT {
if(<=1){
yyerror("Vector to small");
YYERROR; //added here
}else{
if(check()==0){
createVar(, 2, );
}else{
yyerror("Variable alrady exists");
YYERROR; added here
}
}
}
;
ELEMENTS: ELMENTINT
| ELMENTFLOAT{ $$ = ;}
;
yyerror
只是一个打印错误信息的函数。当 bison 解析器出现语法错误时会调用它,但您也可以在其他地方调用它来打印错误。它对解析没有影响(它不会中断或更改它——它不会“抛出”)
如果你想影响解析,你需要使用YYERROR
(触发解析器错误的宏,然后解析器将尝试从中恢复)。然而,如果你有像这样的语义错误(不是语法错误),你可能不想这样做,因为没有语法可以恢复。您可能希望使用 YYABORT
立即中止解析(来自 yyparse 的 return)。或者您可能只想继续解析,以可能识别其他错误。
所以我在我的 Bison 程序上遇到了一个小问题,首先要知道我的程序可以工作并且功能齐全,你在这里看到的只是一个摘录,足以帮助我。
基本上解析器读取“vector(x,2)”程序正在检查变量“” x”已经存在且如果元素个数2”更大然后 1. 当这种情况没有发生时,我会抛出 yyerror。问题是错误没有忽略令牌的其余部分。让我举个vector(x,1)的例子,你会看到它应该在reduce时忽略语句但不是。
Starting parse
Entering state 0
Stack now 0
Reducing stack by rule 1 (line 58):
-> $$ = nterm PROGRAM (1.1: )
Entering state 1
...
....
Entering state 24
Stack now 0 1 5 12 15 18 24
Next token is token PARENTSIS_RIGHT (1.1: )
Shifting token PARENTSIS_RIGHT (1.1: )
Entering state 33
Stack now 0 1 5 12 15 18 24 33
Reducing stack by rule 10 (line 87):
= token RESEV_VAR (1.1: )
= token PARENTSIS_LEFT (1.1: )
= token STRING (1.1: )
= token COMMA (1.1: )
= nterm ELEMENTS (1.1: )
= token PARENTSIS_RIGHT (1.1: )
Erro: blalalala.
-> $$ = nterm DEFINE_VECTOR (1.1: ) //here it should not run this one should skip it
Entering state 9
Stack now 0 1 9
Reducing stack by rule 6 (line 65):
= nterm DEFINE_VECTOR (1.1: )
VECTOR
-> $$ = nterm DECLARACAO (1.1: )
正如你在最后看到的那样,当我指定错误时,他是 运行 减少到 DEFINE_VECTOR。
%start PROGRAM
%%
PROGRAM:
| PROGRAM STATMENT
| PROGRAM error STATMENT
;
STATMENT: QUIT { fclose(yyin); printf("\nBYE\n"); exit('0');}
| DEFINE_VAR { printf("\tVAR\n"); }
| DEFINE_VECTOR { printf("\tVAR\n"); }
;
...
DEFINE_VECTOR: RESEV_VAR PARENTSIS_LEFT STRING COMMA ELEMENT PARENTSIS_RIGHT {
if(<=1){
yyerror("Vector to small");
}else{
if(check()==0){
createVar(, 2, );
}else{
yyerror("Variable alrady exists");
}
}
}
;
ELEMENTS: ELMENTINT
| ELMENTFLOAT{ $$ = ;}
;
解决方案:
%start PROGRAM
%%
PROGRAM:
| PROGRAM STATMENT
| PROGRAM error STATMENT
| PROGRAM error PARENTSIS_RIGHT STATMENT // added here
;
STATMENT: QUIT { fclose(yyin); printf("\nBYE\n"); exit('0');}
| DEFINE_VAR { printf("\tVAR\n"); }
| DEFINE_VECTOR { printf("\tVAR\n"); }
;
...
DEFINE_VECTOR: RESEV_VAR PARENTSIS_LEFT STRING COMMA ELEMENT PARENTSIS_RIGHT {
if(<=1){
yyerror("Vector to small");
YYERROR; //added here
}else{
if(check()==0){
createVar(, 2, );
}else{
yyerror("Variable alrady exists");
YYERROR; added here
}
}
}
;
ELEMENTS: ELMENTINT
| ELMENTFLOAT{ $$ = ;}
;
yyerror
只是一个打印错误信息的函数。当 bison 解析器出现语法错误时会调用它,但您也可以在其他地方调用它来打印错误。它对解析没有影响(它不会中断或更改它——它不会“抛出”)
如果你想影响解析,你需要使用YYERROR
(触发解析器错误的宏,然后解析器将尝试从中恢复)。然而,如果你有像这样的语义错误(不是语法错误),你可能不想这样做,因为没有语法可以恢复。您可能希望使用 YYABORT
立即中止解析(来自 yyparse 的 return)。或者您可能只想继续解析,以可能识别其他错误。