diff options
-rw-r--r-- | bnf/Makefile | 31 | ||||
-rw-r--r-- | bnf/ast_types.hpp | 205 | ||||
-rw-r--r-- | bnf/lex.hpp | 33 | ||||
-rw-r--r-- | bnf/main.cpp | 105 | ||||
-rw-r--r-- | bnf/rust.lex | 89 | ||||
-rw-r--r-- | bnf/rust.y | 149 | ||||
-rw-r--r-- | bnf/rust_tts.y.h | 17 |
7 files changed, 496 insertions, 133 deletions
diff --git a/bnf/Makefile b/bnf/Makefile index 175f6b9e..e85e5fa4 100644 --- a/bnf/Makefile +++ b/bnf/Makefile @@ -1,27 +1,36 @@ .SUFFIXES: -all: test.bin -TSTFILES := ../samples/1.rs -TSTFILES := $(addprefix ../../rust_os/libcore/, lib.rs str/mod.rs str/pattern.rs borrow.rs any.rs array.rs result.rs) +OBJS := main.o rust.tab.o rust.lex.o -test: test.bin $(TSTFILES) - $(foreach f,$(TSTFILES), ./test.bin "$f" &&) true +#TSTFILES := ../samples/1.rs +TSTFILES := ../../rust_os/rustc_src/libcore/lib.rs +#TSTFILES := $(addprefix ../../rust_os/libcore/, lib.rs str/mod.rs str/pattern.rs borrow.rs any.rs array.rs result.rs) + + + +all: test.bin -OBJS := rust.tab.o rust.lex.o +test: test.bin $(TSTFILES) + $(foreach f,$(TSTFILES), $(DBG) ./test.bin "$f" &&) true test.bin: $(OBJS) g++ -std=c++11 $(OBJS) -o $@ -%.o: %.cpp +%.o: %.cpp ast_types.hpp g++ -x c++ -std=c++11 $< -c -o $@ -I . -%.o: .gen/%.cpp +%.o: .gen/%.cpp ast_types.hpp g++ -x c++ -std=c++11 $< -c -o $@ -I . .gen/rust.tab.cpp: .gen/.rust.y @mkdir -p $(dir $@) - bison -o $@ $< -d --verbose + @echo [BISON] $@ + @bison -o $@ $< -d --verbose +# HACK: Bison emits duplicate entries in the union, remove those + @mv $(@:%.cpp=%.hpp) $(@:%.cpp=%.hpp.OLD) + @awk '{ if($$0 ~ /yacc.c:1909/) { ignore = 1; print $$0; } else if( ignore == 1 ) { trigger = $$0; ignore = 2; } else if( ignore == 2 ) { if($$0 == trigger) { ignore = 0 } } if( ignore > 0 ) { } else { print $$0; } }' < ${@:%.cpp=%.hpp.OLD} > $(@:%.cpp=%.hpp) +.gen/rust.tab.hpp: .gen/rust.tab.cpp .gen/.rust.y: Makefile rust.y rust_expr.y.h rust_tts.y.h @mkdir -p $(dir $@) @@ -33,5 +42,7 @@ test.bin: $(OBJS) .gen/rust.lex.cpp: rust.lex @mkdir -p $(dir $@) flex -o $@ $< - + + +main.cpp: .gen/rust.tab.hpp diff --git a/bnf/ast_types.hpp b/bnf/ast_types.hpp index 5ed473f7..09896642 100644 --- a/bnf/ast_types.hpp +++ b/bnf/ast_types.hpp @@ -3,6 +3,7 @@ #include <vector> #include <memory> #include <utility> +#include <cassert> template<typename T> T consume(T* ptr) { @@ -19,6 +20,21 @@ template<typename T> return ::std::unique_ptr<T>(new T(::std::move(ptr))); } + +class Path +{ +public: + struct TagSelf {}; + Path(TagSelf) + {} + struct TagSuper {}; + Path(TagSuper) + {} + struct TagAbs {}; + Path(TagAbs) + {} +}; + class MetaItem; typedef ::std::vector<MetaItem> MetaItems; @@ -27,6 +43,7 @@ class MetaItem ::std::string m_key; ::std::string m_value; MetaItems m_sub_items; + // TODO: How to represent `#[attr()]` (i.e. empty paren set) as distinct from `#[attr=""]` and `#[attr]` public: MetaItem(::std::string key): m_key(key) @@ -39,13 +56,42 @@ public: m_key(key), m_sub_items(sub_items) {} + + const ::std::string& key() const { return m_key; } + const ::std::string& string() const { assert(m_sub_items.size() == 0); return m_value; } }; -class Attr +class AttrList { + ::std::vector<MetaItem> m_ents; public: - Attr(MetaItems items); + bool has(const char* name) const { + return get_first_ptr(name) != nullptr; + } + bool has(const ::std::string& name) const { + return this->has(name.c_str()); + } + + const MetaItem* get_first_ptr(const char* name) const { + for(const auto& e : m_ents) { + if( e.key() == name) + return &e; + } + return nullptr; + } + const MetaItem& get_first(const char* name) const { + auto p = get_first_ptr(name); + assert(p != 0); + return *p; + } + + void push_back(MetaItem a) { + m_ents.push_back( ::std::move(a) ); + } + void append(AttrList other) { + for(auto& e : other.m_ents) + m_ents.push_back( ::std::move(e) ); + } }; -typedef ::std::vector<Attr> AttrList; class TokenTree; @@ -53,19 +99,45 @@ typedef ::std::vector<TokenTree> TokenTreeList; class TokenTree { + int m_tok; + TokenTreeList m_subtts; public: - TokenTree(TokenTreeList tts); - TokenTree(int tok); + TokenTree(TokenTreeList tts): + m_tok(0), + m_subtts(tts) + {} + TokenTree(int tok): + m_tok(tok) + {} }; class Item { + bool m_is_pub; + AttrList m_attrs; public: - void set_pub(); - void add_attrs(AttrList); + Item(): + m_is_pub(false) + {} + Item(AttrList attrs): + m_attrs(attrs) + {} + virtual ~Item() { + } + + void set_pub() { + m_is_pub = true; + } + void add_attrs(AttrList a) { + m_attrs.append( ::std::move(a) ); + } + + const AttrList& attrs() const { return m_attrs; } }; +typedef ::std::vector< ::std::unique_ptr<Item> > ItemList; + class Global: public Item { @@ -73,19 +145,128 @@ class Global: class Module: public Item { + bool m_is_extern; + ::std::string m_name; + ItemList m_items; public: - Module(::std::string name); - Module(AttrList attrs, ::std::vector< ::std::unique_ptr<Item> > items); + Module(::std::string name): + m_is_extern(true), + m_name(name) + {} + Module(AttrList attrs, ::std::vector< ::std::unique_ptr<Item> > items): + Item(attrs), + m_is_extern(false), + m_items( ::std::move(items) ) + {} + + bool is_external() const { return m_is_extern; } + const ::std::string& name() const { return m_name; } + + void set_name(::std::string name) { + assert(m_name == ""); + m_name = name; + } - void set_name(::std::string name); + ItemList& items() { + return m_items; + } }; class Macro: public Item { + ::std::string m_name; + ::std::string m_ident; + TokenTree m_args; public: - Macro(::std::string name, TokenTree contents); - Macro(::std::string name, ::std::string ident, TokenTree contents); + Macro(::std::string name, TokenTree contents): + m_name(name), + m_ident(), + m_args(contents) + {} + Macro(::std::string name, ::std::string ident, TokenTree contents): + m_name(name), + m_ident(ident), + m_args(contents) + {} }; +class UseItem +{ + ::std::string m_name; +public: + struct TagSelf {}; + UseItem(TagSelf): + m_name() + {} + UseItem(::std::string name): + m_name(name) + {} +}; +class UseItems +{ + ::std::string m_alias; + ::std::vector<UseItem> m_items; +public: + UseItems(): + m_alias() + {} + struct TagWildcard {}; + UseItems(TagWildcard): + m_alias("*") + {} + struct TagRename {}; + UseItems(TagRename, ::std::string name): + m_alias(name) + {} + UseItems(::std::vector<UseItem> items): + m_alias(), + m_items(items) + {} +}; +class UseSet: + public Item +{ +public: + UseSet() + {} + UseSet(Path base, UseItems items) + {} +}; + + +class Enum: + public Item +{ +}; +class Struct: + public Item +{ +}; +class Trait: + public Item +{ +}; + +class ExternBlock: + public Item +{ + ::std::string m_abi; + ItemList m_items; +public: + ExternBlock(::std::string abi, ItemList items): + m_abi( abi ), + m_items( ::std::move(items) ) + {} +}; + +class Impl: + public Item +{ +}; + +class Fn: + public Item +{ +}; diff --git a/bnf/lex.hpp b/bnf/lex.hpp new file mode 100644 index 00000000..30d8a2a9 --- /dev/null +++ b/bnf/lex.hpp @@ -0,0 +1,33 @@ +#pragma once + +#include "ast_types.hpp" + +struct ParserContext +{ + ::std::string filename; + ::std::string base_path; + + ::std::unique_ptr<Module> output_module; + + // semi-evil hack used to break '>>' apart into '>' '>' + int next_token; + + + ParserContext(::std::string filename): + filename(filename), + output_module(), + next_token(0) + {} + + void pushback(int tok) { + assert(next_token == 0); + next_token = tok; + } +}; +#include ".gen/rust.tab.hpp" + +extern int yylineno; +extern int yylex(YYSTYPE* lvalp, ParserContext& context); +extern void yyerror(ParserContext& context, const char *s); +extern int yydebug; + diff --git a/bnf/main.cpp b/bnf/main.cpp new file mode 100644 index 00000000..e2c4b3b4 --- /dev/null +++ b/bnf/main.cpp @@ -0,0 +1,105 @@ +#include <stdio.h> +#include <string.h> +#include "lex.hpp" + +extern FILE* yyin; + +::std::string get_dir_path(const ::std::string& input) { + auto pos = input.rfind("/"); + if( pos == ::std::string::npos) { + 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"); + if( !yyin ) { + fprintf(stderr, "ERROR: Unable to open '%s': '%s'\n", argv[1], strerror(errno)); + return 1; + } + } + yylineno = 1; + yydebug = (getenv("BNFDEBUG") != NULL); + + ParserContext context(base_filename); + if( context.filename != "-" ) { + context.base_path = get_dir_path(context.filename); + } + + int rv = yyparse(context); + fclose(yyin); + if( rv != 0 ) { + return rv; + } + + assert( context.output_module.get() ); + auto& mod = *context.output_module; + printf("output module = %p\n", &mod); + + for(auto& item : mod.items()) { + Module* opt_submod = dynamic_cast<Module*>(item.get()); + if( !opt_submod ) continue; + Module& submod = *opt_submod; + printf("- Module %s\n", submod.name().c_str()); + + 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; + } + 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 { + fclose(yyin); + } + } + assert(filename.size() > 0); + yyin = fopen( filename.c_str(), "r" ); + if( !yyin ) { + printf("> '%s' not found\n", filename.c_str()); + return 1; + } + + ParserContext new_context(filename); + int rv = yyparse(new_context); + fclose(yyin); + if( rv != 0 ) { + return rv; + } + submod = ::std::move( *new_context.output_module ); + } + + return 0; +} +void yyerror(ParserContext& context, const char *s) { + fprintf(stderr, "\x1b[31mERROR: %s:%d: yyerror(%s)\x1b[0m\n", context.filename.c_str(), yylineno, s); + exit(1); +} diff --git a/bnf/rust.lex b/bnf/rust.lex index a0dce8fa..6155b4c4 100644 --- a/bnf/rust.lex +++ b/bnf/rust.lex @@ -1,9 +1,7 @@ %{ #include "ast_types.hpp" -#include "rust.tab.hpp" +#include "lex.hpp" #include <stdio.h> -void yyerror(const char *s); -extern int yydebug; %} %option yylineno @@ -12,24 +10,23 @@ extern int yydebug; %{ int rustbnf_forcetoken = 0; //#define YY_DECL yy::parser::symbol_type yylex_inner() -#define YY_DECL int yylex_inner() +#define YY_DECL int yylex_inner(YYSTYPE* lvalp, ParserContext& context) YY_DECL; // Wrap the real yylex with one that can yeild a pushbacked token -int yylex() { - if(rustbnf_forcetoken>0) { - int rv = rustbnf_forcetoken; - rustbnf_forcetoken = 0; +int yylex(YYSTYPE* lvalp, ParserContext& context) { + if(context.next_token > 0) { + int rv = context.next_token; + context.next_token = 0; return rv; } else { - return yylex_inner(); + return yylex_inner(lvalp, context); } } void handle_block_comment(); - -const char *gsCurrentFilename = "-"; +::std::string parse_escaped_string(const char* s); %} @@ -128,43 +125,57 @@ ident_c [a-zA-Z_] if(*yytext == '_' && yytext[1] == 0) return '_'; else { - yylval.IDENT = new ::std::string( yytext ); + lvalp->IDENT = new ::std::string( yytext ); return IDENT; } } -{ident_c}({ident_c}|[0-9])*"!" { yylval.MACRO = new ::std::string(yytext); return MACRO; } -'{ident_c}{ident_c}* { yylval.LIFETIME = new ::std::string(yytext); return LIFETIME; } -[0-9]{dec_digit}*"."{dec_digit}+ { yylval.FLOAT = strtod(yytext, NULL); return FLOAT; } -[0-9]{dec_digit}* { yylval.INTEGER = strtoull(yytext, NULL, 0); return INTEGER; } -0x[0-9a-fA-F_]+ { yylval.INTEGER = strtoull(yytext, NULL, 0); return INTEGER; } -0b[01_]+ { yylval.INTEGER = strtoull(yytext, NULL, 0); return INTEGER; } +[0-9]{dec_digit}*"."{dec_digit}+(e[+\-]?{dec_digit}+)?(f32|f64)? { lvalp->FLOAT = strtod(yytext, NULL); return FLOAT; } +[0-9]{dec_digit}* { lvalp->INTEGER = strtoull(yytext, NULL, 0); return INTEGER; } +0x[0-9a-fA-F_]+ { lvalp->INTEGER = strtoull(yytext, NULL, 0); return INTEGER; } +0b[01_]+ { lvalp->INTEGER = strtoull(yytext, NULL, 0); return INTEGER; } +{ident_c}({ident_c}|[0-9])*"!" { lvalp->MACRO = new ::std::string(yytext, 0, strlen(yytext)-1); return MACRO; } +'{ident_c}{ident_c}* { lvalp->LIFETIME = new ::std::string(yytext, 1); return LIFETIME; } -b?'(.|\\['rn])' { yylval.CHARLIT = yytext[0]; return CHARLIT; } -\"([^"])*\" { yylval.STRING = new ::std::string(yytext); } +b?'(.|\\['rn])' { lvalp->CHARLIT = yytext[0]; return CHARLIT; } +\"([^"])*\" { lvalp->STRING = new ::std::string( parse_escaped_string(yytext) ); return STRING; } -. { fprintf(stderr, "\x1b[31m" "ERROR: %s:%d: Invalid character '%c'\x1b[0m\n", gsCurrentFilename, yylineno, *yytext); exit(1); } +. { fprintf(stderr, "\x1b[31m" "ERROR: %s:%d: Invalid character '%c'\x1b[0m\n", context.filename.c_str(), yylineno, *yytext); exit(1); } %% -int main(int argc, char *argv[]) { - if(argc < 2 || strcmp(argv[1], "-") == 0) { - yyin = stdin; - } - else { - gsCurrentFilename = argv[1]; - yyin = fopen(argv[1], "r"); - if( !yyin ) { - fprintf(stderr, "ERROR: Unable to open '%s': '%s'\n", argv[1], strerror(errno)); - return 1; + +::std::string parse_escaped_string(const char* s) { + assert(*s++ == '"'); + + ::std::string rv; + + for( ; *s != '\0'; s ++ ) + { + if( *s == '\\' ) + { + s ++; + switch(*s) + { + case 'n': rv += '\n'; break; + case 'r': rv += '\r'; break; + case '\n': break; + default: + fprintf(stderr, "Unknown escape code '\\%c' in string\n", *s); + exit(1); + } + } + else if( *s == '"') { + break ; + } + else { + rv += *s; } } - yylineno = 1; - yydebug = (getenv("BNFDEBUG") != NULL); - yyparse(); - return 0; -} -void yyerror(const char *s) { - fprintf(stderr, "\x1b[31mERROR: %s:%d: yyerror(%s)\x1b[0m\n", gsCurrentFilename, yylineno, s); - exit(1); + if( *s == '\0' ) { + // wut? + } + assert(*s++ == '"'); + assert(*s == '\0'); + return rv; } // Thanks stackoverflow: http://www.lysator.liu.se/c/ANSI-C-grammar-l.html @@ -1,4 +1,3 @@ -%define api.value.type union %{ #include <stdio.h> #include <stdarg.h> @@ -6,17 +5,19 @@ #include <string> #include <vector> #include <memory> +#include "lex.hpp" #include "ast_types.hpp" -extern int yylineno; -extern int yylex(); -extern void yyerror(const char *s); - -// semi-evil hack used to break '>>' apart into '>' '>' -extern int rustbnf_forcetoken; +#define YYPARSE_PARAM parser_context +#define YYLEX_PARAM parser_context %} +%define api.value.type union +%define api.pure full +%parse-param {ParserContext& context} +%lex-param {*context} + %token <::std::string*> IDENT LIFETIME STRING MACRO %token <int> INTEGER CHARLIT %token <double> FLOAT @@ -34,7 +35,6 @@ extern int rustbnf_forcetoken; %token RWD_match RWD_if RWD_while RWD_loop RWD_for RWD_else %token RWD_return RWD_break RWD_continue %token RWD_extern -%start module_root %type <Module*> module_root %type <int> tt_tok @@ -43,18 +43,34 @@ extern int rustbnf_forcetoken; %type <bool> opt_pub opt_mut %type <::std::string*> opt_lifetime %type <AttrList*> super_attrs attrs -%type <Attr*> super_attr attr -%type < ::std::vector< ::std::unique_ptr<Item> >* > module_body -%type <Item*> item vis_item unsafe_item unsafe_vis_item impl_def extern_block use_def -%type <Module*> module_def -%type <Global*> static_def const_def +%type <MetaItem*> super_attr attr +%type <ItemList*> module_body extern_items %type <MetaItem*> meta_item %type <MetaItems*> meta_items +%type <Item*> item vis_item unsafe_item unsafe_vis_item +%type <UseSet*> use_def +%type <Module*> module_def +%type <Global*> static_def const_def +%type <Struct*> struct_def +%type <Enum*> enum_def +%type <Trait*> trait_def +%type <Fn*> fn_def fn_def_hdr fn_def_hdr_PROTO +%type <ExternBlock*> extern_block +%type <Impl*> impl_def + +%type <UseItems*> use_def_tail +%type < ::std::vector<UseItem>* > use_picks +%type <UseItem*> path_item + +%type <::std::string*> extern_abi +%type <Item*> extern_item + %debug %error-verbose %{ +// TODO: Replace this with a C++-safe printf /*static inline*/ void bnf_trace(const char* fmt, ...) { fprintf(stderr, "\x1b[32m""TRACE: "); va_list args; @@ -63,25 +79,16 @@ extern int rustbnf_forcetoken; 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 char* fmt, const ::std::string& s) { - bnf_trace(fmt, s.c_str()); + bnf_trace(fmt, s.c_str(), '0'); } -//#define YYPRINT(f,t,v) yyprint(f,t,v) -//static void yyprint(FILE *outstream, int type, const YYSTYPE value) -//{ -// switch(type) -// { -// case IDENT: fprintf(outstream, "%s", value.text); break; -// case MACRO: fprintf(outstream, "%s!", value.text); break; -// case STRING: fprintf(outstream, "\"%s\"", value.text); break; -// case LIFETIME: fprintf(outstream, "'%s", value.text); break; -// default: -// break; -// } -//} %} +%start parse_root %% /* @@ -89,6 +96,8 @@ extern int rustbnf_forcetoken; Root ========================== */ +parse_root: module_root { context.output_module = box_raw($1); } + module_root: super_attrs module_body { $$ = new Module(consume($1), consume($2)); }; tt_list @@ -129,15 +138,15 @@ attrs ; super_attr - : HASHBANG /*'#' '!'*/ '[' meta_items ']' { $$ = new Attr(consume($3)); } - | SUPER_DOC_COMMENT { $$ = new Attr(MetaItems( { MetaItem("doc", consume($1)) } )); } + : HASHBANG /*'#' '!'*/ '[' meta_item ']' { $$ = $3; } + | SUPER_DOC_COMMENT { $$ = new MetaItem("doc", consume($1)); } ; attr - : '#' '[' meta_items ']' { $$ = new Attr( consume($3) ); } - | DOC_COMMENT { $$ = new Attr(MetaItems( { MetaItem("doc", consume($1)) } )); } + : '#' '[' meta_item ']' { $$ = $3; } + | DOC_COMMENT { $$ = new MetaItem("doc", consume($1)); } ; meta_items - : meta_item { $$ = new MetaItems({ consume($1) }); } + : meta_item { $$ = new MetaItems(); $$->push_back( consume($1) ); } | meta_items ',' meta_item { $$ = $1; $$->push_back( consume($3) ); } ; meta_item @@ -170,24 +179,29 @@ vis_item | RWD_use use_def { $$ = $2; } | RWD_static static_def { $$ = $2; } | RWD_const const_def { $$ = $2; } - | RWD_struct struct_def { $$ = nullptr; } - | RWD_enum enum_def { $$ = nullptr; } + | RWD_struct struct_def { $$ = $2; } + | RWD_enum enum_def { $$ = $2; } | unsafe_vis_item ; /* Possibily unsafe visibility item */ unsafe_vis_item - : fn_qualifiers RWD_fn fn_def { $$ = nullptr; } - | RWD_trait trait_def { $$ = nullptr; } + : fn_qualifiers RWD_fn fn_def { $$ = $3; } + | RWD_trait trait_def { $$ = $2; } ; unsafe_item : unsafe_vis_item | RWD_impl impl_def { $$ = $2; } ; -extern_block: extern_abi '{' extern_items '}' { $$ = nullptr; /*new ExternBlock($1, $3);*/ }; -extern_abi: | STRING; -extern_items: | extern_items extern_item; -extern_item: opt_pub RWD_fn fn_def_hdr ';'; +extern_block: extern_abi '{' extern_items '}' { $$ = new ExternBlock( consume($1), consume($3) ); }; +extern_abi: { $$ = new ::std::string("C"); } | STRING; +extern_items + : { $$ = new ItemList(); } + | extern_items extern_item { $$ = $1; $$->push_back( box_raw($2) ); } + ; +extern_item + : opt_pub RWD_fn fn_def_hdr ';' { $$ = $3; if($1) $$->set_pub(); } + ; module_def : IDENT '{' module_root '}' { $3->set_name( consume($1) ); $$ = new Module(consume($3)); } @@ -196,9 +210,9 @@ module_def /* --- 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 { bnf_trace("function '%s'", $1); }; +fn_def_hdr: IDENT generic_def '(' fn_def_args ')' 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 { 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("function '%s'", *$1); }; fn_def_ret : /* -> () */ @@ -238,42 +252,45 @@ fn_qualifiers /* --- Use --- */ use_def - : RWD_self use_def_tail { $$ = nullptr; } - | RWD_self DOUBLECOLON use_path use_def_tail { $$ = nullptr; } - | RWD_super use_def_tail { $$ = nullptr; } - | RWD_super DOUBLECOLON use_path use_def_tail { $$ = nullptr; } - | DOUBLECOLON use_path use_def_tail { $$ = nullptr; } - | use_path use_def_tail { $$ = nullptr; } - | '{' use_picks '}' ';' { $$ = nullptr; } + : RWD_self use_def_tail { $$ = new UseSet( Path(Path::TagSelf()), consume($2) ); } + | RWD_self DOUBLECOLON use_path use_def_tail { $$ = new UseSet(/* TODO */); } + | RWD_super use_def_tail { $$ = new UseSet( Path(Path::TagSuper()), consume($2) ); } + | RWD_super DOUBLECOLON use_path use_def_tail { $$ = new UseSet(/* TODO */); } + | 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) ); } ; use_def_tail - : RWD_as IDENT ';' - | DOUBLECOLON '*' ';' - | DOUBLECOLON '{' use_picks '}' ';' - | ';' + : RWD_as IDENT ';' { $$ = new UseItems(UseItems::TagRename(), consume($2) ); } + | DOUBLECOLON '*' ';' { $$ = new UseItems(UseItems::TagWildcard()); } + | DOUBLECOLON '{' use_picks '}' ';' { $$ = new UseItems( consume($3) ); } + | ';' { $$ = new UseItems(); } /* | RWD_use error ';' */ ; use_picks - : use_picks ',' path_item - | path_item + : use_picks ',' path_item { $$ = $1; $$->push_back( consume($3) ); } + | path_item { $$ = new ::std::vector<UseItem>(); $$->push_back( consume($1) ); } + ; +path_item + : IDENT { $$ = new UseItem( consume($1) ); } + | RWD_self { $$ = new UseItem(UseItem::TagSelf()); } ; -path_item: IDENT | RWD_self; /* --- Static/Const --- */ opt_mut: { $$ = false; } | RWD_mut { $$ = true; }; -static_def: opt_mut IDENT ':' type '=' const_value { $$ = nullptr; }; -const_def: IDENT ':' type '=' const_value { $$ = nullptr; }; +static_def: opt_mut IDENT ':' type '=' const_value { $$ = new Global(); }; +const_def: IDENT ':' type '=' const_value { $$ = new Global(); }; const_value : expr ';' - | error ';' { yyerror("Syntax error in constant expression"); } + | error ';' { yyerror(context, "Syntax error in constant expression"); } ; /* --- Struct --- */ struct_def - : IDENT generic_def where_clause ';' { bnf_trace("unit-like struct"); } - | IDENT generic_def '(' tuple_struct_def_items opt_comma ')' where_clause ';' { bnf_trace("tuple struct"); } - | IDENT generic_def where_clause '{' struct_def_items opt_comma '}' { bnf_trace("normal struct"); } + : 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"); } ; tuple_struct_def_items @@ -289,7 +306,7 @@ struct_def_items struct_def_item: attrs opt_pub IDENT ':' type; /* --- Enum --- */ -enum_def: IDENT generic_def where_clause '{' enum_variants '}'; +enum_def: IDENT generic_def where_clause '{' enum_variants '}' { $$ = new Enum(); }; enum_variants: | enum_variant_list | enum_variant_list ','; enum_variant_list: enum_variant | enum_variant_list ',' enum_variant; enum_variant: attrs enum_variant_; @@ -300,7 +317,7 @@ enum_variant_ ; /* --- Trait --- */ -trait_def: IDENT generic_def trait_bounds '{' trait_items '}'; +trait_def: IDENT generic_def trait_bounds '{' trait_items '}' { $$ = new Trait(); }; trait_bounds: ':' trait_bound_list | ; trait_bound_list: trait_bound_list '+' bound | bound; @@ -313,7 +330,7 @@ trait_item ; /* --- Impl --- */ -impl_def: impl_def_line '{' impl_items '}' { $$ = nullptr; }; +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 DOUBLEDOT where_clause { bnf_trace("wildcard impl"); } @@ -394,7 +411,7 @@ type_path_segs type_path_seg : IDENT | IDENT '<' type_exprs '>' - | IDENT '<' type_exprs DOUBLEGT { bnf_trace("Double-gt terminated type expr"); rustbnf_forcetoken = '>'; } + | IDENT '<' type_exprs DOUBLEGT { bnf_trace("Double-gt terminated type expr"); context.pushback('>'); } ; type_exprs: type_exprs ',' type_arg | type_arg; type_arg: type | LIFETIME | IDENT '=' type; diff --git a/bnf/rust_tts.y.h b/bnf/rust_tts.y.h index c752694f..4a590f2b 100644 --- a/bnf/rust_tts.y.h +++ b/bnf/rust_tts.y.h @@ -1,13 +1,18 @@ #define _C(v) v { $$ = v; } #define _T(v) v { $$ = v; } tt_tok - : _T(IDENT) | _T(STRING) | _T(CHARLIT) | _T(LIFETIME) | _T(INTEGER) | _T(MACRO) - | _C('+') | _C('*') | _C('/') | _C(',') | _C(';') - | _T(RWD_self) | _T(RWD_super) | _T(RWD_mut) | _T(RWD_ref) | _T(RWD_let) | _T(RWD_where) - | _T(RWD_for ) | _T(RWD_while) | _T(RWD_loop) | _T(RWD_if) | _T(RWD_else) | _T(RWD_match) | _T(RWD_return) - | _T(RWD_impl) | _T(RWD_pub ) | _T(RWD_struct) | _T(RWD_enum) | _T(RWD_fn) | _T(RWD_type) | _T(RWD_static) | _T(RWD_const) - | _C('!') | _T(EXCLAMEQUAL) + : _T(IDENT) | _T(STRING) | _T(CHARLIT) | _T(LIFETIME) | _T(INTEGER) | _T(MACRO) | _T(FLOAT) + | _C(',') | _C(';') | _C('_') + | _T(RWD_self) | _T(RWD_super) | _T(RWD_mut) | _T(RWD_ref) | _T(RWD_let) | _T(RWD_where) | _T(RWD_pub) | _T(RWD_in) | _T(RWD_as) + | _T(RWD_for ) | _T(RWD_while) | _T(RWD_loop) | _T(RWD_if) | _T(RWD_else) | _T(RWD_match) + | _T(RWD_return) | _T(RWD_continue) | _T(RWD_break) + | _T(RWD_impl) | _T(RWD_struct) | _T(RWD_enum) | _T(RWD_fn) | _T(RWD_type) | _T(RWD_static) | _T(RWD_const) | _T(RWD_trait) | _T(RWD_use) + | _T(RWD_extern) | _T(RWD_unsafe) + | _C('/') | _T(SLASHEQUAL) + | _C('*') | _T(STAREQUAL) + | _C('+') | _T(PLUSEQUAL) | _C('-') | _T(THINARROW) + | _C('!') | _T(EXCLAMEQUAL) | _C('&') | _T(DOUBLEAMP) | _C(':') | _T(DOUBLECOLON) | _C('|') | _T(DOUBLEPIPE) |