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:
Stephen Williams 2011-07-23 10:07:20 -07:00
parent 3ef1d01ad1
commit df8efed22b
5 changed files with 55 additions and 27 deletions

View File

@ -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);

View File

@ -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]);

View File

@ -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;
}

View File

@ -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"

View File

@ -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);