在Bison抛出异常并在main()中捕获

时间:2015-08-07 17:35:45

标签: c++ exception bison

是否有可能在我的.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文件的顶部是否足够了?

2 个答案:

答案 0 :(得分:1)

据我记忆,如果你抛出e_errors,你需要抓住e_errors,而不是int。即使enum是整数类型,它也不是intcatch不会进行转换。

但是,使用YYABORT可能会更好,这将使解析器有机会进行清理。 (如果你正在使用C ++骨架,那可能没有必要,但它应该仍然有效。)当然,你需要在某处隐藏错误代码。

答案 1 :(得分:1)

您应该按设计师的意图调用yyerror()或YY_ABORT。解析器除非出现故障,否则不应抛出异常。并且您不希望解析中出现一个错误,您只需要它们。

请注意,您并未真正捕捉 flex中的错误。您可以在main()中捕获它,这可能在任何地方。 yyparse()调用yylex(),而不是相反。 yyparse()引发的任何内容都可能会被main()或您提供的任何其他内容调用,但不会在yylex()中。