summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ast/ast.cpp2
-rw-r--r--src/ast/ast.hpp6
-rw-r--r--src/ast/expr.hpp10
-rw-r--r--src/macros.cpp36
-rw-r--r--src/macros.hpp4
-rw-r--r--src/parse/expr.cpp57
-rw-r--r--src/parse/lex.cpp132
-rw-r--r--src/parse/lex.hpp13
-rw-r--r--src/parse/root.cpp162
-rw-r--r--src/parse/tokentree.hpp1
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), &macro_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);