diff options
-rw-r--r-- | Makefile | 6 | ||||
-rw-r--r-- | samples/std.rs | 17 | ||||
-rw-r--r-- | src/ast/ast.cpp | 155 | ||||
-rw-r--r-- | src/ast/ast.hpp | 92 | ||||
-rw-r--r-- | src/ast/expr.cpp | 6 | ||||
-rw-r--r-- | src/ast/expr.hpp | 16 | ||||
-rw-r--r-- | src/common.hpp | 13 | ||||
-rw-r--r-- | src/dump_as_rust.cpp | 22 | ||||
-rw-r--r-- | src/include/debug.hpp | 24 | ||||
-rw-r--r-- | src/include/serialise.hpp | 1 | ||||
-rw-r--r-- | src/macros.cpp | 268 | ||||
-rw-r--r-- | src/macros.hpp | 47 | ||||
-rw-r--r-- | src/parse/common.hpp | 23 | ||||
-rw-r--r-- | src/parse/eTokenType.enum.h | 132 | ||||
-rw-r--r-- | src/parse/expr.cpp | 72 | ||||
-rw-r--r-- | src/parse/lex.cpp | 176 | ||||
-rw-r--r-- | src/parse/lex.hpp | 139 | ||||
-rw-r--r-- | src/parse/preproc.cpp | 5 | ||||
-rw-r--r-- | src/parse/root.cpp | 161 | ||||
-rw-r--r-- | src/parse/tokentree.hpp | 4 |
20 files changed, 941 insertions, 438 deletions
@@ -8,6 +8,7 @@ LIBS := CXXFLAGS := -g -Wall -std=c++11 CPPFLAGS := -I src/include/ +SHELL = bash OBJDIR = .obj/ @@ -30,8 +31,9 @@ clean: test: $(BIN) samples/1.rs mkdir -p output/ - $(DBG) $(BIN) samples/std.rs --emit ast -o output/std.ast 2>&1 | tee output/ast_dbg.txt - $(DBG) $(BIN) samples/1.rs --crate-path output/std.ast -o output/test.c 2>&1 | tee output/1_dbg.txt + $(DBG) $(BIN) samples/std.rs --emit ast -o output/std.ast 2>&1 | tee output/ast_dbg.txt ; test $${PIPESTATUS[0]} -eq 0 +# $(DBG) $(BIN) samples/1.rs --crate-path output/std.ast -o output/test.c 2>&1 | tee output/1_dbg.txt + $(DBG) $(BIN) ../../BinaryView2/src/main.rs --crate-path output/std.ast -o output/test.c 2>&1 | tee output/1_dbg.txt ; test $${PIPESTATUS[0]} -eq 0 $(BIN): $(OBJ) @mkdir -p $(dir $@) diff --git a/samples/std.rs b/samples/std.rs index a44ae54e..228be06d 100644 --- a/samples/std.rs +++ b/samples/std.rs @@ -1,5 +1,22 @@ #![no_std] +#[macro_export] +macro_rules! try { + ($e:expr) => ( match $e { Ok(v) => v, Err(e) => return Err(e); } ); +} +#[macro_export] +macro_rules! assert{ + ($e:expr) => ({ if !($e) { panic!("Assertion {} failed", stringify!($e)); } }); +} +#[macro_export] +macro_rules! assert_eq{ + ($a:expr, $b:expr) => ({ + let left = &$a; + let right = &$b; + assert!( left == right && right == left ); + }); +} + pub mod option { pub enum Option<T> diff --git a/src/ast/ast.cpp b/src/ast/ast.cpp index 7f3430f2..e6187001 100644 --- a/src/ast/ast.cpp +++ b/src/ast/ast.cpp @@ -2,6 +2,7 @@ */
#include "ast.hpp"
#include "../types.hpp"
+#include "../common.hpp"
#include <iostream>
#include "../parse/parseerror.hpp"
#include <algorithm>
@@ -9,14 +10,32 @@ namespace AST {
+void MetaItems::push_back(MetaItem i)
+{
+ m_items.push_back( ::std::move(i) );
+}
+MetaItem* MetaItems::get(const char *name)
+{
+ for( auto& i : m_items ) {
+ if(i.name() == name) {
+ i.mark_used();
+ return &i;
+ }
+ }
+ return 0;
+}
+SERIALISE_TYPE_A(MetaItems::, "AST_MetaItems", {
+ s.item(m_items);
+})
+
SERIALISE_TYPE(MetaItem::, "AST_MetaItem", {
s << m_name;
s << m_str_val;
- s << m_items;
+ s << m_sub_items;
},{
s.item(m_name);
s.item(m_str_val);
- s.item(m_items);
+ s.item(m_sub_items);
})
::std::ostream& operator<<(::std::ostream& os, const Pattern& pat)
@@ -249,6 +268,8 @@ void Crate::load_extern_crate(::std::string name) ExternCrate ret;
d.item( ret.crate() );
+ ret.prescan();
+
m_extern_crates.insert( make_pair(::std::move(name), ::std::move(ret)) );
}
SERIALISE_TYPE(Crate::, "AST_Crate", {
@@ -269,34 +290,47 @@ ExternCrate::ExternCrate(const char *path) {
throw ParseError::Todo("Load extern crate from a file");
}
-SERIALISE_TYPE(ExternCrate::, "AST_ExternCrate", {
-},{
-})
-SERIALISE_TYPE(Module::, "AST_Module", {
- s << m_name;
- s << m_attrs;
-
- s << m_extern_crates;
- s << m_submods;
-
- s << m_imports;
- s << m_type_aliases;
+// Fill runtime-generated structures in the crate
+void ExternCrate::prescan()
+{
+ TRACE_FUNCTION;
- s << m_traits;
- s << m_enums;
- s << m_structs;
- s << m_statics;
+ Crate& cr = m_crate;
+
+ cr.m_root_module.prescan();
- s << m_functions;
- s << m_impls;
+ for( const auto& mi : cr.m_root_module.macro_imports_res() )
+ {
+ DEBUG("Macro (I) '"<<mi.name<<"' is_pub="<<mi.is_pub);
+ if( mi.is_pub )
+ {
+ m_crate.m_exported_macros.insert( ::std::make_pair(mi.name, mi.data) );
+ }
+ }
+ for( const auto& mi : cr.m_root_module.macros() )
+ {
+ DEBUG("Macro '"<<mi.name<<"' is_pub="<<mi.is_pub);
+ if( mi.is_pub )
+ {
+ m_crate.m_exported_macros.insert( ::std::make_pair(mi.name, &mi.data) );
+ }
+ }
+}
+
+SERIALISE_TYPE(ExternCrate::, "AST_ExternCrate", {
},{
+})
+
+SERIALISE_TYPE_A(Module::, "AST_Module", {
s.item(m_name);
s.item(m_attrs);
s.item(m_extern_crates);
s.item(m_submods);
+ s.item(m_macros);
+
s.item(m_imports);
s.item(m_type_aliases);
@@ -308,11 +342,86 @@ SERIALISE_TYPE(Module::, "AST_Module", { s.item(m_functions);
s.item(m_impls);
})
-void Module::add_ext_crate(::std::string ext_name, ::std::string int_name)
+
+void Module::prescan()
{
- DEBUG("add_ext_crate(\"" << ext_name << "\" as " << int_name << ")");
- m_extern_crates.push_back( Item< ::std::string>( ::std::move(int_name), ::std::move(ext_name), false ) );
+ TRACE_FUNCTION;
+ DEBUG("- '"<<m_name<<"'");
+
+ for( auto& sm_p : m_submods )
+ {
+ sm_p.first.prescan();
+ }
+
+ for( const auto& macro_imp : m_macro_imports )
+ {
+ resolve_macro_import( *(Crate*)0, macro_imp.first, macro_imp.second );
+ }
}
+
+void Module::resolve_macro_import(const Crate& crate, const ::std::string& modname, const ::std::string& macro_name)
+{
+ DEBUG("Import macros from " << modname << " matching '" << macro_name << "'");
+ for( const auto& sm_p : m_submods )
+ {
+ const AST::Module& sm = sm_p.first;
+ if( sm.name() == modname )
+ {
+ DEBUG("Using module");
+ if( macro_name == "" )
+ {
+ for( const auto& macro_p : sm.m_macro_import_res )
+ m_macro_import_res.push_back( macro_p );
+ return ;
+ }
+ else
+ {
+ for( const auto& macro_p : sm.m_macro_import_res )
+ {
+ if( macro_p.name == macro_name ) {
+ m_macro_import_res.push_back( macro_p );
+ return ;
+ }
+ }
+ throw ::std::runtime_error("Macro not in module");
+ }
+ }
+ }
+
+ for( const auto& cr : m_extern_crates )
+ {
+ if( cr.name == modname )
+ {
+ DEBUG("Using crate import " << cr.name << " == '" << cr.data << "'");
+ if( macro_name == "" ) {
+ for( const auto& macro_p : crate.extern_crates().at(cr.data).crate().m_exported_macros )
+ m_macro_import_res.push_back( ItemNS<const MacroRules*>( ::std::string(macro_p.first), &*macro_p.second, false ) );
+ return ;
+ }
+ else {
+ for( const auto& macro_p : crate.extern_crates().at(cr.data).crate().m_exported_macros )
+ {
+ DEBUG("Macro " << macro_p.first);
+ if( macro_p.first == macro_name ) {
+ // TODO: Handle #[macro_export] on extern crate
+ m_macro_import_res.push_back( ItemNS<const MacroRules*>( ::std::string(macro_p.first), &*macro_p.second, false ) );
+ return ;
+ }
+ }
+ throw ::std::runtime_error("Macro not in crate");
+ }
+ }
+ }
+
+ throw ::std::runtime_error( FMT("Could not find sub-module '" << modname << "' for macro import") );
+}
+
+void Module::add_macro_import(const Crate& crate, ::std::string modname, ::std::string macro_name)
+{
+ resolve_macro_import(crate, modname, macro_name);
+ m_macro_imports.insert( ::std::make_pair( move(modname), move(macro_name) ) );
+}
+
void Module::iterate_functions(fcn_visitor_t *visitor, const Crate& crate)
{
for( auto fcn_item : this->m_functions )
diff --git a/src/ast/ast.hpp b/src/ast/ast.hpp index 58bcd389..775ed943 100644 --- a/src/ast/ast.hpp +++ b/src/ast/ast.hpp @@ -10,6 +10,7 @@ #include "../parse/tokentree.hpp"
#include "../types.hpp"
+#include "../macros.hpp"
#include <serialise.hpp>
#include "pattern.hpp"
@@ -108,17 +109,16 @@ public: };
template <typename T>
-struct Item:
- public Serialisable
+struct ItemNS
{
::std::string name;
T data;
bool is_pub;
- Item():
+ ItemNS():
is_pub(false)
{}
- Item(::std::string&& name, T&& data, bool is_pub):
+ ItemNS(::std::string&& name, T&& data, bool is_pub):
name( move(name) ),
data( move(data) ),
is_pub( is_pub )
@@ -128,26 +128,60 @@ struct Item: //friend ::std::ostream& operator<<(::std::ostream& os, const Item& i) {
// return os << (i.is_pub ? "pub " : " ") << i.name << ": " << i.data;
//}
- SERIALISE_TYPE(, "Item", {
- s << name << data << is_pub;
- },{
- s.item(name);
- s.item(data);
- s.item(is_pub);
+};
+
+template <typename T>
+struct Item:
+ public ItemNS<T>,
+ public Serialisable
+{
+ Item():
+ ItemNS<T>()
+ {}
+ Item(::std::string&& name, T&& data, bool is_pub):
+ ItemNS<T>( move(name), move(data), is_pub )
+ {}
+ SERIALISE_TYPE_A(, "Item", {
+ s.item(this->name);
+ s.item(this->data);
+ s.item(this->is_pub);
})
};
+
template <typename T>
using ItemList = ::std::vector<Item<T> >;
typedef Item<TypeRef> StructItem;
-
class Crate;
+class MetaItem;
+
+class MetaItems:
+ public Serialisable
+{
+ ::std::vector<MetaItem> m_items;
+public:
+ MetaItems() {}
+ MetaItems(::std::vector<MetaItem> items):
+ m_items(items)
+ {
+ }
+
+ void push_back(MetaItem i);
+
+ MetaItem* get(const char *name);
+ bool has(const char *name) {
+ return get(name) != 0;
+ }
+
+ SERIALISABLE_PROTOTYPES();
+};
+
class MetaItem:
public Serialisable
{
::std::string m_name;
- ::std::vector<MetaItem> m_items;
+ MetaItems m_sub_items;
::std::string m_str_val;
public:
MetaItem() {}
@@ -157,10 +191,11 @@ public: }
MetaItem(::std::string name, ::std::vector<MetaItem> items):
m_name(name),
- m_items(items)
+ m_sub_items(items)
{
}
+ void mark_used() {}
const ::std::string& name() const { return m_name; }
SERIALISABLE_PROTOTYPES();
@@ -404,7 +439,9 @@ class Module: typedef ::std::vector< Item<Static> > itemlist_static_t;
typedef ::std::vector< Item<Enum> > itemlist_enum_t;
typedef ::std::vector< Item<Struct> > itemlist_struct_t;
-
+ typedef ::std::vector< Item<MacroRules> > itemlist_macros_t;
+ typedef ::std::multimap< ::std::string, ::std::string > macro_imports_t;
+
::std::string m_name;
::std::vector<MetaItem> m_attrs;
itemlist_fcn_t m_functions;
@@ -413,6 +450,11 @@ class Module: ::std::vector<Item<TypeAlias> > m_type_aliases;
itemlist_ext_t m_extern_crates;
+ itemlist_macros_t m_macros;
+ macro_imports_t m_macro_imports; // module => macro
+ ::std::vector< ItemNS<const MacroRules*> > m_macro_import_res; // Vec of imported macros (not serialised)
+
+
itemlist_static_t m_statics;
ItemList<Trait> m_traits;
@@ -425,7 +467,13 @@ public: m_name(name)
{
}
- void add_ext_crate(::std::string ext_name, ::std::string imp_name);
+
+ // Called when module is loaded from a serialised format
+ void prescan();
+
+ void add_ext_crate(::std::string ext_name, ::std::string imp_name) {
+ m_extern_crates.push_back( Item< ::std::string>( move(imp_name), move(ext_name), false ) );
+ }
void add_alias(bool is_public, Path path, ::std::string name) {
m_imports.push_back( Item<Path>( move(name), move(path), is_public) );
}
@@ -456,6 +504,10 @@ public: void add_impl(Impl impl) {
m_impls.push_back( ::std::move(impl) );
}
+ void add_macro(bool is_exported, ::std::string name, MacroRules macro) {
+ m_macros.push_back( Item<MacroRules>( move(name), move(macro), is_exported ) );
+ }
+ void add_macro_import(const Crate& crate, ::std::string mod, ::std::string name);
void add_attr(MetaItem item) {
m_attrs.push_back(item);
@@ -488,8 +540,13 @@ public: const ItemList<Trait>& traits() const { return m_traits; }
const itemlist_enum_t& enums () const { return m_enums; }
const itemlist_struct_t& structs() const { return m_structs; }
+ const itemlist_macros_t& macros() const { return m_macros; }
+ const macro_imports_t& macro_imports() const { return m_macro_imports; }
+ const ::std::vector<ItemNS<const MacroRules*> > macro_imports_res() const { return m_macro_import_res; }
SERIALISABLE_PROTOTYPES();
+private:
+ void resolve_macro_import(const Crate& crate, const ::std::string& modname, const ::std::string& macro_name);
};
class Crate:
@@ -499,6 +556,9 @@ class Crate: public:
Module m_root_module;
::std::map< ::std::string, ExternCrate> m_extern_crates;
+ // Mapping filled by searching for (?visible) macros with is_pub=true
+ ::std::map< ::std::string, const MacroRules*> m_exported_macros;
+
bool m_load_std;
Crate();
@@ -537,6 +597,8 @@ public: Module& root_module() { return m_crate.root_module(); }
const Module& root_module() const { return m_crate.root_module(); }
+ void prescan();
+
SERIALISABLE_PROTOTYPES();
};
diff --git a/src/ast/expr.cpp b/src/ast/expr.cpp index b4cd9240..7d6983f6 100644 --- a/src/ast/expr.cpp +++ b/src/ast/expr.cpp @@ -240,6 +240,9 @@ void operator%(::Serialiser& s, const ExprNode_BinOp::Type t) { _(BITXOR); _(SHL); _(SHR); + _(MULTIPLY); + _(DIVIDE); + _(MODULO); #undef _ } } @@ -268,6 +271,9 @@ NODE(ExprNode_BinOp, { case BITXOR: os << "^"; break; case SHR: os << ">>"; break; case SHL: os << "<<"; break; + case MULTIPLY: os << "*"; break; + case DIVIDE: os << "/"; break; + case MODULO: os << "%"; break; } os << " " << *m_right << ")"; }) diff --git a/src/ast/expr.hpp b/src/ast/expr.hpp index bbb82bde..843abb3b 100644 --- a/src/ast/expr.hpp +++ b/src/ast/expr.hpp @@ -43,15 +43,21 @@ public: struct ExprNode_Block: public ExprNode { + bool m_is_unsafe; ::std::vector< ::std::unique_ptr<ExprNode> > m_nodes; - ExprNode_Block() {} + ExprNode_Block(): + m_is_unsafe(false) + {} ExprNode_Block(::std::vector< ::std::unique_ptr<ExprNode> >&& nodes): + m_is_unsafe(false), m_nodes( move(nodes) ) { } virtual ~ExprNode_Block() override; + void set_unsafe() { m_is_unsafe = true; } + NODE_METHODS(); }; @@ -310,6 +316,10 @@ struct ExprNode_BinOp: enum Type { CMPEQU, CMPNEQU, + CMPLT, + CMPLTE, + CMPGT, + CMPGTE, BITAND, BITOR, @@ -317,6 +327,10 @@ struct ExprNode_BinOp: SHL, SHR, + + MULTIPLY, + DIVIDE, + MODULO, }; Type m_type; diff --git a/src/common.hpp b/src/common.hpp index 59035c4b..545a0adf 100644 --- a/src/common.hpp +++ b/src/common.hpp @@ -14,6 +14,19 @@ #include "include/debug.hpp" #include "include/rustic.hpp" // slice and option +template <typename T> +struct LList +{ + LList* m_prev; + T m_item; + + LList(LList* prev, T item): + m_prev(prev), + m_item( ::std::move(item) ) + { + }; +}; + namespace std { template <typename T> diff --git a/src/dump_as_rust.cpp b/src/dump_as_rust.cpp index 83c7f160..cfe9b5d6 100644 --- a/src/dump_as_rust.cpp +++ b/src/dump_as_rust.cpp @@ -190,8 +190,28 @@ public: m_expr_root = false; switch(n.m_datatype) { + case CORETYPE_INVAL: break; + case CORETYPE_CHAR: + m_os << "'\\u" << ::std::hex << n.m_value << ::std::dec << "'"; + break; + case CORETYPE_F32: + case CORETYPE_F64: + break; + case CORETYPE_U8: + case CORETYPE_U16: + case CORETYPE_U32: + case CORETYPE_U64: + case CORETYPE_UINT: + m_os << "0x" << ::std::hex << n.m_value << ::std::dec; + break; + case CORETYPE_I8: + case CORETYPE_I16: + case CORETYPE_I32: + case CORETYPE_I64: + case CORETYPE_INT: + m_os << n.m_value; + break; } - m_os << "0x" << ::std::hex << n.m_value << ::std::dec; } virtual void visit(AST::ExprNode_StructLiteral& n) override { m_expr_root = false; diff --git a/src/include/debug.hpp b/src/include/debug.hpp index 012ef1bb..4da63192 100644 --- a/src/include/debug.hpp +++ b/src/include/debug.hpp @@ -24,3 +24,27 @@ struct RepeatLitStr } }; +class TraceLog +{ + static unsigned int depth; + const char* m_tag; +public: + TraceLog(const char* tag): m_tag(tag) { indent(); ::std::cout << ">> " << m_tag << ::std::endl; } + ~TraceLog() { outdent(); ::std::cout << "<< " << m_tag << ::std::endl; } +private: + void indent() + { + for(unsigned int i = 0; i < depth; i ++) + ::std::cout << " "; + depth ++; + } + void outdent() + { + depth --; + for(unsigned int i = 0; i < depth; i ++) + ::std::cout << " "; + } +}; +#define TRACE_FUNCTION TraceLog _tf_(__func__) + + diff --git a/src/include/serialise.hpp b/src/include/serialise.hpp index 3949c8ae..1c2b882e 100644 --- a/src/include/serialise.hpp +++ b/src/include/serialise.hpp @@ -20,6 +20,7 @@ class Deserialiser; const char* method_prefix serialise_tag() const { return tag_str; } \ void method_prefix serialise(::Serialiser& s) const { body } \ void method_prefix deserialise(::Deserialiser& s) { des_body } +#define SERIALISE_TYPE_A(method_prefix, tag_str, body) SERIALISE_TYPE(method_prefix, tag_str, body, body) #define SERIALISE_TYPE_S(class_, body) SERIALISE_TYPE(class_::, #class_, body, body) class Serialisable diff --git a/src/macros.cpp b/src/macros.cpp index 7d0c7096..609726a6 100644 --- a/src/macros.cpp +++ b/src/macros.cpp @@ -5,10 +5,17 @@ #include "parse/parseerror.hpp"
#include "parse/tokentree.hpp"
#include "parse/common.hpp"
+#include "ast/ast.hpp"
typedef ::std::map< ::std::string, MacroRules> t_macro_regs;
t_macro_regs g_macro_registrations;
+const LList<AST::Module*>* g_macro_module;
+
+void Macro_SetModule(const LList<AST::Module*>& mod)
+{
+ g_macro_module = &mod;
+}
void Macro_InitDefaults()
{
@@ -46,6 +53,152 @@ void Macro_InitDefaults() rules.push_back(rule);
g_macro_registrations.insert( make_pair(::std::string("try"), rules));
}
+
+ // panic!() "macro"
+ {
+ MacroRule rule;
+ rule.m_pattern.push_back( MacroPatEnt(Token(TOK_NULL), {
+ MacroPatEnt("tt", MacroPatEnt::PAT_TT),
+ } ) );
+ rule.m_contents.push_back( MacroRuleEnt(Token(TOK_PAREN_OPEN)) );
+ rule.m_contents.push_back( MacroRuleEnt(Token(TOK_PAREN_CLOSE)) );
+
+
+ MacroRules rules;
+ rules.push_back(rule);
+ g_macro_registrations.insert( make_pair(::std::string("panic"), rules));
+ }
+}
+
+typedef ::std::map<const char*,TokenTree,cmp_str> single_tts_t;
+typedef ::std::multimap<const char*,TokenTree,cmp_str> repeated_tts_t;
+
+void Macro_HandlePattern(TTStream& lex, const MacroPatEnt& pat, bool rep, single_tts_t& bound_tts, repeated_tts_t& rep_bound_tts)
+{
+ Token tok;
+ TokenTree val;
+ switch(pat.type)
+ {
+ case MacroPatEnt::PAT_TOKEN:
+ DEBUG("Token " << pat.tok);
+ GET_CHECK_TOK(tok, lex, pat.tok.type());
+ break;
+ case MacroPatEnt::PAT_LOOP:
+ //case MacroPatEnt::PAT_OPTLOOP:
+ if( rep )
+ {
+ throw ParseError::BugCheck("Nested macro loop");
+ }
+ else
+ {
+ DEBUG("Loop");
+ for(;;)
+ {
+ DEBUG("Try");
+ TTStream saved = lex;
+ try {
+ Macro_HandlePattern(lex, pat.subpats[0], true, bound_tts, rep_bound_tts);
+ }
+ catch(const ParseError::Base& e) {
+ DEBUG("Breakout");
+ lex = saved;
+ break;
+ }
+ for( unsigned int i = 1; i < pat.subpats.size(); i ++ )
+ {
+ Macro_HandlePattern(lex, pat.subpats[i], true, bound_tts, rep_bound_tts);
+ }
+ DEBUG("succ");
+ if( pat.tok.type() != TOK_NULL )
+ {
+ if( GET_TOK(tok, lex) != pat.tok.type() )
+ {
+ lex.putback(tok);
+ break;
+ }
+ }
+ }
+ DEBUG("Done");
+ }
+ break;
+
+ case MacroPatEnt::PAT_TT:
+ DEBUG("TT");
+ if( GET_TOK(tok, lex) == TOK_EOF )
+ throw ParseError::Unexpected(lex, TOK_EOF);
+ else
+ lex.putback(tok);
+ val = Parse_TT(lex);
+ if(0)
+ case MacroPatEnt::PAT_EXPR:
+ val = Parse_TT_Expr(lex);
+ if(0)
+ case MacroPatEnt::PAT_STMT:
+ val = Parse_TT_Stmt(lex);
+ if(0)
+ case MacroPatEnt::PAT_PATH:
+ val = Parse_TT_Path(lex);
+ if(0)
+ case MacroPatEnt::PAT_BLOCK:
+ val = Parse_TT_Block(lex);
+ if(0)
+ case MacroPatEnt::PAT_IDENT:
+ {
+ GET_CHECK_TOK(tok, lex, TOK_IDENT);
+ val = TokenTree(tok);
+ }
+ if(rep)
+ rep_bound_tts.insert( std::make_pair(pat.name.c_str(), val) );
+ else
+ bound_tts.insert( std::make_pair(pat.name.c_str(), val) );
+ break;
+
+ //default:
+ // throw ParseError::Todo("full macro pattern matching");
+ }
+
+}
+
+MacroExpander Macro_InvokeInt(const MacroRules& rules, TokenTree input)
+{
+ // 2. Check input token tree against possible variants
+ // 3. Bind names
+ // 4. Return expander
+ for(const auto& rule : rules)
+ {
+ Token tok;
+ // Create token stream for input tree
+ TTStream lex(input);
+ if(GET_TOK(tok, lex) == TOK_EOF) {
+ throw ParseError::Unexpected(lex, tok);
+ }
+ ::std::map<const char*,TokenTree,cmp_str> bound_tts;
+ ::std::multimap<const char*,TokenTree,cmp_str> rep_bound_tts;
+ // Parse according to rules
+ bool fail = false;
+ try
+ {
+ for(const auto& pat : rule.m_pattern)
+ {
+ Macro_HandlePattern(lex, pat, false, bound_tts, rep_bound_tts);
+ }
+ }
+ catch(const ParseError::Base& e)
+ {
+ DEBUG("Parse of rule failed - " << e.what());
+ fail = true;
+ }
+ // TODO: Actually check if the final token is the closer to the first
+ if( !fail )
+ {
+ if( GET_TOK(tok, lex) != TOK_EOF)
+ throw ParseError::Unexpected(lex, tok);
+ if( lex.getToken().type() == TOK_EOF )
+ return MacroExpander(rule.m_contents, bound_tts);
+ }
+ }
+ DEBUG("");
+ throw ParseError::Todo("Error when macro fails to match");
}
MacroExpander Macro_Invoke(const char* name, TokenTree input)
@@ -58,58 +211,29 @@ MacroExpander Macro_Invoke(const char* name, TokenTree input) t_macro_regs::iterator macro_reg = g_macro_registrations.find(name);
if( macro_reg != g_macro_registrations.end() )
{
- const MacroRules& rules = macro_reg->second;
- // 2. Check input token tree against possible variants
- // 3. Bind names
- // 4. Return expander
- for(const auto& rule : rules)
+ return Macro_InvokeInt(macro_reg->second, input);
+ }
+
+ for( auto ent = g_macro_module; ent; ent = ent->m_prev )
+ {
+ const AST::Module& mm = *ent->m_item;
+ for( const auto &m : mm.macros() )
{
- Token tok;
- // Create token stream for input tree
- TTStream lex(input);
- if(GET_TOK(tok, lex) == TOK_EOF) {
- throw ParseError::Unexpected(lex, tok);
- }
- ::std::map<const char*,TokenTree,cmp_str> bound_tts;
- // Parse according to rules
- bool fail = false;
- for(const auto& pat : rule.m_pattern)
+ DEBUG("" << m.name);
+ if( m.name == name )
{
- TokenTree val;
- try
- {
- switch(pat.type)
- {
- case MacroPatEnt::PAT_TOKEN:
- GET_CHECK_TOK(tok, lex, pat.tok.type());
- break;
- case MacroPatEnt::PAT_EXPR:
- val = Parse_TT_Expr(lex);
- if(0)
- case MacroPatEnt::PAT_STMT:
- val = Parse_TT_Stmt(lex);
- bound_tts.insert( std::make_pair(pat.name.c_str(), val) );
- break;
- default:
- throw ParseError::Todo("macro pattern matching");
- }
- }
- catch(const ParseError::Base& e)
- {
- fail = true;
- break;
- }
+ return Macro_InvokeInt(m.data, input);
}
- // TODO: Actually check if the final token is the closer to the first
- if( !fail && GET_TOK(tok, lex) == TOK_EOF) {
- throw ParseError::Unexpected(lex, tok);
- }
- if( !fail && lex.getToken().type() == TOK_EOF )
+ }
+
+ for( const auto& mi : mm.macro_imports_res() )
+ {
+ DEBUG("" << mi.name);
+ if( mi.name == name )
{
- return MacroExpander(rule.m_contents, bound_tts);
+ return Macro_InvokeInt(*mi.data, input);
}
}
- throw ParseError::Todo("Error when macro fails to match");
}
throw ParseError::Generic( ::std::string("Macro '") + name + "' was not found" );
@@ -144,3 +268,55 @@ Token MacroExpander::realGetToken() }
return Token(TOK_EOF);
}
+
+SERIALISE_TYPE_S(MacroRule, {
+ s.item(m_pattern);
+ s.item(m_contents);
+});
+
+
+void operator%(Serialiser& s, MacroPatEnt::Type c) {
+ switch(c) {
+ #define _(ns,v) case ns v: s << #v; return;
+ _(MacroPatEnt::,PAT_TOKEN);
+ _(MacroPatEnt::,PAT_TT);
+ _(MacroPatEnt::,PAT_EXPR);
+ _(MacroPatEnt::,PAT_LOOP);
+ //_(MacroPatEnt::,PAT_OPTLOOP);
+ _(MacroPatEnt::,PAT_STMT);
+ _(MacroPatEnt::,PAT_PATH);
+ _(MacroPatEnt::,PAT_BLOCK);
+ _(MacroPatEnt::,PAT_IDENT);
+ #undef _
+ }
+ s << "--TODO--";
+}
+void operator%(::Deserialiser& s, MacroPatEnt::Type& c) {
+ ::std::string n;
+ s.item(n);
+ #define _(v) else if(n == #v) c = MacroPatEnt::v
+ if(0) ;
+ _(PAT_TOKEN);
+ _(PAT_TT);
+ _(PAT_EXPR);
+ _(PAT_LOOP);
+ //_(PAT_OPTLOOP);
+ _(PAT_STMT);
+ _(PAT_PATH);
+ _(PAT_BLOCK);
+ _(PAT_IDENT);
+ else
+ throw ::std::runtime_error( FMT("No conversion for '" << n << "'") );
+ #undef _
+}
+SERIALISE_TYPE_S(MacroPatEnt, {
+ s % type;
+ s.item(name);
+ s.item(tok);
+ s.item(subpats);
+});
+
+SERIALISE_TYPE_S(MacroRuleEnt, {
+ s.item(name);
+ s.item(tok);
+});
diff --git a/src/macros.hpp b/src/macros.hpp index b2aeda53..4de41782 100644 --- a/src/macros.hpp +++ b/src/macros.hpp @@ -9,13 +9,19 @@ class MacroExpander;
-class MacroRuleEnt
+class MacroRuleEnt:
+ public Serialisable
{
friend class MacroExpander;
Token tok;
::std::string name;
public:
+ MacroRuleEnt():
+ tok(TOK_NULL),
+ name("")
+ {
+ }
MacroRuleEnt(Token tok):
tok(tok),
name("")
@@ -25,11 +31,17 @@ public: name(name)
{
}
+
+ SERIALISABLE_PROTOTYPES();
};
-struct MacroPatEnt
+struct MacroPatEnt:
+ public Serialisable
{
- Token tok;
::std::string name;
+ Token tok;
+
+ ::std::vector<MacroPatEnt> subpats;
+
enum Type {
PAT_TOKEN,
PAT_TT,
@@ -38,22 +50,46 @@ struct MacroPatEnt PAT_EXPR,
PAT_STMT,
PAT_BLOCK,
+ PAT_LOOP, // Enables use of subpats
} type;
+ MacroPatEnt():
+ tok(TOK_NULL),
+ type(PAT_TOKEN)
+ {
+ }
+ MacroPatEnt(Token tok):
+ tok(tok),
+ type(PAT_TOKEN)
+ {
+ }
+
MacroPatEnt(::std::string name, Type type):
- tok(),
name(name),
+ tok(),
type(type)
{
}
+
+ MacroPatEnt(Token sep, ::std::vector<MacroPatEnt> ents):
+ tok(sep),
+ subpats( move(ents) ),
+ type(PAT_LOOP)
+ {
+ }
+
+ SERIALISABLE_PROTOTYPES();
};
/// A rule within a macro_rules! blcok
-class MacroRule
+class MacroRule:
+ public Serialisable
{
public:
::std::vector<MacroPatEnt> m_pattern;
::std::vector<MacroRuleEnt> m_contents;
+
+ SERIALISABLE_PROTOTYPES();
};
/// A sigle 'macro_rules!' block
@@ -92,6 +128,7 @@ public: virtual Token realGetToken() override;
};
+extern void Macro_SetModule(const LList<AST::Module*>& mod);
extern MacroExpander Macro_Invoke(const char* name, TokenTree input);
#endif // MACROS_HPP_INCLUDED
diff --git a/src/parse/common.hpp b/src/parse/common.hpp index 950a204d..38ef3c96 100644 --- a/src/parse/common.hpp +++ b/src/parse/common.hpp @@ -24,27 +24,4 @@ extern TypeRef Parse_Type(TokenStream& lex); extern AST::Expr Parse_Expr(TokenStream& lex, bool const_only);
extern AST::Expr Parse_ExprBlock(TokenStream& lex);
-class TraceLog
-{
- static unsigned int depth;
- const char* m_tag;
-public:
- TraceLog(const char* tag): m_tag(tag) { indent(); ::std::cout << ">> " << m_tag << ::std::endl; }
- ~TraceLog() { outdent(); ::std::cout << "<< " << m_tag << ::std::endl; }
-private:
- void indent()
- {
- for(unsigned int i = 0; i < depth; i ++)
- ::std::cout << " ";
- depth ++;
- }
- void outdent()
- {
- depth --;
- for(unsigned int i = 0; i < depth; i ++)
- ::std::cout << " ";
- }
-};
-#define TRACE_FUNCTION TraceLog _tf_(__func__)
-
#endif // PARSE_COMMON_HPP_INCLUDED
diff --git a/src/parse/eTokenType.enum.h b/src/parse/eTokenType.enum.h new file mode 100644 index 00000000..d3f294b5 --- /dev/null +++ b/src/parse/eTokenType.enum.h @@ -0,0 +1,132 @@ +_(TOK_NULL) +_(TOK_EOF) + +_(TOK_NEWLINE) +_(TOK_WHITESPACE) +_(TOK_COMMENT) + +// Value tokens +_(TOK_IDENT) +_(TOK_MACRO) +_(TOK_LIFETIME) +_(TOK_INTEGER) +_(TOK_CHAR) +_(TOK_FLOAT) +_(TOK_STRING) + +_(TOK_CATTR_OPEN) +_(TOK_ATTR_OPEN) + +// Symbols +_(TOK_PAREN_OPEN) _(TOK_PAREN_CLOSE) +_(TOK_BRACE_OPEN) _(TOK_BRACE_CLOSE) +_(TOK_LT) _(TOK_GT) +_(TOK_SQUARE_OPEN) _(TOK_SQUARE_CLOSE) +_(TOK_COMMA) +_(TOK_SEMICOLON) +_(TOK_COLON) +_(TOK_DOUBLE_COLON) +_(TOK_STAR) _(TOK_AMP) +_(TOK_PIPE) + +_(TOK_FATARROW) // => +_(TOK_THINARROW) // -> + +_(TOK_PLUS) _(TOK_DASH) +_(TOK_EXCLAM) +_(TOK_PERCENT) +_(TOK_SLASH) + +_(TOK_DOT) +_(TOK_DOUBLE_DOT) +_(TOK_TRIPLE_DOT) + +_(TOK_EQUAL) +_(TOK_PLUS_EQUAL) +_(TOK_DASH_EQUAL) +_(TOK_PERCENT_EQUAL) +_(TOK_SLASH_EQUAL) +_(TOK_STAR_EQUAL) +_(TOK_AMP_EQUAL) +_(TOK_PIPE_EQUAL) + +_(TOK_DOUBLE_EQUAL) +_(TOK_EXCLAM_EQUAL) +_(TOK_GTE) +_(TOK_LTE) + +_(TOK_DOUBLE_AMP) +_(TOK_DOUBLE_PIPE) +_(TOK_DOUBLE_LT) +_(TOK_DOUBLE_GT) + +_(TOK_DOLLAR) + +_(TOK_QMARK) +_(TOK_AT) +_(TOK_TILDE) +_(TOK_BACKSLASH) +_(TOK_CARET) +_(TOK_BACKTICK) + +// Reserved Words +_(TOK_RWORD_PUB) +_(TOK_RWORD_PRIV) +_(TOK_RWORD_MUT) +_(TOK_RWORD_CONST) +_(TOK_RWORD_STATIC) +_(TOK_RWORD_UNSAFE) +_(TOK_RWORD_EXTERN) + +_(TOK_RWORD_CRATE) +_(TOK_RWORD_MOD) +_(TOK_RWORD_STRUCT) +_(TOK_RWORD_ENUM) +_(TOK_RWORD_TRAIT) +_(TOK_RWORD_FN) +_(TOK_RWORD_USE) +_(TOK_RWORD_IMPL) +_(TOK_RWORD_TYPE) + +_(TOK_RWORD_WHERE) +_(TOK_RWORD_AS) + +_(TOK_RWORD_LET) +_(TOK_RWORD_MATCH) +_(TOK_RWORD_IF) +_(TOK_RWORD_ELSE) +_(TOK_RWORD_LOOP) +_(TOK_RWORD_WHILE) +_(TOK_RWORD_FOR) +_(TOK_RWORD_IN) +_(TOK_RWORD_DO) + +_(TOK_RWORD_CONTINUE) +_(TOK_RWORD_BREAK) +_(TOK_RWORD_RETURN) +_(TOK_RWORD_YIELD) +_(TOK_RWORD_BOX) +_(TOK_RWORD_REF) + +_(TOK_RWORD_FALSE) +_(TOK_RWORD_TRUE) +_(TOK_RWORD_SELF) +_(TOK_RWORD_SUPER) + +_(TOK_RWORD_PROC) +_(TOK_RWORD_MOVE) +_(TOK_RWORD_ONCE) + +_(TOK_RWORD_ABSTRACT) +_(TOK_RWORD_FINAL) +_(TOK_RWORD_PURE) +_(TOK_RWORD_OVERRIDE) +_(TOK_RWORD_VIRTUAL) + +_(TOK_RWORD_ALIGNOF) +_(TOK_RWORD_OFFSETOF) +_(TOK_RWORD_SIZEOF) +_(TOK_RWORD_TYPEOF) + +_(TOK_RWORD_BE) +_(TOK_RWORD_UNSIZED) diff --git a/src/parse/expr.cpp b/src/parse/expr.cpp index 1ee3a2e2..a1b9ed29 100644 --- a/src/parse/expr.cpp +++ b/src/parse/expr.cpp @@ -229,7 +229,7 @@ ExprNodeP Parse_Stmt(TokenStream& lex, bool& opt_semicolon) else {
CHECK_TOK(tok, TOK_EQUAL);
}
- ExprNodeP val = Parse_Expr1(lex);
+ ExprNodeP val = Parse_ExprBlocks(lex);
opt_semicolon = false;
return NEWNODE( AST::ExprNode_LetBinding, ::std::move(pat), ::std::move(type), ::std::move(val) );
}
@@ -244,11 +244,9 @@ ExprNodeP Parse_Stmt(TokenStream& lex, bool& opt_semicolon) case TOK_RWORD_WHILE:
throw ParseError::Todo("while");
break;
- default: {
+ default:
lex.putback(tok);
- opt_semicolon = true;
return Parse_Expr0(lex);
- }
}
}
@@ -369,8 +367,12 @@ ExprNodeP Parse_ExprBlocks(TokenStream& lex) case TOK_RWORD_MATCH:
return Parse_Expr_Match(lex);
case TOK_RWORD_IF:
- // TODO: if let
return Parse_IfStmt(lex);
+ case TOK_RWORD_UNSAFE: {
+ auto rv = Parse_ExprBlockNode(lex);
+ dynamic_cast<AST::ExprNode_Block&>(*rv).set_unsafe();
+ return rv;
+ }
default:
lex.putback(tok);
return Parse_Expr1(lex);
@@ -391,7 +393,7 @@ ExprNodeP cur(TokenStream& lex) \ { \
cases \
default: \
- ::std::cout << "<<" << #cur << ::std::endl; \
+ /*::std::cout << "<<" << #cur << ::std::endl; */\
lex.putback(tok); \
return rv; \
} \
@@ -419,13 +421,17 @@ LEFTASSOC(Parse_Expr3, Parse_Expr4, // 4: Comparisons
LEFTASSOC(Parse_Expr4, Parse_Expr5,
case TOK_LT:
- throw ParseError::Todo("expr - less than");
+ rv = NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::CMPLT, ::std::move(rv), next(lex));
+ break;
case TOK_GT:
- throw ParseError::Todo("expr - greater than");
+ rv = NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::CMPGT, ::std::move(rv), next(lex));
+ break;
case TOK_LTE:
- throw ParseError::Todo("expr - less than or equal");
+ rv = NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::CMPLTE, ::std::move(rv), next(lex));
+ break;
case TOK_GTE:
- throw ParseError::Todo("expr - greater than or equal");
+ rv = NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::CMPGTE, ::std::move(rv), next(lex));
+ break;
)
// 5: Bit OR
LEFTASSOC(Parse_Expr5, Parse_Expr6,
@@ -470,9 +476,11 @@ LEFTASSOC(Parse_Expr10, Parse_Expr11, // 11: Times / Divide / Modulo
LEFTASSOC(Parse_Expr11, Parse_Expr12,
case TOK_STAR:
- throw ParseError::Todo("expr - multiply");
+ rv = NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::MULTIPLY, ::std::move(rv), next(lex));
+ break;
case TOK_SLASH:
- throw ParseError::Todo("expr - divide");
+ rv = NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::DIVIDE, ::std::move(rv), next(lex));
+ break;
case TOK_PERCENT:
throw ParseError::Todo("expr - modulo");
)
@@ -541,6 +549,8 @@ ExprNodeP Parse_ExprFC(TokenStream& lex) ExprNodeP Parse_ExprVal(TokenStream& lex)
{
+ TRACE_FUNCTION;
+
Token tok;
AST::Path path;
switch( GET_TOK(tok, lex) )
@@ -596,21 +606,31 @@ ExprNodeP Parse_ExprVal(TokenStream& lex) throw ParseError::Todo("Float");
case TOK_RWORD_SELF:
return NEWNODE( AST::ExprNode_NamedValue, AST::Path(AST::Path::TagLocal(), "self") );
- case TOK_PAREN_OPEN: {
- ExprNodeP rv = Parse_Expr0(lex);
- if( GET_TOK(tok, lex) == TOK_COMMA ) {
- ::std::vector<ExprNodeP> ents;
- ents.push_back( ::std::move(rv) );
- do {
- if( GET_TOK(tok, lex) == TOK_PAREN_CLOSE )
- break;
- lex.putback(tok);
- ents.push_back( Parse_Expr0(lex) );
- } while( GET_TOK(tok, lex) == TOK_COMMA );
- rv = NEWNODE( AST::ExprNode_Tuple, ::std::move(ents) );
+ case TOK_PAREN_OPEN:
+ if( GET_TOK(tok, lex) == TOK_PAREN_CLOSE )
+ {
+ DEBUG("Unit");
+ return NEWNODE( AST::ExprNode_Tuple, ::std::vector<ExprNodeP>() );
+ }
+ else
+ {
+ lex.putback(tok);
+
+ ExprNodeP rv = Parse_Expr0(lex);
+ if( GET_TOK(tok, lex) == TOK_COMMA ) {
+ ::std::vector<ExprNodeP> ents;
+ ents.push_back( ::std::move(rv) );
+ do {
+ if( GET_TOK(tok, lex) == TOK_PAREN_CLOSE )
+ break;
+ lex.putback(tok);
+ ents.push_back( Parse_Expr0(lex) );
+ } while( GET_TOK(tok, lex) == TOK_COMMA );
+ rv = NEWNODE( AST::ExprNode_Tuple, ::std::move(ents) );
+ }
+ CHECK_TOK(tok, TOK_PAREN_CLOSE);
+ return rv;
}
- CHECK_TOK(tok, TOK_PAREN_CLOSE);
- return rv; }
case TOK_MACRO:
//return NEWNODE( AST::ExprNode_Macro, tok.str(), Parse_TT(lex) );
{
diff --git a/src/parse/lex.cpp b/src/parse/lex.cpp index 43fc12aa..a81086ce 100644 --- a/src/parse/lex.cpp +++ b/src/parse/lex.cpp @@ -41,7 +41,7 @@ static const struct { TOKENT("#", 0), TOKENT("# {
mod.add_alias(false, p, s);
@@ -802,12 +888,16 @@ void Parse_ModRoot(Preproc& lex, AST::Crate& crate, AST::Module& mod, const ::st switch(GET_TOK(tok, lex))
{
case TOK_BRACE_CLOSE:
- if( !nested_module )
+ if( !nested_module ) {
+ DEBUG("Brace close in file root");
throw ParseError::Unexpected(lex, tok);
+ }
return ;
case TOK_EOF:
- if( nested_module )
+ if( nested_module ) {
+ DEBUG("EOF in nested module");
throw ParseError::Unexpected(lex, tok);
+ }
return ;
default:
lex.putback(tok);
@@ -815,7 +905,7 @@ void Parse_ModRoot(Preproc& lex, AST::Crate& crate, AST::Module& mod, const ::st }
// Attributes on the following item
- ::std::vector<AST::MetaItem> meta_items;
+ AST::MetaItems meta_items;
while( GET_TOK(tok, lex) == TOK_ATTR_OPEN )
{
meta_items.push_back( Parse_MetaItem(lex) );
@@ -837,6 +927,18 @@ void Parse_ModRoot(Preproc& lex, AST::Crate& crate, AST::Module& mod, const ::st // The actual item!
switch( GET_TOK(tok, lex) )
{
+ case TOK_MACRO:
+ if( tok.str() == "macro_rules" )
+ {
+ // TODO: Handle #[macro_export]
+ Parse_MacroRules(lex, mod, meta_items);
+ }
+ else
+ {
+ throw ParseError::Todo("module-level syntax extensions");
+ }
+ break;
+
case TOK_RWORD_USE:
Parse_Use(lex, [&mod,is_public](AST::Path p, std::string s) { mod.add_alias(is_public, p, s); });
GET_CHECK_TOK(tok, lex, TOK_SEMICOLON);
@@ -848,24 +950,27 @@ void Parse_ModRoot(Preproc& lex, AST::Crate& crate, AST::Module& mod, const ::st case TOK_STRING:
throw ParseError::Todo("'extern \"C\"'");
break;
- case TOK_RWORD_CRATE:
+ case TOK_RWORD_CRATE: {
+ ::std::string path, name;
+ // TODO: Handle #[macro_use]/#[macro_use(...)]
if( GET_TOK(tok, lex) == TOK_STRING )
{
- ::std::string path = tok.str();
+ path = tok.str();
GET_CHECK_TOK(tok, lex, TOK_RWORD_AS);
GET_CHECK_TOK(tok, lex, TOK_IDENT);
- ::std::string name = tok.str();
-
- mod.add_ext_crate(path, name);
+ name = tok.str();
}
else if( tok.type() == TOK_IDENT )
{
- ::std::string name = tok.str();
-
- mod.add_ext_crate(name, name);
+ path = name = tok.str();
}
+ else
+ {
+ throw ParseError::Unexpected(lex, tok);
+ }
+ mod.add_ext_crate(path, name);
GET_CHECK_TOK(tok, lex, TOK_SEMICOLON);
- break;
+ break; }
default:
throw ParseError::Unexpected(lex, tok);
}
@@ -938,7 +1043,7 @@ void Parse_ModRoot(Preproc& lex, AST::Crate& crate, AST::Module& mod, const ::st switch( GET_TOK(tok, lex) )
{
case TOK_BRACE_OPEN:
- Parse_ModRoot(lex, crate, submod, "-");
+ Parse_ModRoot(lex, crate, submod, &modstack, "-");
break;
case TOK_SEMICOLON:
DEBUG("Mod = " << name << ", curpath = " << path);
@@ -960,13 +1065,13 @@ void Parse_ModRoot(Preproc& lex, AST::Crate& crate, AST::Module& mod, const ::st {
// Load from dir
Preproc sub_lex(newpath_dir + "mod.rs");
- Parse_ModRoot(sub_lex, crate, submod, newpath_dir);
+ Parse_ModRoot(sub_lex, crate, submod, &modstack, newpath_dir);
}
else if( ifs_file.is_open() )
{
// Load from file
Preproc sub_lex(newpath_file);
- Parse_ModRoot(sub_lex, crate, submod, newpath_file);
+ Parse_ModRoot(sub_lex, crate, submod, &modstack, newpath_file);
}
else
{
@@ -979,6 +1084,7 @@ void Parse_ModRoot(Preproc& lex, AST::Crate& crate, AST::Module& mod, const ::st throw ParseError::Generic("Expected { or ; after module name");
}
mod.add_submod(is_public, ::std::move(submod));
+ Macro_SetModule(modstack);
break; }
default:
@@ -1025,13 +1131,14 @@ AST::Crate Parse_Crate(::std::string mainfile) // Load the standard library (add 'extern crate std;')
crate.load_extern_crate("std");
rootmod.add_ext_crate("std", "std");
+ rootmod.add_macro_import(crate, "std", "");
// Prelude imports are handled in Parse_ModRoot
}
// Include the std if the 'no_std' attribute was absent
// - First need to load the std macros, then can import the prelude
- Parse_ModRoot(lex, crate, rootmod, mainpath);
+ Parse_ModRoot(lex, crate, rootmod, NULL, mainpath);
return crate;
}
diff --git a/src/parse/tokentree.hpp b/src/parse/tokentree.hpp index f7094357..d69a7a12 100644 --- a/src/parse/tokentree.hpp +++ b/src/parse/tokentree.hpp @@ -39,6 +39,8 @@ public: TTStream(const TokenTree& input_tt);
~TTStream();
+ TTStream& operator=(const TTStream& x) { m_stack = x.m_stack; return *this; }
+
virtual Position getPosition() const override;
protected:
@@ -48,5 +50,7 @@ protected: extern TokenTree Parse_TT(TokenStream& lex);
extern TokenTree Parse_TT_Expr(TokenStream& lex);
extern TokenTree Parse_TT_Stmt(TokenStream& lex);
+extern TokenTree Parse_TT_Block(TokenStream& lex);
+extern TokenTree Parse_TT_Path(TokenStream& lex);
#endif // TOKENTREE_HPP_INCLUDED
|