Parse work library for imported packages
When a "use" clause tries to pull a package from the work library, put together a file name and try to find that package in the work library directory. If found, parse the package file and try again to find the package.
This commit is contained in:
parent
3ef1d01ad1
commit
df8efed22b
|
|
@ -30,6 +30,12 @@ using namespace std;
|
|||
static const char*library_work_path = 0;
|
||||
static void store_package_in_work(const Package*pack);
|
||||
|
||||
static string make_work_package_path(const char*name)
|
||||
{
|
||||
return string(library_work_path).append("/").append(name).append(".pkg");
|
||||
}
|
||||
|
||||
|
||||
struct library_contents {
|
||||
map<perm_string,Package*> packages;
|
||||
};
|
||||
|
|
@ -66,7 +72,7 @@ void dump_libraries(ostream&file)
|
|||
* This function saves a package into the named library. Create the
|
||||
* library if necessary.
|
||||
*/
|
||||
void library_save_package(const char*libname, Package*pack)
|
||||
void library_save_package(const char*libname, Package*pack, bool parse_work)
|
||||
{
|
||||
if (libname == 0)
|
||||
libname = "work";
|
||||
|
|
@ -76,7 +82,9 @@ void library_save_package(const char*libname, Package*pack)
|
|||
|
||||
lib.packages[pack->name()] = pack;
|
||||
|
||||
if (use_libname == "work")
|
||||
// If this is a work package, and we are NOT parsing the work
|
||||
// library right now, then store it in the work library.
|
||||
if (use_libname == "work" && !parse_work)
|
||||
store_package_in_work(pack);
|
||||
}
|
||||
|
||||
|
|
@ -114,6 +122,14 @@ void library_use(const YYLTYPE&loc, ActiveScope*res,
|
|||
|
||||
struct library_contents&lib = libraries[use_library];
|
||||
Package*pack = lib.packages[use_package];
|
||||
// If the package is not found in the work library already
|
||||
// parsed, then see if it exists unparsed.
|
||||
if (use_library=="work" && pack == 0) {
|
||||
string path = make_work_package_path(use_package.str());
|
||||
parse_source_file(path.c_str(), true);
|
||||
pack = lib.packages[use_package];
|
||||
}
|
||||
// If the package is still not found, then error.
|
||||
if (pack == 0) {
|
||||
errormsg(loc, "No package %s in library %s\n",
|
||||
use_package.str(), use_library.str());
|
||||
|
|
@ -229,7 +245,7 @@ void library_set_work_path(const char*path)
|
|||
|
||||
static void store_package_in_work(const Package*pack)
|
||||
{
|
||||
string path = string(library_work_path).append("/").append(pack->name()).append(".pkg");
|
||||
string path = make_work_package_path(pack->name());
|
||||
|
||||
ofstream file (path.c_str(), ios_base::out|ios_base::app);
|
||||
|
||||
|
|
|
|||
|
|
@ -127,19 +127,12 @@ int main(int argc, char*argv[])
|
|||
for (int idx = optind ; idx < argc ; idx += 1) {
|
||||
parse_errors = 0;
|
||||
parse_sorrys = 0;
|
||||
FILE*fd = fopen(argv[idx], "r");
|
||||
if (fd == 0) {
|
||||
perror(argv[idx]);
|
||||
rc = parse_source_file(argv[idx], false);
|
||||
if (rc < 0)
|
||||
return 1;
|
||||
}
|
||||
|
||||
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);
|
||||
fprintf(stderr, "parse_source_file() returns %d, parse_errors=%d, parse_sorrys=%d\n", rc, parse_errors, parse_sorrys);
|
||||
|
||||
if (parse_errors > 0) {
|
||||
fprintf(stderr, "Encountered %d errors parsing %s\n", parse_errors, argv[idx]);
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
|
||||
%pure-parser
|
||||
%parse-param {yyscan_t yyscanner}
|
||||
%lex-param { yyscan_t yyscanner }
|
||||
%parse-param {yyscan_t yyscanner }
|
||||
%parse-param {const char*file_path}
|
||||
%parse-param {bool parsing_work }
|
||||
%{
|
||||
/*
|
||||
* Copyright (c) 2011 Stephen Williams (steve@icarus.com)
|
||||
|
|
@ -58,7 +59,7 @@ inline void FILE_NAME(LineInfo*tmp, const struct yyltype&where)
|
|||
(Current).first_line = (Rhs)[1].first_line; \
|
||||
(Current).text = file_path; /*(Rhs)[1].text;*/ } while (0)
|
||||
|
||||
static void yyerror(YYLTYPE*yyllocp,yyscan_t yyscanner,const char*file_path, const char*msg);
|
||||
static void yyerror(YYLTYPE*yyllocp,yyscan_t yyscanner,const char*file_path,bool, const char*msg);
|
||||
|
||||
int parse_errors = 0;
|
||||
int parse_sorrys = 0;
|
||||
|
|
@ -1110,7 +1111,7 @@ package_declaration
|
|||
if ($6) delete[]$6;
|
||||
pop_scope();
|
||||
/* Put this package into the work library. */
|
||||
library_save_package(0, tmp);
|
||||
library_save_package(0, tmp, parsing_work);
|
||||
}
|
||||
| package_declaration_start K_is error K_end K_package_opt identifier_opt ';'
|
||||
{ errormsg(@3, "Syntax error in package clause.\n");
|
||||
|
|
@ -1651,7 +1652,7 @@ K_postponed_opt : K_postponed | ;
|
|||
K_is_opt : K_is | ;
|
||||
%%
|
||||
|
||||
static void yyerror(YYLTYPE*, yyscan_t, const char*, const char* /*msg*/)
|
||||
static void yyerror(YYLTYPE*, yyscan_t, const char*, bool, const char* /*msg*/)
|
||||
{
|
||||
//fprintf(stderr, "%s\n", msg);
|
||||
parse_errors += 1;
|
||||
|
|
@ -1678,3 +1679,27 @@ void sorrymsg(const YYLTYPE&loc, const char*fmt, ...)
|
|||
va_end(ap);
|
||||
parse_sorrys += 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 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 yyscan_t prepare_lexor(FILE*fd);
|
||||
extern void destroy_lexor(yyscan_t scanner);
|
||||
|
||||
int parse_source_file(const char*file_path, bool work_library_flag)
|
||||
{
|
||||
FILE*fd = fopen(file_path, "r");
|
||||
if (fd == 0) {
|
||||
perror(file_path);
|
||||
return -1;
|
||||
}
|
||||
|
||||
yyscan_t scanner = prepare_lexor(fd);
|
||||
int rc = yyparse(scanner, file_path, work_library_flag);
|
||||
fclose(fd);
|
||||
destroy_lexor(scanner);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,16 +37,10 @@ struct yyltype {
|
|||
# define YYLTYPE 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.
|
||||
* This calls the bison-generated parser with the given file path as
|
||||
* the input stream. If the file cannot be opened, this returns -1.
|
||||
*/
|
||||
extern yyscan_t prepare_lexor(FILE*fd);
|
||||
extern void destroy_lexor(yyscan_t scanner);
|
||||
|
||||
/*
|
||||
* This is the bison-generated parser.
|
||||
*/
|
||||
extern int yyparse(yyscan_t scanner, const char*file_path);
|
||||
extern int parse_source_file(const char*file_path, bool parse_work_library);
|
||||
|
||||
/*
|
||||
* Use this function during parse to generate error messages. The "loc"
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ extern const VType* calculate_subtype_range(const YYLTYPE&loc, const char*base_n
|
|||
*/
|
||||
extern const VType* parse_type_by_name(perm_string name);
|
||||
|
||||
extern void library_save_package(const char*libname, Package*pack);
|
||||
extern void library_save_package(const char*libname, Package*pack, bool parse_work);
|
||||
|
||||
extern void library_import(const YYLTYPE&loc, const std::list<perm_string>*names);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue