From 06e7e28cd4de3871f55255150b66821b12365881 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Thu, 12 Mar 2015 12:40:36 +0800 Subject: Float parsing, module-level macro expansion --- src/ast/ast.cpp | 2 + src/ast/ast.hpp | 6 ++ src/ast/expr.hpp | 10 ++- src/macros.cpp | 36 ++++++----- src/macros.hpp | 4 +- src/parse/expr.cpp | 57 +++++++++++++---- src/parse/lex.cpp | 132 +++++++++++++++++++++++++++++++++++++-- src/parse/lex.hpp | 13 ++++ src/parse/root.cpp | 162 ++++++++++++++++++++++++++++++++++++------------ src/parse/tokentree.hpp | 1 + 10 files changed, 350 insertions(+), 73 deletions(-) (limited to 'src') diff --git a/src/ast/ast.cpp b/src/ast/ast.cpp index 8a903cca..0caa41a2 100644 --- a/src/ast/ast.cpp +++ b/src/ast/ast.cpp @@ -387,6 +387,8 @@ void Module::resolve_macro_import(const Crate& crate, const ::std::string& modna { for( const auto& macro_p : sm.m_macro_import_res ) m_macro_import_res.push_back( macro_p ); + for( const auto& macro_i : sm.m_macros ) + m_macro_import_res.push_back( ItemNS( ::std::string(macro_i.name), ¯o_i.data, false ) ); return ; } else diff --git a/src/ast/ast.hpp b/src/ast/ast.hpp index 1da79696..81a0dbd6 100644 --- a/src/ast/ast.hpp +++ b/src/ast/ast.hpp @@ -190,6 +190,11 @@ public: m_name(name) { } + MetaItem(::std::string name, ::std::string str_val): + m_name(name), + m_str_val(str_val) + { + } MetaItem(::std::string name, ::std::vector items): m_name(name), m_sub_items(items) @@ -198,6 +203,7 @@ public: void mark_used() {} const ::std::string& name() const { return m_name; } + const ::std::string& string() const { return m_str_val; } bool has_sub_items() const { return m_sub_items.m_items.size() > 0; } MetaItems& items() { return m_sub_items; } diff --git a/src/ast/expr.hpp b/src/ast/expr.hpp index e01606d7..ca655fe0 100644 --- a/src/ast/expr.hpp +++ b/src/ast/expr.hpp @@ -110,11 +110,17 @@ struct ExprNode_LetBinding: struct ExprNode_Assign: public ExprNode { + enum Operation { + NONE, + ADD, + SUB, + } m_op; unique_ptr m_slot; unique_ptr m_value; - ExprNode_Assign() {} - ExprNode_Assign(unique_ptr&& slot, unique_ptr&& value): + ExprNode_Assign(): m_op(NONE) {} + ExprNode_Assign(Operation op, unique_ptr&& slot, unique_ptr&& value): + m_op(op), m_slot( move(slot) ), m_value( move(value) ) { diff --git a/src/macros.cpp b/src/macros.cpp index b20f9fad..c52f8836 100644 --- a/src/macros.cpp +++ b/src/macros.cpp @@ -62,7 +62,7 @@ void Macro_InitDefaults() // panic!() "macro" { MacroRule rule; - rule.m_pattern.push_back( MacroPatEnt(Token(TOK_NULL), { + rule.m_pattern.push_back( MacroPatEnt(Token(TOK_NULL), false, { MacroPatEnt("tt", MacroPatEnt::PAT_TT), } ) ); rule.m_contents.push_back( MacroRuleEnt(Token(TOK_PAREN_OPEN)) ); @@ -132,6 +132,9 @@ void Macro_HandlePattern(TTStream& lex, const MacroPatEnt& pat, unsigned int lay lex.putback(tok); val = Parse_TT(lex, false); if(0) + case MacroPatEnt::PAT_TYPE: + val = Parse_TT_Type(lex); + if(0) case MacroPatEnt::PAT_EXPR: val = Parse_TT_Expr(lex); if(0) @@ -211,23 +214,15 @@ MacroExpander Macro_Invoke(const char* name, TokenTree input) if( g_macro_registrations.size() == 0 ) { Macro_InitDefaults(); } - - // 1. Builtin syntax extensions - { - const ::std::string sname = name; - if( sname == "format_args" ) - { - throw ParseError::Todo("format_args"); - } - } - // 2. Locate macro with that name + // Look for macro in builtins t_macro_regs::iterator macro_reg = g_macro_registrations.find(name); if( macro_reg != g_macro_registrations.end() ) { return Macro_InvokeInt(macro_reg->first.c_str(), macro_reg->second, input); } + // Search import list for( auto ent = g_macro_module; ent; ent = ent->m_prev ) { const AST::Module& mm = *ent->m_item; @@ -296,11 +291,22 @@ Token MacroExpander::realGetToken() return m_ttstream->getToken(); } else { - const auto tt_i = m_mappings.find( ::std::make_pair(layer, ent.name.c_str()) ); - if( tt_i == m_mappings.end() ) + const size_t iter_idx = m_offsets.back().second; + const auto tt_i = m_mappings.equal_range( ::std::make_pair(layer, ent.name.c_str()) ); + if( tt_i.first == tt_i.second ) throw ParseError::Generic( FMT("Cannot find mapping name: " << ent.name << " for layer " << layer) ); - m_ttstream.reset( new TTStream(tt_i->second) ); - return m_ttstream->getToken(); + + size_t i = 0; + for( auto it = tt_i.first; it != tt_i.second; it ++ ) + { + if( i == iter_idx ) + { + m_ttstream.reset( new TTStream(it->second) ); + return m_ttstream->getToken(); + } + i ++; + } + throw ParseError::Generic( FMT("Cannot find mapping name: " << ent.name << " for layer " << layer) ); } } else if( ent.subpats.size() != 0 ) diff --git a/src/macros.hpp b/src/macros.hpp index 74001cae..2938cb93 100644 --- a/src/macros.hpp +++ b/src/macros.hpp @@ -57,6 +57,7 @@ struct MacroPatEnt: PAT_TT, PAT_IDENT, PAT_PATH, + PAT_TYPE, PAT_EXPR, PAT_STMT, PAT_BLOCK, @@ -81,7 +82,8 @@ struct MacroPatEnt: { } - MacroPatEnt(Token sep, ::std::vector ents): + MacroPatEnt(Token sep, bool need_once, ::std::vector ents): + name( need_once ? "+" : "*" ), tok(sep), subpats( move(ents) ), type(PAT_LOOP) diff --git a/src/parse/expr.cpp b/src/parse/expr.cpp index be4d67a6..1a9b494c 100644 --- a/src/parse/expr.cpp +++ b/src/parse/expr.cpp @@ -57,14 +57,12 @@ AST::Pattern Parse_Pattern(TokenStream& lex) // 1. Mutablity + Reference if( tok.type() == TOK_RWORD_REF ) { - throw ParseError::Todo("ref bindings"); is_ref = true; expect_bind = true; tok = lex.getToken(); } if( tok.type() == TOK_RWORD_MUT ) { - throw ParseError::Todo("mut bindings"); is_mut = true; expect_bind = true; tok = lex.getToken(); @@ -288,16 +286,18 @@ ExprNodeP Parse_Expr0(TokenStream& lex) Token tok; ExprNodeP rv = Parse_ExprBlocks(lex); - if( GET_TOK(tok, lex) == TOK_EQUAL ) - { - ExprNodeP val = Parse_Expr1(lex); - rv = NEWNODE( AST::ExprNode_Assign, ::std::move(rv), ::std::move(val) ); - } - else + switch( GET_TOK(tok, lex) ) { + case TOK_EQUAL: + return NEWNODE( AST::ExprNode_Assign, AST::ExprNode_Assign::NONE, ::std::move(rv), Parse_Expr1(lex) ); + case TOK_PLUS_EQUAL: + return NEWNODE( AST::ExprNode_Assign, AST::ExprNode_Assign::ADD, ::std::move(rv), Parse_Expr1(lex) ); + case TOK_DASH_EQUAL: + return NEWNODE( AST::ExprNode_Assign, AST::ExprNode_Assign::SUB, ::std::move(rv), Parse_Expr1(lex) ); + default: lex.putback(tok); + return rv; } - return rv; } /// Parse an 'if' statement @@ -623,6 +623,31 @@ ExprNodeP Parse_ExprVal_StructLiteral(TokenStream& lex, AST::Path path) return NEWNODE( AST::ExprNode_StructLiteral, path, ::std::move(base_val), ::std::move(items) ); } +ExprNodeP Parse_FormatArgs(TokenStream& lex) +{ + TRACE_FUNCTION; + + Token tok; + + GET_CHECK_TOK(tok, lex, TOK_STRING); + ::std::string fmt = tok.str(); + + ::std::vector nodes; + + while( GET_TOK(tok, lex) == TOK_COMMA ) + { + // TODO: Support named + auto exp = NEWNODE( AST::ExprNode_UniOp, AST::ExprNode_UniOp::REF, Parse_Expr1(lex) ); + + // ( &arg as *const _, &::fmt as fn(*const (), &mut Formatter) ) + //nodes.push_back( NEWNODE( AST::ExprNode_Cast, TypeRef + } + + //return NEWNODE( AST::ExprNode_ArrayLiteral, ::std::move(nodes) ); + DEBUG("TODO: Proper support for format_args!"); + return NEWNODE( AST::ExprNode_Tuple, ::std::vector() ); +} + ExprNodeP Parse_ExprVal(TokenStream& lex) { TRACE_FUNCTION; @@ -694,8 +719,18 @@ ExprNodeP Parse_ExprVal(TokenStream& lex) if( tt.size() == 0 ) { throw ParseError::Unexpected(lex, tt.tok()); } - MacroExpander expanded_macro = Macro_Invoke(tok.str().c_str(), tt); - return Parse_Expr0(expanded_macro); + ::std::string name = tok.str(); + + if( name == "format_args" ) + { + TTStream slex(tt); + return Parse_FormatArgs(slex); + } + else + { + MacroExpander expanded_macro = Macro_Invoke(name.c_str(), tt); + return Parse_Expr0(expanded_macro); + } } default: throw ParseError::Unexpected(lex, tok); diff --git a/src/parse/lex.cpp b/src/parse/lex.cpp index 678da4d0..fc2c7401 100644 --- a/src/parse/lex.cpp +++ b/src/parse/lex.cpp @@ -200,6 +200,10 @@ bool issym(char ch) Token Lexer::getToken() { + if( this->m_next_token.type() != TOK_NULL ) + { + return ::std::move(this->m_next_token); + } try { char ch = this->getc(); @@ -222,12 +226,20 @@ Token Lexer::getToken() char ch = this->getc(); if( isdigit(ch) ) { + enum eCoreType num_type = CORETYPE_ANY; + enum { + BIN, + OCT, + DEC, + HEX, + } num_mode = DEC; // TODO: handle integers/floats uint64_t val = 0; if( ch == '0' ) { // Octal/hex handling ch = this->getc(); if( ch == 'x' ) { + num_mode = HEX; while( isxdigit(ch = this->getc()) ) { val *= 16; @@ -239,10 +251,16 @@ Token Lexer::getToken() val += ch - 'a' + 10; } } + else if( ch == 'b' ) { + num_mode = BIN; + throw ParseError::Todo("Lex binary numbers"); + } else if( isdigit(ch) ) { + num_mode = OCT; throw ParseError::Todo("Lex octal numbers"); } else { + num_mode = DEC; val = 0; } } @@ -259,11 +277,60 @@ Token Lexer::getToken() throw ParseError::Todo("Lex number suffixes"); } else if( ch == '.' ) { - throw ParseError::Todo("Lex floats"); + if( num_mode != DEC ) + throw ParseError::Todo("Non-decimal floats"); + + ch = this->getc(); + + // Double/Triple Dot + if( ch == '.' ) { + if( this->getc() == '.') { + this->m_next_token = Token(TOK_TRIPLE_DOT); + } + else { + this->putback(); + this->m_next_token = Token(TOK_DOUBLE_DOT); + } + return Token(val, CORETYPE_ANY); + } + // Single dot + else if( !isdigit(ch) ) + { + this->m_next_token = Token(TOK_DOT); + return Token(val, CORETYPE_ANY); + } + + this->putback(); + double fval = this->parseFloat(val); + if( (ch = this->getc()) == 'f' ) + { + ::std::string suffix; + while( issym(ch) ) + { + suffix.push_back(ch); + ch = this->getc(); + } + this->putback(); + if( suffix == "f32" ) { + num_type = CORETYPE_F32; + } + else if( suffix == "f64" ) { + num_type = CORETYPE_F64; + } + else { + throw ParseError::Generic( FMT("Unknown number suffix " << suffix) ); + } + } + else + { + this->putback(); + } + return Token( fval, num_type); + } else { this->putback(); - return Token(val, CORETYPE_ANY); + return Token(val, num_type); } } else if( issym(ch) ) @@ -379,6 +446,42 @@ Token Lexer::getToken() //assert(!"bugcheck"); } +// Takes the VERY lazy way of reading the float into a string then passing to strtod +double Lexer::parseFloat(uint64_t whole) +{ + const int MAX_LEN = 63; + const int MAX_SIG = MAX_LEN - 1 - 4; + char buf[MAX_LEN+1]; + int ofs = snprintf(buf, MAX_LEN+1, "%llu", (unsigned long long)whole); + + char ch = this->getc_num(); + #define PUTC(ch) do { if( ofs < MAX_SIG ) { buf[ofs] = ch; ofs ++; } else { throw ParseError::Generic("Oversized float"); } } while(0) + while( isdigit(ch) ) + { + PUTC(ch); + ch = this->getc_num(); + } + if( ch == 'e' || ch == 'E' ) + { + PUTC(ch); + ch = this->getc_num(); + if( ch == '-' || ch == '+' ) { + PUTC(ch); + ch = this->getc_num(); + } + if( !isdigit(ch) ) + throw ParseError::Generic( FMT("Non-numeric '"<getc_num(); + } while( isdigit(ch) ); + } + this->putback(); + buf[ofs] = 0; + + return ::std::strtod(buf, NULL); +} + uint32_t Lexer::parseEscape(char enclosing) { char ch = this->getc(); @@ -389,7 +492,7 @@ uint32_t Lexer::parseEscape(char enclosing) uint32_t val = 0; ch = this->getc(); if( !isxdigit(ch) ) - throw ParseError::Todo("Proper lex error for escape sequences"); + throw ParseError::Todo( FMT("Found invalid character '\\x" << ::std::hex << (int)ch << "' in \\u sequence" ) ); while( isxdigit(ch) ) { char tmp[2] = {ch, 0}; @@ -401,8 +504,14 @@ uint32_t Lexer::parseEscape(char enclosing) return val; } case '\\': return '\\'; + case 'n': + return '\n'; + case '\n': + while( isspace(ch) ) + ch = this->getc(); + return ch; default: - throw ParseError::Todo("Proper lex error for escape sequences"); + throw ParseError::Todo( FMT("Unknown escape sequence \\" << ch) ); } } @@ -422,6 +531,15 @@ char Lexer::getc() return m_last_char; } +char Lexer::getc_num() +{ + char ch; + do { + ch = this->getc(); + } while( ch == '_' ); + return ch; +} + void Lexer::putback() { // ::std::cout << "putback(): " << m_last_char_valid << " '" << m_last_char << "'" << ::std::endl; @@ -450,6 +568,12 @@ Token::Token(uint64_t val, enum eCoreType datatype): m_intval(val) { } +Token::Token(double val, enum eCoreType datatype): + m_type(TOK_FLOAT), + m_datatype(datatype), + m_floatval(val) +{ +} const char* Token::typestr(enum eTokenType type) { diff --git a/src/parse/lex.hpp b/src/parse/lex.hpp index 25c2d530..bea5698a 100644 --- a/src/parse/lex.hpp +++ b/src/parse/lex.hpp @@ -24,6 +24,16 @@ class Token: }; public: Token(); + Token(const Token& t) = default; + Token& operator =(const Token& t) = default; + Token(Token&& t): + m_type(t.m_type), + m_str( ::std::move(t.m_str) ), + m_datatype( t.m_datatype ), + m_intval( t.m_intval ) + { + t.m_type = TOK_NULL; + } Token(enum eTokenType type); Token(enum eTokenType type, ::std::string str); Token(uint64_t val, enum eCoreType datatype); @@ -104,6 +114,7 @@ class Lexer ::std::ifstream m_istream; bool m_last_char_valid; char m_last_char; + Token m_next_token; // Used when lexing generated two tokens public: Lexer(::std::string filename); @@ -111,9 +122,11 @@ public: private: signed int getSymbol(); + double parseFloat(uint64_t whole); uint32_t parseEscape(char enclosing); char getc(); + char getc_num(); void putback(); class EndOfFile {}; diff --git a/src/parse/root.cpp b/src/parse/root.cpp index 8ae7bc1f..8f5bc737 100644 --- a/src/parse/root.cpp +++ b/src/parse/root.cpp @@ -8,6 +8,7 @@ #include extern AST::Pattern Parse_Pattern(TokenStream& lex); +void Parse_ModRoot(TokenStream& lex, AST::Crate& crate, AST::Module& mod, LList *prev_modstack, const ::std::string& path); ::std::vector Parse_Path_GenericList(TokenStream& lex) { @@ -324,22 +325,41 @@ AST::Function Parse_FunctionDef(TokenStream& lex, bool allow_no_code=false) if( tok.type() == TOK_AMP ) { // By-reference method + bool force_type = false; ::std::string lifetime; if( GET_TOK(tok, lex) == TOK_LIFETIME ) { lifetime = tok.str(); GET_TOK(tok, lex); + force_type = true; + // Forces to be a type } if( tok.type() == TOK_RWORD_MUT ) { - GET_CHECK_TOK(tok, lex, TOK_RWORD_SELF); + // Forces to be a type fcn_class = AST::Function::CLASS_MUTMETHOD; + force_type = true; + GET_TOK(tok, lex); } else { - CHECK_TOK(tok, TOK_RWORD_SELF); fcn_class = AST::Function::CLASS_REFMETHOD; } + + if( tok.type() == TOK_RWORD_SELF ) + { + // Could be a type or a binding... + CHECK_TOK(tok, TOK_RWORD_SELF); + } + else if( force_type ) + { + // Fall into type parsing somehow + + } + else + { + // either a reference binding or a type + } DEBUG("TODO: UFCS / self lifetimes"); //args.push_back( ::std::make_pair( AST::Pattern(), TypeRef(TypeRef::TagReference(), lifetime, (fcn_class == AST::Function::CLASS_MUTMETHOD), ) ) ); GET_TOK(tok, lex); @@ -644,7 +664,8 @@ AST::MetaItem Parse_MetaItem(TokenStream& lex) switch(GET_TOK(tok, lex)) { case TOK_EQUAL: - throw ParseError::Todo("Meta item key-value"); + GET_CHECK_TOK(tok, lex, TOK_STRING); + return AST::MetaItem(name, tok.str()); case TOK_PAREN_OPEN: { ::std::vector items; do { @@ -733,7 +754,7 @@ void Parse_Use_Wildcard(const AST::Path& base_path, ::std::function fcn) +void Parse_Use(TokenStream& lex, ::std::function fcn) { TRACE_FUNCTION; @@ -838,10 +859,16 @@ void Parse_Use(Preproc& lex, ::std::function fcn ::std::string type = tok.str(); if(0) ; - else if( type == "expr" ) - ret.push_back( MacroPatEnt(name, MacroPatEnt::PAT_EXPR) ); else if( type == "tt" ) ret.push_back( MacroPatEnt(name, MacroPatEnt::PAT_TT) ); + else if( type == "ident" ) + ret.push_back( MacroPatEnt(name, MacroPatEnt::PAT_IDENT) ); + else if( type == "path" ) + ret.push_back( MacroPatEnt(name, MacroPatEnt::PAT_PATH) ); + else if( type == "expr" ) + ret.push_back( MacroPatEnt(name, MacroPatEnt::PAT_EXPR) ); + else if( type == "ty" ) + ret.push_back( MacroPatEnt(name, MacroPatEnt::PAT_TYPE) ); else throw ParseError::Generic(FMT("Unknown fragment type " << type)); break; } @@ -861,11 +888,12 @@ void Parse_Use(Preproc& lex, ::std::function fcn switch(tok.type()) { case TOK_PLUS: - throw ParseError::Todo(lex, "+ repetitions"); + DEBUG("$()+ " << subpat); + ret.push_back( MacroPatEnt(Token(joiner), true, ::std::move(subpat)) ); break; case TOK_STAR: DEBUG("$()* " << subpat); - ret.push_back( MacroPatEnt(Token(joiner), ::std::move(subpat)) ); + ret.push_back( MacroPatEnt(Token(joiner), false, ::std::move(subpat)) ); break; default: throw ParseError::Unexpected(lex, tok); @@ -891,7 +919,7 @@ void Parse_Use(Preproc& lex, ::std::function fcn return ret; } -::std::vector Parse_MacroRules_Cont(Preproc& lex, bool allow_sub, enum eTokenType open, enum eTokenType close) +::std::vector Parse_MacroRules_Cont(TokenStream& lex, bool allow_sub, enum eTokenType open, enum eTokenType close) { TRACE_FUNCTION; @@ -940,6 +968,10 @@ void Parse_Use(Preproc& lex, ::std::function fcn case TOK_STAR: ret.push_back( MacroRuleEnt(joiner, ::std::move(content)) ); break; + case TOK_PLUS: + // TODO: Ensure that the plusses match + ret.push_back( MacroRuleEnt(joiner, ::std::move(content)) ); + break; default: throw ParseError::Unexpected(lex, tok); } @@ -967,7 +999,7 @@ void Parse_Use(Preproc& lex, ::std::function fcn return ret; } -MacroRule Parse_MacroRules_Var(Preproc& lex) +MacroRule Parse_MacroRules_Var(TokenStream& lex) { TRACE_FUNCTION; Token tok; @@ -1003,7 +1035,7 @@ MacroRule Parse_MacroRules_Var(Preproc& lex) return rule; } -void Parse_MacroRules(Preproc& lex, AST::Module& mod, AST::MetaItems& meta_items) +void Parse_MacroRules(TokenStream& lex, AST::Module& mod, AST::MetaItems& meta_items) { TRACE_FUNCTION; @@ -1020,7 +1052,10 @@ void Parse_MacroRules(Preproc& lex, AST::Module& mod, AST::MetaItems& meta_items lex.putback(tok); rules.push_back( Parse_MacroRules_Var(lex) ); - GET_CHECK_TOK(tok, lex, TOK_SEMICOLON); + if(GET_TOK(tok, lex) != TOK_SEMICOLON) { + CHECK_TOK(tok, TOK_BRACE_CLOSE); + break; + } } bool is_pub = meta_items.has("macro_export"); @@ -1028,38 +1063,12 @@ void Parse_MacroRules(Preproc& lex, AST::Module& mod, AST::MetaItems& meta_items mod.add_macro( is_pub, name, MacroRules(move(rules)) ); } -void Parse_ModRoot(Preproc& lex, AST::Crate& crate, AST::Module& mod, LList *prev_modstack, const ::std::string& path) +void Parse_ModRoot_Items(TokenStream& lex, AST::Crate& crate, AST::Module& mod, LList& modstack, const ::std::string& path) { TRACE_FUNCTION; - LList modstack(prev_modstack, &mod); - Macro_SetModule(modstack); - const bool nested_module = (path == "-"); // 'mod name { code }', as opposed to 'mod name;' Token tok; - if( crate.m_load_std ) - { - // Import the prelude - AST::Path prelude_path = AST::Path( "std", { AST::PathNode("prelude", {}), AST::PathNode("v1", {}) } ); - Parse_Use_Wildcard(prelude_path, - [&mod](AST::Path p, std::string s) { - mod.add_alias(false, p, s); - } - ); - } - - // Attributes on module/crate (will continue loop) - while( GET_TOK(tok, lex) == TOK_CATTR_OPEN ) - { - AST::MetaItem item = Parse_MetaItem(lex); - GET_CHECK_TOK(tok, lex, TOK_SQUARE_CLOSE); - - mod.add_attr( item ); - } - lex.putback(tok); - - // TODO: Iterate attributes, and check for handlers on each - for(;;) { // Check 1 - End of module (either via a closing brace, or EOF) @@ -1113,7 +1122,14 @@ void Parse_ModRoot(Preproc& lex, AST::Crate& crate, AST::Module& mod, LListstring(); + ::std::ifstream ifs_dir (newpath_dir); + if( !ifs_dir.is_open() ) + { + } + else + { + ::std::string newdir( newpath_dir.begin(), newpath_dir.begin() + newpath_dir.find_last_of('/') ); + Preproc sub_lex(newpath_dir); + Parse_ModRoot(sub_lex, crate, submod, &modstack, newdir); + } + } else { ::std::string newpath_dir = path + name + "/"; @@ -1276,8 +1306,25 @@ void Parse_ModRoot(Preproc& lex, AST::Crate& crate, AST::Module& mod, LListhas_sub_items() ) + { + throw ParseError::Todo("selective macro_use"); + } + else + { + mod.add_macro_import(crate, name, ""); + } + } + } break; } default: @@ -1286,6 +1333,41 @@ void Parse_ModRoot(Preproc& lex, AST::Crate& crate, AST::Module& mod, LList *prev_modstack, const ::std::string& path) +{ + TRACE_FUNCTION; + LList modstack(prev_modstack, &mod); + Macro_SetModule(modstack); + + const bool nested_module = (path == "-"); // 'mod name { code }', as opposed to 'mod name;' + Token tok; + + if( crate.m_load_std ) + { + // Import the prelude + AST::Path prelude_path = AST::Path( "std", { AST::PathNode("prelude", {}), AST::PathNode("v1", {}) } ); + Parse_Use_Wildcard(prelude_path, + [&mod](AST::Path p, std::string s) { + mod.add_alias(false, p, s); + } + ); + } + + // Attributes on module/crate (will continue loop) + while( GET_TOK(tok, lex) == TOK_CATTR_OPEN ) + { + AST::MetaItem item = Parse_MetaItem(lex); + GET_CHECK_TOK(tok, lex, TOK_SQUARE_CLOSE); + + mod.add_attr( item ); + } + lex.putback(tok); + + // TODO: Iterate attributes, and check for handlers on each + + Parse_ModRoot_Items(lex, crate, mod, modstack, path); +} + AST::Crate Parse_Crate(::std::string mainfile) { Token tok; diff --git a/src/parse/tokentree.hpp b/src/parse/tokentree.hpp index 629322dd..b3156f66 100644 --- a/src/parse/tokentree.hpp +++ b/src/parse/tokentree.hpp @@ -50,6 +50,7 @@ protected: // unwrapped = Exclude the enclosing brackets (used by macro parse code) extern TokenTree Parse_TT(TokenStream& lex, bool unwrapped); extern TokenTree Parse_TT_Expr(TokenStream& lex); +extern TokenTree Parse_TT_Type(TokenStream& lex); extern TokenTree Parse_TT_Stmt(TokenStream& lex); extern TokenTree Parse_TT_Block(TokenStream& lex); extern TokenTree Parse_TT_Path(TokenStream& lex, bool mode_expr); -- cgit v1.2.3