diff --git a/vhdlpp/lexor.lex b/vhdlpp/lexor.lex index 215b3f123..0de49af1f 100644 --- a/vhdlpp/lexor.lex +++ b/vhdlpp/lexor.lex @@ -1,6 +1,8 @@ %option prefix="yy" %option never-interactive %option nounput +%option reentrant +%option noyywrap %{ /* @@ -33,6 +35,7 @@ # include # include +# define YY_DECL int yylex(YYSTYPE*yylvalp, YYLTYPE*yyllocp, yyscan_t yyscanner) //class vhdlnum; //class vhdlreal; @@ -45,7 +48,8 @@ extern int lexor_keyword_code (const char*str, unsigned len); * the name as it exists in the list (and delete the passed string.) * If the name is new, it will be added to the list. */ -extern YYLTYPE yylloc; +#define yylloc (*yyllocp) +#define yylval (*yylvalp) static bool are_underscores_correct(char* text); static bool is_based_correct(char* text); @@ -735,16 +739,15 @@ static int64_t lpow(int64_t left, int64_t right) { return left*lpow(left, right - 1); } -void reset_lexor(FILE*fd, const char*path) +yyscan_t prepare_lexor(FILE*fd) { - yylloc.text = path; - yylloc.first_line = 1; - yyrestart(fd); - - yyparse_set_filepath(path); + yyscan_t scanner; + yylex_init(&scanner); + yyrestart(fd, scanner); + return scanner; } -int yywrap() +void destroy_lexor(yyscan_t scanner) { - return 1; + yylex_destroy(scanner); } diff --git a/vhdlpp/main.cc b/vhdlpp/main.cc index 3bcf7f69e..da78eaf21 100644 --- a/vhdlpp/main.cc +++ b/vhdlpp/main.cc @@ -133,8 +133,11 @@ int main(int argc, char*argv[]) return 1; } - reset_lexor(fd, argv[idx]); - rc = yyparse(); + yyscan_t scanner = prepare_lexor(fd); + rc = yyparse(scanner, argv[idx]); + fclose(fd); + destroy_lexor(scanner); + if (verbose_flag) fprintf(stderr, "yyparse() returns %d, parse_errors=%d, parse_sorrys=%d\n", rc, parse_errors, parse_sorrys); @@ -145,8 +148,6 @@ int main(int argc, char*argv[]) fprintf(stderr, "Encountered %d unsupported constructs parsing %s\n", parse_sorrys, argv[idx]); } - fclose(fd); - if (parse_errors || parse_sorrys) { errors += parse_errors; errors += parse_sorrys; diff --git a/vhdlpp/parse.y b/vhdlpp/parse.y index 655b26a1f..4a2039d11 100644 --- a/vhdlpp/parse.y +++ b/vhdlpp/parse.y @@ -1,4 +1,8 @@ +%pure-parser +%parse-param {yyscan_t yyscanner} +%lex-param { yyscan_t yyscanner } +%parse-param {const char*file_path} %{ /* * Copyright (c) 2011 Stephen Williams (steve@icarus.com) @@ -52,16 +56,19 @@ inline void FILE_NAME(LineInfo*tmp, const struct yyltype&where) text field, that otherwise won't be copied. */ # define YYLLOC_DEFAULT(Current, Rhs, N) do { \ (Current).first_line = (Rhs)[1].first_line; \ - (Current).first_column = (Rhs)[1].first_column; \ - (Current).last_line = (Rhs)[N].last_line; \ - (Current).last_column = (Rhs)[N].last_column; \ - (Current).text = (Rhs)[1].text; } while (0) + (Current).text = file_path; /*(Rhs)[1].text;*/ } while (0) -static void yyerror(const char*msg); +static void yyerror(YYLTYPE*yyllocp,yyscan_t yyscanner,const char*file_path, const char*msg); int parse_errors = 0; int parse_sorrys = 0; +/* + * The parser calls yylex to get the next lexical token. It is only + * called by the bison-generated parser. + */ +extern int yylex(union YYSTYPE*yylvalp,YYLTYPE*yyllocp,yyscan_t yyscanner); + /* * Create an initial scope that collects all the global @@ -233,8 +240,9 @@ const VType*parse_type_by_name(perm_string name) %% - /* The design_file is the root for the VHDL parse. */ -design_file : design_units ; + /* The design_file is the root for the VHDL parse. This rule is also + where I put some run-time initializations. */ +design_file : { yylloc.text = file_path; } design_units ; architecture_body : architecture_body_start @@ -1643,20 +1651,18 @@ K_postponed_opt : K_postponed | ; K_is_opt : K_is | ; %% -static void yyerror(const char* /*msg*/) +static void yyerror(YYLTYPE*, yyscan_t, const char*, const char* /*msg*/) { //fprintf(stderr, "%s\n", msg); parse_errors += 1; } -static const char*file_path = ""; - void errormsg(const YYLTYPE&loc, const char*fmt, ...) { va_list ap; va_start(ap, fmt); - fprintf(stderr, "%s:%d: error: ", file_path, loc.first_line); + fprintf(stderr, "%s:%d: error: ", loc.text, loc.first_line); vfprintf(stderr, fmt, ap); va_end(ap); parse_errors += 1; @@ -1667,17 +1673,8 @@ void sorrymsg(const YYLTYPE&loc, const char*fmt, ...) va_list ap; va_start(ap, fmt); - fprintf(stderr, "%s:%d: sorry: ", file_path, loc.first_line); + fprintf(stderr, "%s:%d: sorry: ", loc.text, loc.first_line); vfprintf(stderr, fmt, ap); va_end(ap); parse_sorrys += 1; } - -/* - * This is used only by the lexor, to set the file path used in error - * messages. - */ -void yyparse_set_filepath(const char*path) -{ - file_path = path; -} diff --git a/vhdlpp/parse_api.h b/vhdlpp/parse_api.h index 1193d8fb9..ac986c5ee 100644 --- a/vhdlpp/parse_api.h +++ b/vhdlpp/parse_api.h @@ -22,6 +22,8 @@ # include # include "entity.h" +typedef void*yyscan_t; + /* * The vlltype supports the passing of detailed source file location * information between the lexical analyzer and the parser. Defining @@ -29,10 +31,8 @@ */ struct yyltype { unsigned first_line; - unsigned first_column; - unsigned last_line; - unsigned last_column; const char*text; + yyltype() { first_line = 1; text = ""; } }; # define YYLTYPE struct yyltype @@ -40,18 +40,13 @@ struct yyltype { * The reset_lexor function takes the fd and makes it the input file * for the lexor. The path argument is used in lexor/parser error messages. */ -extern void reset_lexor(FILE*fd, const char*path); - -/* - * The parser calls yylex to get the next lexical token. It is only - * called by the bison-generated parser. - */ -extern int yylex(void); +extern yyscan_t prepare_lexor(FILE*fd); +extern void destroy_lexor(yyscan_t scanner); /* * This is the bison-generated parser. */ -extern int yyparse(void); +extern int yyparse(yyscan_t scanner, const char*file_path); /* * Use this function during parse to generate error messages. The "loc"