diff --git a/vhdlpp/parse.y b/vhdlpp/parse.y index e5069a2ce..e326658cf 100644 --- a/vhdlpp/parse.y +++ b/vhdlpp/parse.y @@ -266,6 +266,8 @@ static void touchup_interface_for_functions(std::list*ports) ReportStmt::severity_t severity; SubprogramHeader*subprogram; + + file_open_info_t*file_info; }; /* The keywords are all tokens. */ @@ -343,6 +345,8 @@ static void touchup_interface_for_functions(std::list*ports) %type process_sensitivity_list process_sensitivity_list_opt %type selected_names use_clause +%type file_open_information file_open_information_opt + %type association_element %type association_list port_map_aspect port_map_aspect_opt %type generic_map_aspect generic_map_aspect_opt @@ -1236,7 +1240,7 @@ factor ; file_declaration - : K_file identifier_list ':' IDENTIFIER ';' + : K_file identifier_list ':' IDENTIFIER file_open_information_opt ';' { if (strcasecmp($4, "TEXT")) sorrymsg(@1, "file declaration currently handles only TEXT type.\n"); @@ -1246,7 +1250,27 @@ file_declaration Variable*var = new Variable(*cur, &primitive_INTEGER); FILE_NAME(var, @1); active_scope->bind_name(*cur, var); + + // there was a file name specified, so it needs an implicit call + // to open it at the beginning of simulation and close it at the end + if($5) { + std::list params; + + // add file_open() call in 'initial' block + params.push_back(new ExpName(*cur)); + params.push_back($5->filename()); + params.push_back($5->kind()); + ProcedureCall*fopen_call = new ProcedureCall(perm_string::literal("file_open"), ¶ms); + active_scope->add_initializer(fopen_call); + + // add file_close() call in 'final' block + params.clear(); + params.push_back(new ExpName(*cur)); + ProcedureCall*fclose_call = new ProcedureCall(perm_string::literal("file_close"), ¶ms); + active_scope->add_finalizer(fclose_call); + } } + delete $2; } | K_file error ';' @@ -1255,6 +1279,23 @@ file_declaration } ; +file_open_information + : K_open IDENTIFIER K_is STRING_LITERAL + { + ExpName*mode = new ExpName(lex_strings.make($2)); + delete[]$2; + $$ = new file_open_info_t(new ExpString($4), mode); + } + | K_is STRING_LITERAL + { + $$ = new file_open_info_t(new ExpString($2)); + } + +file_open_information_opt + : file_open_information { $$ = $1; } + | { $$ = 0; } + ; + for_generate_statement : IDENTIFIER ':' K_for IDENTIFIER K_in range K_generate generate_statement_body diff --git a/vhdlpp/parse_types.h b/vhdlpp/parse_types.h index 3639a9c1f..838381efe 100644 --- a/vhdlpp/parse_types.h +++ b/vhdlpp/parse_types.h @@ -102,4 +102,23 @@ struct adding_term { Expression*term; }; +// Stores information for file declarations containing a file name and open mode +// (VHDL-2008 6.4.2.5) +class file_open_info_t { + public: + file_open_info_t(ExpString*filename, ExpName*kind = NULL) + : kind_(kind), filename_(filename) { + // By default files are opened in read-only mode + if(!kind_) kind_ = new ExpName(perm_string::literal("read_mode")); + } + ~file_open_info_t() { delete kind_; delete filename_; } + + ExpName*kind() { return kind_; } + ExpString*filename() { return filename_; } + + private: + ExpName*kind_; + ExpString*filename_; +}; + #endif /* IVL_parse_types_H */