diff options
-rw-r--r-- | bnf/ast_types.hpp | 22 | ||||
-rw-r--r-- | bnf/common.hpp | 21 | ||||
-rw-r--r-- | bnf/main.cpp | 155 | ||||
-rw-r--r-- | bnf/rust.y | 63 | ||||
-rw-r--r-- | bnf/rust_expr.y.h | 4 | ||||
-rw-r--r-- | bnf/rust_expr.y_tree.h | 8 |
6 files changed, 178 insertions, 95 deletions
diff --git a/bnf/ast_types.hpp b/bnf/ast_types.hpp index cef70bc5..daa71b89 100644 --- a/bnf/ast_types.hpp +++ b/bnf/ast_types.hpp @@ -115,6 +115,7 @@ public: class Item { bool m_is_pub; +protected: AttrList m_attrs; public: Item(): @@ -148,7 +149,11 @@ class Module: bool m_is_extern; ::std::string m_name; ItemList m_items; + + ::std::vector<::std::string> m_mod_path; + ::std::string m_filename, m_base_dir; public: + Module(Module&&) = default; Module(::std::string name): m_is_extern(true), m_name(name) @@ -158,15 +163,32 @@ public: m_is_extern(false), m_items( ::std::move(items) ) {} + Module& operator=(Module&& x) { + assert(m_is_extern); + assert(x.m_name == ""); + m_items = ::std::move(x.m_items); + this->add_attrs( ::std::move(x.m_attrs) ); + } bool is_external() const { return m_is_extern; } const ::std::string& name() const { return m_name; } + const ::std::string& filename() const { return m_filename; } + const ::std::string& base_dir() const { return m_base_dir; } + const ::std::vector<::std::string>& mod_path() const { return m_mod_path; } void set_name(::std::string name) { assert(m_name == ""); m_name = name; } + void set_mod_path(::std::vector<::std::string> mod_path) { + m_mod_path = ::std::move(mod_path); + } + void set_paths(::std::string filename, ::std::string base_dir) { + m_filename = filename; + m_base_dir = base_dir; + } + ItemList& items() { return m_items; } diff --git a/bnf/common.hpp b/bnf/common.hpp new file mode 100644 index 00000000..2a74a7ba --- /dev/null +++ b/bnf/common.hpp @@ -0,0 +1,21 @@ +#pragma once + +namespace std { + +template <typename T> +inline ::std::ostream& operator<<(::std::ostream& os, const ::std::vector<T>& v) { + if( v.size() > 0 ) + { + bool is_first = true; + for( const auto& i : v ) + { + if(!is_first) + os << ", "; + is_first = false; + os << i; + } + } + return os; +} + +}; diff --git a/bnf/main.cpp b/bnf/main.cpp index f88eb21f..020ff0f6 100644 --- a/bnf/main.cpp +++ b/bnf/main.cpp @@ -1,52 +1,56 @@ #include <stdio.h> #include <string.h> +#include <iostream> #include "lex.hpp" +#include "common.hpp" extern FILE* yyin; ::std::string get_dir_path(const ::std::string& input) { auto pos = input.rfind("/"); if( pos == ::std::string::npos) { - return ""; + return "./"; } else { return ::std::string( input, 0, input.rfind("/") + 1 ); } } -int main(int argc, char *argv[]) { - const char *base_filename; - if(argc < 2 || strcmp(argv[1], "-") == 0) { - yyin = stdin; - base_filename = "-"; - } - else { - base_filename = argv[1]; - yyin = fopen(argv[1], "r"); +::std::unique_ptr<Module> parse_module_file(::std::string filename, ::std::string base_path) +{ + ::std::cout << "filename = " << filename << ", base_path = " << base_path << ";" << ::std::endl; + + if( filename != "-" ) { + yyin = fopen(filename.c_str(), "r"); if( !yyin ) { - fprintf(stderr, "ERROR: Unable to open '%s': '%s'\n", argv[1], strerror(errno)); - return 1; + fprintf(stderr, "ERROR: Unable to open '%s': '%s'\n", filename.c_str(), strerror(errno)); + exit(1); } } - yylineno = 1; - yydebug = (getenv("BNFDEBUG") != NULL); - - ParserContext context(base_filename); - if( context.filename != "-" ) { - context.base_path = get_dir_path(context.filename); - } + ParserContext context( ::std::move(filename) ); + context.base_path = ::std::move(base_path); + + yylineno = 1; int rv = yyparse(context); - fclose(yyin); + if( yyin != stdin ) { + fclose(yyin); + } if( rv != 0 ) { - return rv; + exit(1); } - + assert( context.output_module.get() ); - auto& mod = *context.output_module; - printf("output module = %p\n", &mod); + //context.output_module->set_paths( ::std::move(context.filename), ::std::move(context.base_path) ); + return ::std::move(context.output_module); +} + +void post_process_module(Module& mod, const ::std::string& mod_filename, const ::std::string& mod_dir_path) +{ + ::std::cout << "mod = ["<<mod.mod_path()<<"], mod_filename = " << mod_filename << ", mod_dir_path = " << mod_dir_path << ";" << ::std::endl; - for(auto& item : mod.items()) { + for(auto& item : mod.items()) + { Module* opt_submod = dynamic_cast<Module*>(item.get()); if( !opt_submod ) continue; Module& submod = *opt_submod; @@ -54,49 +58,78 @@ int main(int argc, char *argv[]) { if( ! submod.is_external() ) { // - inline modules can be ignored.. for now - continue ; - } - ::std::string filename; - ::std::string base_path; - if( context.filename == "-" ) { - return 1; - } - else if( submod.attrs().has("path") ) { - filename = get_dir_path(context.filename) + submod.attrs().get_first("path").string(); - base_path = get_dir_path(filename); - } - else if( context.base_path == "" ) { - return 1; + if( mod_dir_path != "" ) { + submod.set_paths( mod_filename, mod_dir_path + submod.name() + "/" ); + } } - else { - filename = context.base_path + submod.name() + ".rs"; - base_path = ""; - yyin = fopen( filename.c_str(), "r" ); - if( !yyin ) { - printf("> '%s' not found\n", filename.c_str()); - base_path = context.base_path + submod.name() + "/"; - filename = base_path + "mod.rs"; + else + { + ::std::string filename; + ::std::string base_path; + if( mod_filename == "-" ) { + fprintf(stderr, "ERROR: Referencing 'mod %s;' from stdin\n", submod.name().c_str()); + exit(1); + } + else if( submod.attrs().has("path") ) { + filename = get_dir_path(mod_filename) + submod.attrs().get_first("path").string(); + base_path = get_dir_path(filename); + } + else if( mod_dir_path == "" ) { + fprintf(stderr, "ERROR: Referencing 'mod %s;' from non-controlling file\n", submod.name().c_str()); + exit(1); } else { - fclose(yyin); + filename = mod_dir_path + submod.name() + ".rs"; + base_path = ""; + yyin = fopen( filename.c_str(), "r" ); + if( !yyin ) { + printf("> '%s' not found\n", filename.c_str()); + base_path = mod_dir_path + submod.name() + "/"; + filename = base_path + "mod.rs"; + } + else { + fclose(yyin); + } } - } - assert(filename.size() > 0); - yyin = fopen( filename.c_str(), "r" ); - if( !yyin ) { - printf("> '%s' not found\n", filename.c_str()); - return 1; + + assert(filename.size() > 0); + submod = ::std::move( *parse_module_file(filename, base_path) ); + submod.set_paths( filename, base_path ); } - ParserContext new_context(filename); - yylineno = 1; - int rv = yyparse(new_context); - fclose(yyin); - if( rv != 0 ) { - return rv; - } - submod = ::std::move( *new_context.output_module ); + auto mp = mod.mod_path(); + mp.push_back(submod.name()); + submod.set_mod_path(::std::move(mp)); + } + + for(auto& item : mod.items()) + { + Module* opt_submod = dynamic_cast<Module*>(item.get()); + if( !opt_submod ) continue; + Module& submod = *opt_submod; + + const ::std::string& submod_fname = submod.filename(); + const ::std::string& submod_dir = submod.base_dir(); + post_process_module(submod, submod_fname, submod_dir); + } +} + +int main(int argc, char *argv[]) { + ::std::string base_filename; + if(argc < 2 || strcmp(argv[1], "-") == 0) { + yyin = stdin; + base_filename = "-"; } + else { + base_filename = argv[1]; + } + yydebug = (getenv("BNFDEBUG") != NULL); + + ::std::string base_path = (base_filename == "-" ? ::std::string("") : get_dir_path(base_filename)); + auto mod = parse_module_file(base_filename, base_path); + printf("output module = %p\n", &*mod); + + post_process_module(*mod, base_filename, base_path); return 0; } @@ -73,19 +73,19 @@ %{ // TODO: Replace this with a C++-safe printf -/*static inline*/ void bnf_trace(const char* fmt, ...) { - fprintf(stderr, "\x1b[32m""TRACE: "); +/*static inline*/ void bnf_trace(const ParserContext& context, const char* fmt, ...) { + fprintf(stderr, "\x1b[32m""TRACE:%s:%i: ", context.filename.c_str(), yylineno); va_list args; va_start(args, fmt); vfprintf(stderr, fmt, args); va_end(args); fprintf(stderr, "\x1b[0m\n"); } -/*static inline*/ void bnf_trace(const char* fmt, const ::std::string* s) { - bnf_trace(fmt, s->c_str(), '0'); +/*static inline*/ void bnf_trace(const ParserContext& context, const char* fmt, const ::std::string* s) { + bnf_trace(context, fmt, s->c_str(), '0'); } -/*static inline*/ void bnf_trace(const char* fmt, const ::std::string& s) { - bnf_trace(fmt, s.c_str(), '0'); +/*static inline*/ void bnf_trace(const ParserContext& context, const char* fmt, const ::std::string& s) { + bnf_trace(context, fmt, s.c_str(), '0'); } %} @@ -121,8 +121,8 @@ super_attrs ; opt_pub - : /* mt */ { $$ = false; bnf_trace("private"); } - | RWD_pub { $$ = true; bnf_trace("public"); } + : /* mt */ { $$ = false; bnf_trace(context, "private"); } + | RWD_pub { $$ = true; bnf_trace(context, "public"); } ; opt_comma: | ','; opt_semicolon: | ';'; @@ -208,14 +208,14 @@ extern_item module_def : IDENT '{' module_root '}' { $3->set_name( consume($1) ); $$ = new Module(consume($3)); } - | IDENT ';' { bnf_trace("mod %s;", $1); $$ = new Module( consume($1) ); } + | IDENT ';' { bnf_trace(context, "mod %s;", $1); $$ = new Module( consume($1) ); } ; /* --- Function --- */ -fn_def: fn_def_hdr code { bnf_trace("function defined"); }; -fn_def_hdr: IDENT generic_def '(' fn_def_args ')' fn_def_ret where_clause { $$ = new Fn(); bnf_trace("function '%s'", *$1); }; +fn_def: fn_def_hdr code { bnf_trace(context, "function defined"); }; +fn_def_hdr: IDENT generic_def '(' fn_def_args ')' fn_def_ret where_clause { $$ = new Fn(); bnf_trace(context, "function '%s'", *$1); }; -fn_def_hdr_PROTO: IDENT generic_def '(' fn_def_args_PROTO ')' fn_def_ret where_clause { $$ = new Fn(); bnf_trace("function '%s'", *$1); }; +fn_def_hdr_PROTO: IDENT generic_def '(' fn_def_args_PROTO ')' fn_def_ret where_clause { $$ = new Fn(); bnf_trace(context, "function '%s'", *$1); }; fn_def_ret : /* -> () */ @@ -267,6 +267,7 @@ use_def | DOUBLECOLON use_path use_def_tail { $$ = new UseSet(/* TODO */); } | use_path use_def_tail { $$ = new UseSet(/* TODO */); } | '{' use_picks '}' ';' { $$ = new UseSet( Path(Path::TagAbs()), consume($2) ); } + | DOUBLECOLON '{' use_picks '}' ';' { $$ = new UseSet( Path(Path::TagAbs()), consume($3) ); } ; use_def_tail : RWD_as IDENT ';' { $$ = new UseItems(UseItems::TagRename(), consume($2) ); } @@ -296,9 +297,9 @@ const_value /* --- Struct --- */ struct_def - : IDENT generic_def where_clause ';' { $$ = new Struct(); bnf_trace("unit-like struct"); } - | IDENT generic_def '(' tuple_struct_def_items opt_comma ')' where_clause ';' { $$ = new Struct(); bnf_trace("tuple struct"); } - | IDENT generic_def where_clause '{' struct_def_items opt_comma '}' { $$ = new Struct(); bnf_trace("normal struct"); } + : IDENT generic_def where_clause ';' { $$ = new Struct(); bnf_trace(context, "unit-like struct"); } + | IDENT generic_def '(' tuple_struct_def_items opt_comma ')' where_clause ';' { $$ = new Struct(); bnf_trace(context, "tuple struct"); } + | IDENT generic_def where_clause '{' struct_def_items opt_comma '}' { $$ = new Struct(); bnf_trace(context, "normal struct"); } ; tuple_struct_def_items @@ -309,7 +310,7 @@ tuple_struct_def_item: attrs opt_pub type; struct_def_items : struct_def_items ',' struct_def_item - | struct_def_item { bnf_trace("struct_def_item"); } + | struct_def_item { bnf_trace(context, "struct_def_item"); } ; struct_def_item: attrs opt_pub IDENT ':' type; @@ -342,10 +343,10 @@ trait_item /* --- Impl --- */ impl_def: impl_def_line '{' impl_items '}' { $$ = new Impl(); }; impl_def_line - : generic_def trait_path RWD_for type where_clause { bnf_trace("trait impl"); } - | generic_def '!' trait_path RWD_for type where_clause { bnf_trace("negative trait impl"); } - | generic_def trait_path RWD_for DOUBLEDOT where_clause { bnf_trace("wildcard impl"); } - | generic_def type where_clause { bnf_trace("inherent impl"); } + : generic_def trait_path RWD_for type where_clause { bnf_trace(context, "trait impl"); } + | generic_def '!' trait_path RWD_for type where_clause { bnf_trace(context, "negative trait impl"); } + | generic_def trait_path RWD_for DOUBLEDOT where_clause { bnf_trace(context, "wildcard impl"); } + | generic_def type where_clause { bnf_trace(context, "inherent impl"); } ; impl_items: | impl_items attrs impl_item; impl_item @@ -356,12 +357,12 @@ impl_item /* Generic paramters */ -generic_def : /* mt */ | '<' generic_def_list '>' { bnf_trace("generic_def_list"); }; +generic_def : /* mt */ | '<' generic_def_list '>' { bnf_trace(context, "generic_def_list"); }; generic_def_list : generic_def_one | generic_def_list ',' generic_def_one | ; generic_def_one : IDENT ':' bounds '=' type | IDENT '=' type - | IDENT ':' bounds { bnf_trace("bounded ident"); } + | IDENT ':' bounds { bnf_trace(context, "bounded ident"); } | IDENT | LIFETIME | LIFETIME ':' LIFETIME @@ -394,7 +395,7 @@ dlt: DOUBLELT { context.pushback('<'); context.pushback('<'); } type_args : '<' type_exprs '>' - | '<' type_exprs DOUBLEGT { bnf_trace("Double-gt terminated type expr"); context.pushback('>'); } + | '<' type_exprs DOUBLEGT { bnf_trace(context, "Double-gt terminated type expr"); context.pushback('>'); } | dlt type_args ; @@ -512,6 +513,8 @@ nonbind_pattern | value_pattern TRIPLEDOT value_pattern | '&' pattern | '&' RWD_mut pattern + | DOUBLEAMP pattern + | DOUBLEAMP RWD_mut pattern ; value_pattern : expr_path @@ -531,7 +534,7 @@ pattern_list Expressions! ========================================= */ -code: block { bnf_trace("code parsed"); }; +code: block { bnf_trace(context, "code parsed"); }; block: '{' block_contents '}'; @@ -544,10 +547,10 @@ tail_expr | flow_control ; flow_control - : RWD_return opt_semicolon {} - | RWD_return expr_0 opt_semicolon {} - | RWD_break opt_lifetime opt_semicolon {} - | RWD_continue opt_lifetime opt_semicolon {} + : RWD_return {} + | RWD_return expr_0 {} + | RWD_break opt_lifetime {} + | RWD_continue opt_lifetime {} ; block_lines: | block_lines block_line; block_line @@ -581,7 +584,7 @@ expr_blocks : RWD_match expr_NOSTRLIT '{' match_arms '}' { } | RWD_if if_block | RWD_unsafe '{' block_contents '}' { } -/* | flow_control */ + | flow_control | loop_block | block ; @@ -624,7 +627,7 @@ match_arm | match_arm_brace ; match_arm_brace : match_patterns FATARROW '{' block_contents '}' { }; -match_arm_expr: match_patterns FATARROW tail_expr { bnf_trace("match_arm"); }; +match_arm_expr: match_patterns FATARROW tail_expr { bnf_trace(context, "match_arm"); }; /* rust_expr.y.h inserted */ diff --git a/bnf/rust_expr.y.h b/bnf/rust_expr.y.h index 78121070..7b3494c8 100644 --- a/bnf/rust_expr.y.h +++ b/bnf/rust_expr.y.h @@ -9,6 +9,10 @@ closure_arg : pattern | pattern ':' type ; +closure_ret + : + | THINARROW type + ; #define SUFFIX_is_ #define _(v) v diff --git a/bnf/rust_expr.y_tree.h b/bnf/rust_expr.y_tree.h index 26beb77c..756e5e4a 100644 --- a/bnf/rust_expr.y_tree.h +++ b/bnf/rust_expr.y_tree.h @@ -62,7 +62,7 @@ _(expr_9) /* 10: Cast */ _(expr_cast) : _(expr_11) - | _(expr_cast) RWD_as type_ele { bnf_trace("expr:cast"); } + | _(expr_cast) RWD_as type_ele { bnf_trace(context, "expr:cast"); } ; /* 11: Times/Div/Modulo */ _(expr_11) @@ -95,7 +95,7 @@ _(expr_fc) _(expr_value) : CHARLIT | INTEGER | FLOAT | STRING | expr_blocks - | expr_path '(' expr_list ')' { bnf_trace("function call"); } + | expr_path '(' expr_list ')' { bnf_trace(context, "function call"); } #ifndef SUFFIX_is__NOSTRLIT | expr_path '{' struct_literal_list '}' | expr_path '{' struct_literal_list ',' '}' @@ -108,7 +108,7 @@ _(expr_value) | '(' expr ',' expr_list ')' | '[' expr_list opt_comma ']' | '[' expr ';' expr ']' - | MACRO tt_paren { bnf_trace("Expr macro invocation"); } - | '|' closure_arg_list '|' expr + | MACRO tt_paren { bnf_trace(context, "Expr macro invocation"); } + | '|' closure_arg_list '|' closure_ret expr | DOUBLEPIPE expr ; |