是否有可能在我的.y文件中抛出异常并在.l中启动yyparse()?
让我们编写一些示例代码。这是我的.y文件的一部分:
%{
#include <stdio.h>
#include <string>
#include <cstring>
using namespace std;
extern int yylex();
extern void yyerror(char*);
typedef enum { ZERO_DIVISION = 0,
VAR_DUPLICATE_NAME = 1,
...
GENERAL = 100
} e_errors;
const char* e_errNames[] = {"ZERO_DIVISION","VAR_DUPLICATE_NAME",...,"GENERAL"};
...
%}
//Symbols
%union
{
...
};
%token ...
%start X1
%%
X1:
BEGIN
....
END
;
{
...
if(myCheck(i)>=0) throw VAR_DUPLICATE_NAME;
...
}
;
...
%%
这就是我试图在我的.l文件中以错误的方式捕获VAR_DUPLICATE_NAME的方式:
%{
#include <string.h>
#include "proxydata.tab.h"
void yyerror(char*);
int yyparse(void);
char linebuf[500]; //for output the row in case of syntax error
%}
%option yylineno
blanks [ \t\n]+
text [a-zA-Z0-9]+|[0-9]+.[0-9]+
%%
\n.* { /* saving the next row in case of syntax error */
strncpy(linebuf, yytext+1, sizeof(linebuf)); /* save the next line */
yyless(1); /* give back all but the \n to rescan */
}
{blanks} { /* ignore */ };
... return(...);
{text} { yylval.str_val=(char*)strdup(yytext);
return(IDENTIFIER);
}
. return yytext[0];
%%
void yyerror(char *s){
printf("LINE %d: %s at %s in this line:\n%s\n", yylineno, s, yytext, linebuf);
}
int yywrap (void){
;
}
int main(int num_args, char** args){
if(num_args != 2) {printf("usage: ./parser filename\n"); exit(0);}
FILE* file = fopen(args[1],"r");
if(file == NULL) {printf("couldn't open %s\n",args[1]); exit(0);}
yyin = file;
try{
yyparse();
}catch(int err){
printf("ERROR! %s",e_errNames[err]);
}
fclose(file);
}
通过这种方式,解析器被正确创建,但是当我输入一个生成异常的文件时,我面对以下消息:
在抛出'e_errors'实例后终止调用 (核心倾销)
我知道在写printf("ERROR! %s",e_errNames[err])
之前,我也应该声明。这个extern const char* e_errNames[];
在flex文件的顶部是否足够了?
答案 0 :(得分:1)
据我记忆,如果你抛出e_errors
,你需要抓住e_errors
,而不是int
。即使enum
是整数类型,它也不是int
而catch
不会进行转换。
但是,使用YYABORT
可能会更好,这将使解析器有机会进行清理。 (如果你正在使用C ++骨架,那可能没有必要,但它应该仍然有效。)当然,你需要在某处隐藏错误代码。
答案 1 :(得分:1)
您应该按设计师的意图调用yyerror()
或YY_ABORT。解析器除非出现故障,否则不应抛出异常。并且您不希望解析中出现一个错误,您只需要它们。
请注意,您并未真正捕捉 flex中的错误。您可以在main()
中捕获它,这可能在任何地方。 yyparse()
调用yylex()
,而不是相反。 yyparse()
引发的任何内容都可能会被main()
或您提供的任何其他内容调用,但不会在yylex()
中。