diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/ast/ast.cpp | 2 | ||||
-rw-r--r-- | src/ast/ast.hpp | 6 | ||||
-rw-r--r-- | src/ast/expr.hpp | 10 | ||||
-rw-r--r-- | src/macros.cpp | 36 | ||||
-rw-r--r-- | src/macros.hpp | 4 | ||||
-rw-r--r-- | src/parse/expr.cpp | 57 | ||||
-rw-r--r-- | src/parse/lex.cpp | 132 | ||||
-rw-r--r-- | src/parse/lex.hpp | 13 | ||||
-rw-r--r-- | src/parse/root.cpp | 162 | ||||
-rw-r--r-- | src/parse/tokentree.hpp | 1 |
10 files changed, 350 insertions, 73 deletions
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<const MacroRules*>( ::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<MetaItem> 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<ExprNode> m_slot; unique_ptr<ExprNode> m_value; - ExprNode_Assign() {} - ExprNode_Assign(unique_ptr<ExprNode>&& slot, unique_ptr<ExprNode>&& value): + ExprNode_Assign(): m_op(NONE) {} + ExprNode_Assign(Operation op, unique_ptr<ExprNode>&& slot, unique_ptr<ExprNode>&& 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<MacroPatEnt> ents):
+ MacroPatEnt(Token sep, bool need_once, ::std::vector<MacroPatEnt> 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<ExprNodeP> 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 _, &<arg as Trait>::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>() );
+}
+
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 '"<<ch<<"' in float exponent") ); + do { + PUTC(ch); + ch = this->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 <cassert>
extern AST::Pattern Parse_Pattern(TokenStream& lex);
+void Parse_ModRoot(TokenStream& lex, AST::Crate& crate, AST::Module& mod, LList<AST::Module*> *prev_modstack, const ::std::string& path);
::std::vector<TypeRef> 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<AST::MetaItem> items;
do {
@@ -733,7 +754,7 @@ void Parse_Use_Wildcard(const AST::Path& base_path, ::std::function<void(AST::Pa fcn(base_path, ""); // HACK! Empty path indicates wilcard import
}
-void Parse_Use(Preproc& lex, ::std::function<void(AST::Path, ::std::string)> fcn)
+void Parse_Use(TokenStream& lex, ::std::function<void(AST::Path, ::std::string)> fcn)
{
TRACE_FUNCTION;
@@ -838,10 +859,16 @@ void Parse_Use(Preproc& lex, ::std::function<void(AST::Path, ::std::string)> 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<void(AST::Path, ::std::string)> 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<void(AST::Path, ::std::string)> fcn return ret;
}
-::std::vector<MacroRuleEnt> Parse_MacroRules_Cont(Preproc& lex, bool allow_sub, enum eTokenType open, enum eTokenType close)
+::std::vector<MacroRuleEnt> 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<void(AST::Path, ::std::string)> 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<void(AST::Path, ::std::string)> 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<AST::Module*> *prev_modstack, const ::std::string& path)
+void Parse_ModRoot_Items(TokenStream& lex, AST::Crate& crate, AST::Module& mod, LList<AST::Module*>& modstack, const ::std::string& path)
{
TRACE_FUNCTION;
- LList<AST::Module*> 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, LList<AST: }
else
{
- throw ParseError::Todo("module-level syntax extensions");
+ TokenTree tt = Parse_TT(lex, true);
+ if( tt.size() == 0 ) {
+ throw ParseError::Unexpected(lex, tt.tok());
+ }
+ ::std::string name = tok.str();
+
+ MacroExpander expanded_macro = Macro_Invoke(name.c_str(), tt);
+ Parse_ModRoot_Items(expanded_macro, crate, mod, modstack, path);
}
break;
@@ -1244,6 +1260,20 @@ void Parse_ModRoot(Preproc& lex, AST::Crate& crate, AST::Module& mod, LList<AST: {
throw ParseError::Generic( FMT("Can't load from files outside of mod.rs or crate root") );
}
+ else if( meta_items.has("path") )
+ {
+ ::std::string newpath_dir = path + meta_items.get("path")->string();
+ ::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, LList<AST: default:
throw ParseError::Generic("Expected { or ; after module name");
}
+ submod.prescan();
mod.add_submod(is_public, ::std::move(submod));
Macro_SetModule(modstack);
+
+ // import macros
+ {
+ auto at = meta_items.get("macro_use");
+ if( at )
+ {
+ if( at->has_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<AST: }
}
+void Parse_ModRoot(TokenStream& lex, AST::Crate& crate, AST::Module& mod, LList<AST::Module*> *prev_modstack, const ::std::string& path)
+{
+ TRACE_FUNCTION;
+ LList<AST::Module*> 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);
|