Rework parse/lex API to be reentrant
Bison and Flex generate different interfaces for reentrant parsers, so handle that different API. We need this change because library support is going to reuse the parser to read in library packages.
This commit is contained in:
parent
38854822da
commit
3ef1d01ad1
|
|
@ -1,6 +1,8 @@
|
|||
%option prefix="yy"
|
||||
%option never-interactive
|
||||
%option nounput
|
||||
%option reentrant
|
||||
%option noyywrap
|
||||
|
||||
%{
|
||||
/*
|
||||
|
|
@ -33,6 +35,7 @@
|
|||
# include <iostream>
|
||||
# include <set>
|
||||
|
||||
# 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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,6 +22,8 @@
|
|||
# include <cstdio>
|
||||
# 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"
|
||||
|
|
|
|||
Loading…
Reference in New Issue