From a9ffe782db9565f6844835e79e0ea38008a211f4 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sun, 23 Aug 2015 11:11:02 +0800 Subject: Cleanup and new syntax --- .lvimrc | 1 + Makefile | 2 +- src/ast/expr.cpp | 35 ----------- src/ast/expr.hpp | 50 +--------------- src/convert/resolve.cpp | 2 + src/dump_as_rust.cpp | 17 ------ src/main.cpp | 94 +++++++++++++++++++---------- src/parse/eTokenType.enum.h | 2 +- src/parse/expr.cpp | 39 +++++++++--- src/parse/lex.cpp | 43 ++++++++++---- src/parse/root.cpp | 142 ++++++++++++++++++++++++++++++++------------ src/synexts/lang_item.cpp | 2 + 12 files changed, 234 insertions(+), 195 deletions(-) diff --git a/.lvimrc b/.lvimrc index 069917a3..c3c698fb 100644 --- a/.lvimrc +++ b/.lvimrc @@ -1,2 +1,3 @@ set expandtab set sts=4 ts=4 sw=4 +set list diff --git a/Makefile b/Makefile index 475f42dd..dc8110d7 100644 --- a/Makefile +++ b/Makefile @@ -38,7 +38,7 @@ output/%.ast: samples/%.rs $(BIN) @mkdir -p output/ $(DBG) $(BIN) $< --emit ast -o $@ 2>&1 | tee $@_dbg.txt | tail -n 40 ; test $${PIPESTATUS[0]} -eq 0 -RUSTCSRC := ../../../Source/rust/rustc-nightly/ +RUSTCSRC := ~/Source/rust/rustc-nightly/ output/core.ast: $(RUSTCSRC)src/libcore/lib.rs $(BIN) @mkdir -p output/ $(DBG) $(BIN) $< --emit ast -o $@ 2>&1 | tee $@_dbg.txt | tail -n 40 ; test $${PIPESTATUS[0]} -eq 0 diff --git a/src/ast/expr.cpp b/src/ast/expr.cpp index 6adec104..f42870f8 100644 --- a/src/ast/expr.cpp +++ b/src/ast/expr.cpp @@ -54,9 +54,6 @@ SERIALISE_TYPE(Expr::, "Expr", { _(ExprNode_Block) else _(ExprNode_Macro) else _(ExprNode_Flow) - else _(ExprNode_Const) - else _(ExprNode_Import) - else _(ExprNode_Extern) else _(ExprNode_LetBinding) else _(ExprNode_Assign) else _(ExprNode_CallPath) @@ -146,32 +143,6 @@ NODE(ExprNode_Flow, { os << " " << *m_value; }) -NODE(ExprNode_Const, { - s.item(m_name); - s.item(m_type); - s.item(m_value); -},{ - os << "const " << m_name << ": " << m_type << " = " << *m_value; -}) - - -ExprNode_Extern::ExprNode_Extern() -{} -ExprNode_Extern::ExprNode_Extern(ExprNode_Extern::imports_t imports): - m_imports( ::std::move(imports) ) -{} - -NODE(ExprNode_Import, { - s.item(m_imports); -},{ - os << "/* todo: use /*"; -}) - -NODE(ExprNode_Extern, { - s.item(m_imports); -},{ - os << "/* todo: export /*"; -}) NODE(ExprNode_LetBinding, { s.item(m_pat); @@ -533,12 +504,6 @@ NV(ExprNode_Flow, { visit(node.m_value); }) -NV(ExprNode_Const, -{ - visit(node.m_value); -}) -NV(ExprNode_Import, {}) -NV(ExprNode_Extern, {}) NV(ExprNode_LetBinding, { // TODO: Handle recurse into Let pattern diff --git a/src/ast/expr.hpp b/src/ast/expr.hpp index 45f6e3c9..bbfa37ad 100644 --- a/src/ast/expr.hpp +++ b/src/ast/expr.hpp @@ -81,7 +81,7 @@ struct ExprNode_Macro: NODE_METHODS(); }; -// Return a value +// Break/Continue/Return struct ExprNode_Flow: public ExprNode { @@ -103,48 +103,6 @@ struct ExprNode_Flow: NODE_METHODS(); }; -struct ExprNode_Const: - public ExprNode -{ - ::std::string m_name; - TypeRef m_type; - unique_ptr m_value; - - ExprNode_Const() {} - ExprNode_Const(::std::string name, TypeRef type, unique_ptr&& value): - m_name( move(name) ), - m_type( move(type) ), - m_value( move(value) ) - { - } - - NODE_METHODS(); -}; -struct ExprNode_Import: - public ExprNode -{ - typedef ::std::vector< ::std::pair< ::std::string, AST::Path> > imports_t; - imports_t m_imports; - - ExprNode_Import() {} - ExprNode_Import(imports_t imports): - m_imports( ::std::move(imports) ) - {} - - NODE_METHODS(); -}; -struct ExprNode_Extern: - public ExprNode -{ - typedef ::std::vector< ::std::pair< ::std::string, AST::Function> > imports_t; - imports_t m_imports; - - ExprNode_Extern(); - ExprNode_Extern(imports_t imports); - // - Non-local because AST::Function - - NODE_METHODS(); -}; struct ExprNode_LetBinding: public ExprNode { @@ -616,9 +574,6 @@ public: NT(ExprNode_Block); NT(ExprNode_Macro); NT(ExprNode_Flow); - NT(ExprNode_Const); - NT(ExprNode_Import); - NT(ExprNode_Extern); NT(ExprNode_LetBinding); NT(ExprNode_Assign); NT(ExprNode_CallPath); @@ -661,9 +616,6 @@ public: NT(ExprNode_Block); NT(ExprNode_Macro); NT(ExprNode_Flow); - NT(ExprNode_Const); - NT(ExprNode_Import); - NT(ExprNode_Extern); NT(ExprNode_LetBinding); NT(ExprNode_Assign); NT(ExprNode_CallPath); diff --git a/src/convert/resolve.cpp b/src/convert/resolve.cpp index f3ba701f..0891a748 100644 --- a/src/convert/resolve.cpp +++ b/src/convert/resolve.cpp @@ -244,9 +244,11 @@ public: m_res.start_scope(); for( auto& param : node.m_args ) { + DEBUG("- ExprNode_Closure: pat=" << param.first << ", ty=" << param.second); m_res.handle_type(param.second); m_res.handle_pattern(param.first, param.second); } + DEBUG("- ExprNode_Closure: rt=" << node.m_return); m_res.handle_type(node.m_return); AST::NodeVisitor::visit(node.m_code); m_res.end_scope(); diff --git a/src/dump_as_rust.cpp b/src/dump_as_rust.cpp index d760f4cd..1c1ae2a0 100644 --- a/src/dump_as_rust.cpp +++ b/src/dump_as_rust.cpp @@ -72,23 +72,6 @@ public: } AST::NodeVisitor::visit(n.m_value); } - virtual void visit(AST::ExprNode_Const& n) override { - m_expr_root = false; - m_os << "const " << n.m_name << ": "; - print_type(n.m_type); - m_os << " = "; - AST::NodeVisitor::visit(n.m_value); - } - virtual void visit(AST::ExprNode_Import& n) override { - m_expr_root = false; - for( const auto& item : n.m_imports ) - m_os << "use " << item.second << " as " << item.first << ";\n" << indent(); - } - virtual void visit(AST::ExprNode_Extern& n) override { - m_expr_root = false; - for( const auto& item : n.m_imports ) - m_os << "extern \"\" fn " << item.first /*<< item.second*/ << ";\n" << indent(); - } virtual void visit(AST::ExprNode_LetBinding& n) override { m_expr_root = false; m_os << "let "; diff --git a/src/main.cpp b/src/main.cpp index 8f39b78e..710b7e89 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -30,67 +30,99 @@ bool debug_enabled() struct ProgramParams { - static const unsigned int EMIT_C = 0x1; - static const unsigned int EMIT_AST = 0x2; + static const unsigned int EMIT_C = 0x1; + static const unsigned int EMIT_AST = 0x2; - const char *infile = NULL; - ::std::string outfile; - const char *crate_path = "."; - unsigned emit_flags = EMIT_C; + const char *infile = NULL; + ::std::string outfile; + const char *crate_path = "."; + unsigned emit_flags = EMIT_C; ProgramParams(int argc, char *argv[]); }; +template +Rv CompilePhase(const char *name, Fcn f) { + g_cur_phase = name; + auto rv = f(); + g_cur_phase = ""; + return rv; +} +template +void CompilePhaseV(const char *name, Fcn f) { + g_cur_phase = name; + f(); + g_cur_phase = ""; +} + /// main! int main(int argc, char *argv[]) { AST_InitProvidedModule(); - + ProgramParams params(argc, argv); try { - g_cur_phase = "Parse"; - AST::Crate crate = Parse_Crate(params.infile); + // Parse the crate into AST + AST::Crate crate = CompilePhase("Parse", [&]() { + return Parse_Crate(params.infile); + }); // Iterate all items in the AST, applying syntax extensions - g_cur_phase = "Syn Exts"; - Process_Decorators(crate); - // TODO: - - g_cur_phase = "PostParse"; - crate.post_parse(); + CompilePhaseV("Decorators", [&]() { + Process_Decorators(crate); + }); + + // Run a quick post-parse pass + // TODO: What does this do? + CompilePhaseV("PostParse", [&]() { + crate.post_parse(); + }); - //s << crate; - g_cur_phase = "Temp output"; - Dump_Rust( FMT(params.outfile << ".rs").c_str(), crate ); + // XXX: Dump crate before resolve + CompilePhaseV("Temp output - Parsed", [&]() { + Dump_Rust( FMT(params.outfile << ".rs").c_str(), crate ); + }); // Resolve names to be absolute names (include references to the relevant struct/global/function) - g_cur_phase = "Resolve"; - ResolvePaths(crate); + CompilePhaseV("Resolve", [&]() { + ResolvePaths(crate); + }); - g_cur_phase = "Temp output"; Dump_Rust( FMT(params.outfile << ".rs").c_str(), crate ); + // XXX: Dump crate before typecheck + CompilePhaseV("Temp output - Resolved", [&]() { + Dump_Rust( FMT(params.outfile << ".rs").c_str(), crate ); + }); + // Replace type aliases (`type`) into the actual type + CompilePhaseV("Resolve Type Aliases", [&]() { + // + }); + // Typecheck / type propagate module (type annotations of all values) // - Check all generic conditions (ensure referenced trait is valid) // > Also mark parameter with applicable traits - #if 0 - g_cur_phase = "TypecheckBounds"; - Typecheck_GenericBounds(crate); + CompilePhaseV("TypecheckBounds", [&]() { + //Typecheck_GenericBounds(crate); + }); + // - Check all generic parameters match required conditions - g_cur_phase = "TypecheckParams"; - Typecheck_GenericParams(crate); + CompilePhaseV("TypecheckParams", [&]() { + //Typecheck_GenericParams(crate); + }); // - Typecheck statics and consts // - Typecheck + propagate functions // > Forward pass first - //g_cur_phase = "TypecheckExpr"; - //Typecheck_Expr(crate); - #endif + CompilePhaseV("TypecheckExpr", [&]() { + //Typecheck_Expr(crate); + }); - g_cur_phase = "Output"; - Dump_Rust( FMT(params.outfile << ".rs").c_str(), crate ); + CompilePhaseV("Output", [&]() { + Dump_Rust( FMT(params.outfile << ".rs").c_str(), crate ); + }); if( params.emit_flags == ProgramParams::EMIT_AST ) { diff --git a/src/parse/eTokenType.enum.h b/src/parse/eTokenType.enum.h index 69f00f02..2adfb042 100644 --- a/src/parse/eTokenType.enum.h +++ b/src/parse/eTokenType.enum.h @@ -13,6 +13,7 @@ _(TOK_INTEGER) _(TOK_CHAR) _(TOK_FLOAT) _(TOK_STRING) +_(TOK_BYTESTRING) _(TOK_CATTR_OPEN) _(TOK_ATTR_OPEN) @@ -120,7 +121,6 @@ _(TOK_RWORD_SUPER) _(TOK_RWORD_PROC) _(TOK_RWORD_MOVE) -_(TOK_RWORD_ONCE) _(TOK_RWORD_ABSTRACT) _(TOK_RWORD_FINAL) diff --git a/src/parse/expr.cpp b/src/parse/expr.cpp index a12eb526..15e983f7 100644 --- a/src/parse/expr.cpp +++ b/src/parse/expr.cpp @@ -755,14 +755,8 @@ LEFTASSOC(Parse_Expr9, Parse_Expr10, rv = NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::SUB, ::std::move(rv), next(lex)); break; ) -// 10: Cast +// 10: Times / Divide / Modulo LEFTASSOC(Parse_Expr10, Parse_Expr11, - case TOK_RWORD_AS: - rv = NEWNODE( AST::ExprNode_Cast, ::std::move(rv), Parse_Type(lex) ); - break; -) -// 11: Times / Divide / Modulo -LEFTASSOC(Parse_Expr11, Parse_Expr12, case TOK_STAR: rv = NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::MULTIPLY, ::std::move(rv), next(lex)); break; @@ -773,6 +767,12 @@ LEFTASSOC(Parse_Expr11, Parse_Expr12, rv = NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::MODULO, ::std::move(rv), next(lex)); break; ) +// 11: Cast +LEFTASSOC(Parse_Expr11, Parse_Expr12, + case TOK_RWORD_AS: + rv = NEWNODE( AST::ExprNode_Cast, ::std::move(rv), Parse_Type(lex) ); + break; +) // 12: Unaries ExprNodeP Parse_ExprFC(TokenStream& lex); ExprNodeP Parse_Expr12(TokenStream& lex) @@ -891,7 +891,7 @@ ExprNodeP Parse_ExprVal_StructLiteral(TokenStream& lex, AST::Path path) return NEWNODE( AST::ExprNode_StructLiteral, path, ::std::move(base_val), ::std::move(items) ); } -ExprNodeP Parse_ExprVal_Closure(TokenStream& lex) +ExprNodeP Parse_ExprVal_Closure(TokenStream& lex, bool is_move) { TRACE_FUNCTION; Token tok; @@ -1041,16 +1041,37 @@ ExprNodeP Parse_ExprVal(TokenStream& lex) lex.putback(tok); return NEWNODE( AST::ExprNode_NamedValue, ::std::move(path) ); } + case TOK_RWORD_MOVE: + // TODO: Annotate closure as move + GET_TOK(tok, lex); + if(tok.type() == TOK_PIPE) + return Parse_ExprVal_Closure(lex, true); + else if(tok.type() == TOK_DOUBLE_PIPE) { + lex.putback(Token(TOK_PIPE)); + return Parse_ExprVal_Closure(lex, true); + } + else { + CHECK_TOK(tok, TOK_PIPE); + } case TOK_DOUBLE_PIPE: lex.putback(Token(TOK_PIPE)); case TOK_PIPE: - return Parse_ExprVal_Closure(lex); + return Parse_ExprVal_Closure(lex, false); case TOK_INTEGER: return NEWNODE( AST::ExprNode_Integer, tok.intval(), tok.datatype() ); case TOK_FLOAT: return NEWNODE( AST::ExprNode_Float, tok.floatval(), tok.datatype() ); case TOK_STRING: return NEWNODE( AST::ExprNode_String, tok.str() ); + case TOK_BYTESTRING: { + ::std::vector items; + for(char b: tok.str()) { + items.push_back( NEWNODE( AST::ExprNode_Integer, b, CORETYPE_U8 ) ); + } + return NEWNODE( AST::ExprNode_Array, ::std::move(items) ); + } + // TODO: Correct type here + return NEWNODE( AST::ExprNode_String, tok.str() ); case TOK_RWORD_TRUE: return NEWNODE( AST::ExprNode_Bool, true ); case TOK_RWORD_FALSE: diff --git a/src/parse/lex.cpp b/src/parse/lex.cpp index 419a04d5..cac8f511 100644 --- a/src/parse/lex.cpp +++ b/src/parse/lex.cpp @@ -97,6 +97,8 @@ static const struct { TOKENT("^", TOK_CARET), TOKENT("^=", TOK_CARET_EQUAL), TOKENT("`", TOK_BACKTICK), + // a-z :: Elsewhere + //TOKENT("b\"", DOUBLEQUOTE), TOKENT("{", TOK_BRACE_OPEN), TOKENT("|", TOK_PIPE), @@ -139,7 +141,6 @@ static const struct { TOKENT("move", TOK_RWORD_MOVE), TOKENT("mut", TOK_RWORD_MUT), TOKENT("offsetof",TOK_RWORD_OFFSETOF), - TOKENT("once", TOK_RWORD_ONCE), TOKENT("override",TOK_RWORD_OVERRIDE), TOKENT("priv", TOK_RWORD_PRIV), TOKENT("proc", TOK_RWORD_PROC), @@ -401,6 +402,7 @@ Token Lexer::getTokenInt() return Token(val, num_type); } } + // Symbols else if( issym(ch) ) { ::std::string str; @@ -416,19 +418,34 @@ Token Lexer::getTokenInt() } else { - if( str == "b" && ch == '\'' ) { - // Byte constant - ch = this->getc(); - if( ch == '\\' ) { - uint32_t val = this->parseEscape('\''); - if( this->getc() != '\'' ) - throw ParseError::Generic(*this, "Multi-byte character literal"); - return Token((uint64_t)val, CORETYPE_U8); + if( str == "b" ) + { + if( ch == '\'' ) { + // Byte constant + ch = this->getc(); + if( ch == '\\' ) { + uint32_t val = this->parseEscape('\''); + if( this->getc() != '\'' ) + throw ParseError::Generic(*this, "Multi-byte character literal"); + return Token((uint64_t)val, CORETYPE_U8); + } + else { + if( this->getc() != '\'' ) + throw ParseError::Generic(*this, "Multi-byte character literal"); + return Token((uint64_t)ch, CORETYPE_U8); + } + } + else if( ch == '"') { + ::std::string str; + while( (ch = this->getc()) != '"' ) + { + if( ch == '\\' ) + ch = this->parseEscape('"'); + str.push_back(ch); + } + return Token(TOK_BYTESTRING, str); } else { - if( this->getc() != '\'' ) - throw ParseError::Generic(*this, "Multi-byte character literal"); - return Token((uint64_t)ch, CORETYPE_U8); } } @@ -719,6 +736,7 @@ enum eTokenType Token::typefromstr(const ::std::string& s) case TOK_CHAR: return FMT("'\\u{"<< ::std::hex << m_intval << "}"); case TOK_FLOAT: return FMT(m_floatval); case TOK_STRING: return "\"" + m_str + "\""; + case TOK_BYTESTRING:return "b\"" + m_str + "\""; case TOK_CATTR_OPEN:return "#!["; case TOK_ATTR_OPEN: return "#["; case TOK_UNDERSCORE:return "_"; @@ -829,7 +847,6 @@ enum eTokenType Token::typefromstr(const ::std::string& s) case TOK_RWORD_PROC: return "proc"; case TOK_RWORD_MOVE: return "move"; - case TOK_RWORD_ONCE: return "once"; case TOK_RWORD_ABSTRACT:return "abstract"; case TOK_RWORD_FINAL: return "final"; diff --git a/src/parse/root.cpp b/src/parse/root.cpp index 2ae39d91..1fd62741 100644 --- a/src/parse/root.cpp +++ b/src/parse/root.cpp @@ -821,6 +821,12 @@ void Parse_Impl_Item(TokenStream& lex, AST::Impl& impl) impl.add_type(is_public, name, Parse_Type(lex)); GET_CHECK_TOK(tok, lex, TOK_SEMICOLON); break; } + case TOK_RWORD_CONST: + if( GET_TOK(tok, lex) != TOK_RWORD_FN ) + { + throw ParseError::Todo("Associated const"); + } + if( 0 ) case TOK_RWORD_EXTERN: { abi = "C"; @@ -883,6 +889,22 @@ void Parse_Use_Wildcard(const AST::Path& base_path, ::std::function fcn) +{ + TRACE_FUNCTION; + + Token tok; + do { + if( GET_TOK(tok, lex) == TOK_RWORD_SELF ) { + fcn(base_path, base_path[base_path.size()-1].name()); + } + else { + CHECK_TOK(tok, TOK_IDENT); + fcn(base_path + AST::PathNode(tok.str(), {}), tok.str()); + } + } while( GET_TOK(tok, lex) == TOK_COMMA ); + lex.putback(tok); +} void Parse_Use(TokenStream& lex, ::std::function fcn) { @@ -916,6 +938,10 @@ void Parse_Use(TokenStream& lex, ::std::function lex.putback(tok); } break; + case TOK_BRACE_OPEN: + Parse_Use_Set(lex, path, fcn); + GET_CHECK_TOK(tok, lex, TOK_BRACE_CLOSE); + return; default: throw ParseError::Unexpected(lex, tok); } @@ -931,16 +957,8 @@ void Parse_Use(TokenStream& lex, ::std::function switch( tok.type() ) { case TOK_BRACE_OPEN: - do { - if( GET_TOK(tok, lex) == TOK_RWORD_SELF ) { - fcn(path, path[path.size()-1].name()); - } - else { - CHECK_TOK(tok, TOK_IDENT); - fcn(path + AST::PathNode(tok.str(), {}), tok.str()); - } - } while( GET_TOK(tok, lex) == TOK_COMMA ); - CHECK_TOK(tok, TOK_BRACE_CLOSE); + Parse_Use_Set(lex, path, fcn); + GET_CHECK_TOK(tok, lex, TOK_BRACE_CLOSE); break ; case TOK_STAR: Parse_Use_Wildcard(path, fcn); @@ -1244,8 +1262,10 @@ void Parse_ModRoot_Items(TokenStream& lex, AST::Crate& crate, AST::Module& mod, lex.putback(tok); DEBUG("meta_items = " << meta_items); + // root-level macros if( GET_TOK(tok, lex) == TOK_MACRO ) { + // `macro_rules! ...` if( tok.str() == "macro_rules" ) { Parse_MacroRules(lex, mod, mv$(meta_items)); @@ -1275,19 +1295,17 @@ void Parse_ModRoot_Items(TokenStream& lex, AST::Crate& crate, AST::Module& mod, // Module visibility bool is_public = false; - if( GET_TOK(tok, lex) == TOK_RWORD_PUB ) - { + if( GET_TOK(tok, lex) == TOK_RWORD_PUB ) { is_public = true; } - else - { + else { lex.putback(tok); } // The actual item! switch( GET_TOK(tok, lex) ) { - + // `use ...` case TOK_RWORD_USE: Parse_Use(lex, [&mod,is_public,&path](AST::Path p, std::string s) { DEBUG(path << " - use " << p << " as '" << s << "'"); @@ -1299,41 +1317,58 @@ void Parse_ModRoot_Items(TokenStream& lex, AST::Crate& crate, AST::Module& mod, case TOK_RWORD_EXTERN: switch( GET_TOK(tok, lex) ) { + // `extern "" fn ...` + // `extern "" { ...` case TOK_STRING: { ::std::string abi = tok.str(); switch(GET_TOK(tok, lex)) { + // `extern "" fn ...` case TOK_RWORD_FN: - throw ParseError::Todo(lex, "'extern \"\" fn'"); + GET_CHECK_TOK(tok, lex, TOK_IDENT); + mod.add_function(is_public, tok.str(), Parse_FunctionDefWithCode(lex, abi, ::std::move(meta_items), false)); + break; + // `extern "" { ...` case TOK_BRACE_OPEN: Parse_ExternBlock(lex, mod, ::std::move(abi)); break; default: - throw ParseError::Unexpected(lex, tok); - } + throw ParseError::Unexpected(lex, tok, {TOK_RWORD_FN, TOK_BRACE_OPEN}); } + break; } + // `extern fn ...` + case TOK_RWORD_FN: + throw ParseError::Todo(lex, "'extern fn'"); break; + // `extern { ...` + case TOK_BRACE_OPEN: + Parse_ExternBlock(lex, mod, "C"); + break; + // `extern crate "crate-name" as crate_name;` + // `extern crate crate_name;` case TOK_RWORD_CRATE: { ::std::string path, name; - // TODO: Handle #[macro_use]/#[macro_use(...)] - if( GET_TOK(tok, lex) == TOK_STRING ) + switch( GET_TOK(tok, lex) ) { + // `extern crate "crate-name" as crate_name;` + // TODO: rustc no longer supports this feature + case TOK_STRING: path = tok.str(); GET_CHECK_TOK(tok, lex, TOK_RWORD_AS); GET_CHECK_TOK(tok, lex, TOK_IDENT); name = tok.str(); - } - else if( tok.type() == TOK_IDENT ) - { + break; + // `extern crate crate_name;` + case TOK_IDENT: path = name = tok.str(); - } - else - { - throw ParseError::Unexpected(lex, tok); + break; + default: + throw ParseError::Unexpected(lex, tok, {TOK_STRING, TOK_IDENT}); } crate.load_extern_crate(path); mod.add_ext_crate(path, name); + // Handle #[macro_use]/#[macro_use(...)] auto at = meta_items.get("macro_use"); if( at ) { @@ -1350,21 +1385,37 @@ void Parse_ModRoot_Items(TokenStream& lex, AST::Crate& crate, AST::Module& mod, GET_CHECK_TOK(tok, lex, TOK_SEMICOLON); break; } default: - throw ParseError::Unexpected(lex, tok); + throw ParseError::Unexpected(lex, tok, {TOK_STRING, TOK_RWORD_FN, TOK_BRACE_OPEN, TOK_RWORD_CRATE}); } break; + // `const NAME` + // `const fn` case TOK_RWORD_CONST: { - GET_CHECK_TOK(tok, lex, TOK_IDENT); - ::std::string name = tok.str(); + switch( GET_TOK(tok, lex) ) + { + case TOK_IDENT: { + ::std::string name = tok.str(); - GET_CHECK_TOK(tok, lex, TOK_COLON); - TypeRef type = Parse_Type(lex); - GET_CHECK_TOK(tok, lex, TOK_EQUAL); - AST::Expr val = Parse_Expr(lex, true); - GET_CHECK_TOK(tok, lex, TOK_SEMICOLON); - mod.add_static(is_public, name, AST::Static(::std::move(meta_items), AST::Static::CONST, type, val)); + GET_CHECK_TOK(tok, lex, TOK_COLON); + TypeRef type = Parse_Type(lex); + GET_CHECK_TOK(tok, lex, TOK_EQUAL); + AST::Expr val = Parse_Expr(lex, true); + GET_CHECK_TOK(tok, lex, TOK_SEMICOLON); + mod.add_static(is_public, name, AST::Static(::std::move(meta_items), AST::Static::CONST, type, val)); + break; } + case TOK_RWORD_FN: { + GET_CHECK_TOK(tok, lex, TOK_IDENT); + // - self not allowed, not prototype + // TODO: Mark as const + mod.add_function(is_public, tok.str(), Parse_FunctionDefWithCode(lex, "rust", ::std::move(meta_items), false)); + break; } + default: + throw ParseError::Unexpected(lex, tok, {TOK_IDENT, TOK_RWORD_FN}); + } break; } + // `static NAME` + // `static mut NAME` case TOK_RWORD_STATIC: { tok = lex.getToken(); bool is_mut = false; @@ -1388,52 +1439,64 @@ void Parse_ModRoot_Items(TokenStream& lex, AST::Crate& crate, AST::Module& mod, ); break; } + // `unsafe fn` + // `unsafe trait` + // `unsafe impl` case TOK_RWORD_UNSAFE: meta_items.push_back( AST::MetaItem("#UNSAFE") ); switch(GET_TOK(tok, lex)) { + // `unsafe fn` case TOK_RWORD_FN: GET_CHECK_TOK(tok, lex, TOK_IDENT); // - self not allowed, not prototype + // TODO: Mark as unsafe mod.add_function(is_public, tok.str(), Parse_FunctionDefWithCode(lex, "rust", ::std::move(meta_items), false)); break; + // `unsafe trait` case TOK_RWORD_TRAIT: { GET_CHECK_TOK(tok, lex, TOK_IDENT); ::std::string name = tok.str(); mod.add_trait(is_public, name, Parse_TraitDef(lex, meta_items)); - break; - } + break; } + // `unsafe impl` case TOK_RWORD_IMPL: Parse_Impl(lex, mod, true); break; default: - throw ParseError::Unexpected(lex, tok); + throw ParseError::Unexpected(lex, tok, {TOK_RWORD_FN, TOK_RWORD_TRAIT, TOK_RWORD_IMPL}); } break; + // `fn` case TOK_RWORD_FN: { GET_CHECK_TOK(tok, lex, TOK_IDENT); ::std::string name = tok.str(); // - self not allowed, not prototype mod.add_function(is_public, name, Parse_FunctionDefWithCode(lex, "rust", ::std::move(meta_items), false)); break; } + // `type` case TOK_RWORD_TYPE: { GET_CHECK_TOK(tok, lex, TOK_IDENT); ::std::string name = tok.str(); mod.add_typealias(is_public, name, Parse_TypeAlias(lex, meta_items)); break; } + // `struct` case TOK_RWORD_STRUCT: { GET_CHECK_TOK(tok, lex, TOK_IDENT); ::std::string name = tok.str(); mod.add_struct( is_public, name, Parse_Struct(lex, meta_items) ); break; } + // `enum` case TOK_RWORD_ENUM: { GET_CHECK_TOK(tok, lex, TOK_IDENT); ::std::string name = tok.str(); mod.add_enum(is_public, name, Parse_EnumDef(lex, meta_items)); break; } + // `impl` case TOK_RWORD_IMPL: Parse_Impl(lex, mod); break; + // `trait` case TOK_RWORD_TRAIT: { GET_CHECK_TOK(tok, lex, TOK_IDENT); ::std::string name = tok.str(); @@ -1443,6 +1506,7 @@ void Parse_ModRoot_Items(TokenStream& lex, AST::Crate& crate, AST::Module& mod, case TOK_RWORD_MOD: { GET_CHECK_TOK(tok, lex, TOK_IDENT); ::std::string name = tok.str(); + // TODO: Remove this copy, by keeping record of macro_use() AST::Module submod(meta_items, name); DEBUG("Sub module '"<