summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile6
-rw-r--r--samples/std.rs17
-rw-r--r--src/ast/ast.cpp155
-rw-r--r--src/ast/ast.hpp92
-rw-r--r--src/ast/expr.cpp6
-rw-r--r--src/ast/expr.hpp16
-rw-r--r--src/common.hpp13
-rw-r--r--src/dump_as_rust.cpp22
-rw-r--r--src/include/debug.hpp24
-rw-r--r--src/include/serialise.hpp1
-rw-r--r--src/macros.cpp268
-rw-r--r--src/macros.hpp47
-rw-r--r--src/parse/common.hpp23
-rw-r--r--src/parse/eTokenType.enum.h132
-rw-r--r--src/parse/expr.cpp72
-rw-r--r--src/parse/lex.cpp176
-rw-r--r--src/parse/lex.hpp139
-rw-r--r--src/parse/preproc.cpp5
-rw-r--r--src/parse/root.cpp161
-rw-r--r--src/parse/tokentree.hpp4
20 files changed, 941 insertions, 438 deletions
diff --git a/Makefile b/Makefile
index e2bec3f9..6561e33e 100644
--- a/Makefile
+++ b/Makefile
@@ -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("#![",TOK_CATTR_OPEN),
TOKENT("#[", TOK_ATTR_OPEN),
- //TOKENT("$", 0),
+ TOKENT("$", TOK_DOLLAR),
TOKENT("%" , TOK_PERCENT),
TOKENT("%=", TOK_PERCENT_EQUAL),
TOKENT("&" , TOK_AMP),
@@ -194,8 +194,6 @@ bool issym(char ch)
return true;
if( ch == '_' )
return true;
- if( ch == '$' )
- return true;
return false;
}
@@ -209,7 +207,7 @@ Token Lexer::getToken()
return Token(TOK_NEWLINE);
if( isspace(ch) )
{
- while( isspace(this->getc()) )
+ while( isspace(ch = this->getc()) && ch != '\n' )
;
this->putback();
return Token(TOK_WHITESPACE);
@@ -358,9 +356,16 @@ Token Lexer::getToken()
return Token((uint64_t)val, CORETYPE_CHAR);
}
break; }
- case DOUBLEQUOTE:
- throw ParseError::Todo("Strings");
- break;
+ case DOUBLEQUOTE: {
+ ::std::string str;
+ while( (ch = this->getc()) != '"' )
+ {
+ if( ch == '\\' )
+ ch = this->parseEscape('"');
+ str.push_back(ch);
+ }
+ return Token(TOK_STRING, str);
+ }
default:
assert(!"bugcheck");
}
@@ -449,140 +454,37 @@ const char* Token::typestr(enum eTokenType type)
{
switch(type)
{
- case TOK_NULL: return "TOK_NULL";
- case TOK_EOF: return "TOK_EOF";
-
- case TOK_NEWLINE: return "TOK_NEWLINE";
- case TOK_WHITESPACE: return "TOK_WHITESPACE";
- case TOK_COMMENT: return "TOK_COMMENT";
-
- // Value tokens
- case TOK_IDENT: return "TOK_IDENT";
- case TOK_MACRO: return "TOK_MACRO";
- case TOK_LIFETIME: return "TOK_LIFETIME";
- case TOK_INTEGER: return "TOK_INTEGER";
- case TOK_CHAR: return "TOK_CHAR";
- case TOK_FLOAT: return "TOK_FLOAT";
- case TOK_STRING: return "TOK_STRING";
-
- case TOK_CATTR_OPEN: return "TOK_CATTR_OPEN";
- case TOK_ATTR_OPEN: return "TOK_ATTR_OPEN";
-
- // Symbols
- case TOK_PAREN_OPEN: return "TOK_PAREN_OPEN"; case TOK_PAREN_CLOSE: return "TOK_PAREN_CLOSE";
- case TOK_BRACE_OPEN: return "TOK_BRACE_OPEN"; case TOK_BRACE_CLOSE: return "TOK_BRACE_CLOSE";
- case TOK_LT: return "TOK_LT"; case TOK_GT: return "TOK_GT";
- case TOK_SQUARE_OPEN: return "TOK_SQUARE_OPEN";case TOK_SQUARE_CLOSE: return "TOK_SQUARE_CLOSE";
- case TOK_COMMA: return "TOK_COMMA";
- case TOK_SEMICOLON: return "TOK_SEMICOLON";
- case TOK_COLON: return "TOK_COLON";
- case TOK_DOUBLE_COLON: return "TOK_DOUBLE_COLON";
- case TOK_STAR: return "TOK_STAR"; case TOK_AMP: return "TOK_AMP";
- case TOK_PIPE: return "TOK_PIPE";
-
- case TOK_FATARROW: return "TOK_FATARROW"; // =>
- case TOK_THINARROW: return "TOK_THINARROW"; // ->
-
- case TOK_PLUS: return "TOK_PLUS"; case TOK_DASH: return "TOK_DASH";
- case TOK_EXCLAM: return "TOK_EXCLAM";
- case TOK_PERCENT: return "TOK_PERCENT";
- case TOK_SLASH: return "TOK_SLASH";
-
- case TOK_DOT: return "TOK_DOT";
- case TOK_DOUBLE_DOT: return "TOK_DOUBLE_DOT";
- case TOK_TRIPLE_DOT: return "TOK_TRIPLE_DOT";
-
- case TOK_EQUAL: return "TOK_EQUAL";
- case TOK_PLUS_EQUAL: return "TOK_PLUS_EQUAL";
- case TOK_DASH_EQUAL: return "TOK_DASH_EQUAL";
- case TOK_PERCENT_EQUAL: return "TOK_PERCENT_EQUAL";
- case TOK_SLASH_EQUAL: return "TOK_SLASH_EQUAL";
- case TOK_STAR_EQUAL: return "TOK_STAR_EQUAL";
- case TOK_AMP_EQUAL: return "TOK_AMP_EQUAL";
- case TOK_PIPE_EQUAL: return "TOK_PIPE_EQUAL";
-
- case TOK_DOUBLE_EQUAL: return "TOK_DOUBLE_EQUAL";
- case TOK_EXCLAM_EQUAL: return "TOK_EXCLAM_EQUAL";
- case TOK_GTE: return "TOK_GTE";
- case TOK_LTE: return "TOK_LTE";
-
- case TOK_DOUBLE_AMP: return "TOK_DOUBLE_AMP";
- case TOK_DOUBLE_PIPE: return "TOK_DOUBLE_PIPE";
- case TOK_DOUBLE_LT: return "TOK_DOUBLE_LT";
- case TOK_DOUBLE_GT: return "TOK_DOUBLE_GT";
-
- case TOK_QMARK: return "TOK_QMARK";
- case TOK_AT: return "TOK_AT";
- case TOK_TILDE: return "TOK_TILDE";
- case TOK_BACKSLASH: return "TOK_BACKSLASH";
- case TOK_CARET: return "TOK_CARET";
- case TOK_BACKTICK: return "TOK_BACKTICK";
-
- // Reserved Words
- case TOK_RWORD_PUB: return "TOK_RWORD_PUB";
- case TOK_RWORD_PRIV: return "TOK_RWORD_PRIV";
- case TOK_RWORD_MUT: return "TOK_RWORD_MUT";
- case TOK_RWORD_CONST: return "TOK_RWORD_CONST";
- case TOK_RWORD_STATIC: return "TOK_RWORD_STATIC";
- case TOK_RWORD_UNSAFE: return "TOK_RWORD_UNSAFE";
- case TOK_RWORD_EXTERN: return "TOK_RWORD_EXTERN";
-
- case TOK_RWORD_CRATE: return "TOK_RWORD_CRATE";
- case TOK_RWORD_MOD: return "TOK_RWORD_MOD";
- case TOK_RWORD_STRUCT: return "TOK_RWORD_STRUCT";
- case TOK_RWORD_ENUM: return "TOK_RWORD_ENUM";
- case TOK_RWORD_TRAIT: return "TOK_RWORD_TRAIT";
- case TOK_RWORD_FN: return "TOK_RWORD_FN";
- case TOK_RWORD_USE: return "TOK_RWORD_USE";
- case TOK_RWORD_IMPL: return "TOK_RWORD_IMPL";
- case TOK_RWORD_TYPE: return "TOK_RWORD_TYPE";
-
- case TOK_RWORD_WHERE: return "TOK_RWORD_WHERE";
- case TOK_RWORD_AS: return "TOK_RWORD_AS";
-
- case TOK_RWORD_LET: return "TOK_RWORD_LET";
- case TOK_RWORD_MATCH: return "TOK_RWORD_MATCH";
- case TOK_RWORD_IF: return "TOK_RWORD_IF";
- case TOK_RWORD_ELSE: return "TOK_RWORD_ELSE";
- case TOK_RWORD_LOOP: return "TOK_RWORD_LOOP";
- case TOK_RWORD_WHILE: return "TOK_RWORD_WHILE";
- case TOK_RWORD_FOR: return "TOK_RWORD_FOR";
- case TOK_RWORD_IN: return "TOK_RWORD_IN";
- case TOK_RWORD_DO: return "TOK_RWORD_DO";
-
- case TOK_RWORD_CONTINUE: return "TOK_RWORD_CONTINUE";
- case TOK_RWORD_BREAK: return "TOK_RWORD_BREAK";
- case TOK_RWORD_RETURN: return "TOK_RWORD_RETURN";
- case TOK_RWORD_YIELD: return "TOK_RWORD_YIELD";
- case TOK_RWORD_BOX: return "TOK_RWORD_BOX";
- case TOK_RWORD_REF: return "TOK_RWORD_REF";
-
- case TOK_RWORD_FALSE: return "TOK_RWORD_FALSE";
- case TOK_RWORD_TRUE: return "TOK_RWORD_TRUE";
- case TOK_RWORD_SELF: return "TOK_RWORD_SELF";
- case TOK_RWORD_SUPER: return "TOK_RWORD_SUPER";
-
- case TOK_RWORD_PROC: return "TOK_RWORD_PROC";
- case TOK_RWORD_MOVE: return "TOK_RWORD_MOVE";
- case TOK_RWORD_ONCE: return "TOK_RWORD_ONCE";
-
- case TOK_RWORD_ABSTRACT: return "TOK_RWORD_ABSTRACT";
- case TOK_RWORD_FINAL: return "TOK_RWORD_FINAL";
- case TOK_RWORD_PURE: return "TOK_RWORD_PURE";
- case TOK_RWORD_OVERRIDE: return "TOK_RWORD_OVERRIDE";
- case TOK_RWORD_VIRTUAL: return "TOK_RWORD_VIRTUAL";
-
- case TOK_RWORD_ALIGNOF: return "TOK_RWORD_ALIGNOF";
- case TOK_RWORD_OFFSETOF: return "TOK_RWORD_OFFSETOF";
- case TOK_RWORD_SIZEOF: return "TOK_RWORD_SIZEOF";
- case TOK_RWORD_TYPEOF: return "TOK_RWORD_TYPEOF";
-
- case TOK_RWORD_BE: return "TOK_RWORD_BE";
- case TOK_RWORD_UNSIZED: return "TOK_RWORD_UNSIZED";
+ #define _(t) case t: return #t;
+ #include "eTokenType.enum.h"
+ #undef _
}
return ">>BUGCHECK: BADTOK<<";
}
+enum eTokenType Token::typefromstr(const ::std::string& s)
+{
+ if(s == "")
+ return TOK_NULL;
+ #define _(t) else if( s == #t ) return t;
+ #include "eTokenType.enum.h"
+ #undef _
+ else
+ return TOK_NULL;
+}
+
+void operator%(Serialiser& s, enum eTokenType c) {
+ s << Token::typestr(c);
+}
+void operator%(::Deserialiser& s, enum eTokenType& c) {
+ ::std::string n;
+ s.item(n);
+ c = Token::typefromstr(n);
+}
+SERIALISE_TYPE_S(Token, {
+ s % m_type;
+ s.item(m_str);
+});
+
::std::ostream& operator<<(::std::ostream& os, const Token& tok)
{
os << Token::typestr(tok.type()) << "\"" << tok.str() << "\"";
diff --git a/src/parse/lex.hpp b/src/parse/lex.hpp
index 38f730c5..d28b0afd 100644
--- a/src/parse/lex.hpp
+++ b/src/parse/lex.hpp
@@ -7,139 +7,13 @@
enum eTokenType
{
- 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_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,
+ #define _(t) t,
+ #include "eTokenType.enum.h"
+ #undef _
};
-class Token
+class Token:
+ public Serialisable
{
enum eTokenType m_type;
::std::string m_str;
@@ -162,6 +36,9 @@ public:
double floatval() const { return m_floatval; }
static const char* typestr(enum eTokenType type);
+ static eTokenType typefromstr(const ::std::string& s);
+
+ SERIALISABLE_PROTOTYPES();
};
extern ::std::ostream& operator<<(::std::ostream& os, const Token& tok);
diff --git a/src/parse/preproc.cpp b/src/parse/preproc.cpp
index c8f0aeea..781ea8bc 100644
--- a/src/parse/preproc.cpp
+++ b/src/parse/preproc.cpp
@@ -25,12 +25,15 @@ Token Preproc::getTokenInt()
{
case TOK_NEWLINE:
m_line ++;
+ //DEBUG("m_line = " << m_line << " (NL)");
continue;
case TOK_WHITESPACE:
continue;
case TOK_COMMENT: {
::std::string comment = tok.str();
- m_line += ::std::count(comment.begin(), comment.end(), '\n');
+ unsigned int c = ::std::count(comment.begin(), comment.end(), '\n');
+ m_line += c;
+ //DEBUG("m_line = " << m_line << " (comment w/ "<<c<<")");
continue; }
default:
return tok;
diff --git a/src/parse/root.cpp b/src/parse/root.cpp
index ef04ea2f..6b857ff9 100644
--- a/src/parse/root.cpp
+++ b/src/parse/root.cpp
@@ -4,6 +4,7 @@
#include "../ast/ast.hpp"
#include "parseerror.hpp"
#include "common.hpp"
+#include "../macros.hpp"
#include <cassert>
unsigned int TraceLog::depth = 0;
@@ -72,6 +73,7 @@ AST::Path Parse_PathFrom(TokenStream& lex, AST::Path path, eParsePathGenericMode
path.append( AST::PathNode(component, params) );
break;
}
+ GET_TOK(tok, lex);
}
path.append( AST::PathNode(component, params) );
}
@@ -145,9 +147,14 @@ TypeRef Parse_Type(TokenStream& lex)
case TOK_DOUBLE_COLON:
// Path with generics
return TypeRef(TypeRef::TagPath(), Parse_Path(lex, true, PATH_GENERIC_TYPE));
- case TOK_AMP:
+ case TOK_AMP: {
+ ::std::string lifetime;
// Reference
tok = lex.getToken();
+ if( tok.type() == TOK_LIFETIME ) {
+ lifetime = tok.str();
+ tok = lex.getToken();
+ }
if( tok.type() == TOK_RWORD_MUT ) {
// Mutable reference
return TypeRef(TypeRef::TagReference(), true, Parse_Type(lex));
@@ -158,6 +165,7 @@ TypeRef Parse_Type(TokenStream& lex)
return TypeRef(TypeRef::TagReference(), false, Parse_Type(lex));
}
throw ParseError::BugCheck("Reached end of Parse_Type:AMP");
+ }
case TOK_STAR:
// Pointer
switch( GET_TOK(tok, lex) )
@@ -367,7 +375,7 @@ AST::Function Parse_FunctionDef(TokenStream& lex, bool allow_no_code=false)
return AST::Function(params, fcn_class, ret_type, args, code);
}
-AST::TypeAlias Parse_TypeAlias(TokenStream& lex, const ::std::vector<AST::MetaItem> meta_items)
+AST::TypeAlias Parse_TypeAlias(TokenStream& lex, const AST::MetaItems meta_items)
{
TRACE_FUNCTION;
@@ -392,7 +400,7 @@ AST::TypeAlias Parse_TypeAlias(TokenStream& lex, const ::std::vector<AST::MetaIt
return AST::TypeAlias( ::std::move(params), ::std::move(type) );
}
-void Parse_Struct(AST::Module& mod, TokenStream& lex, const bool is_public, const ::std::vector<AST::MetaItem> meta_items)
+void Parse_Struct(AST::Module& mod, TokenStream& lex, const bool is_public, const AST::MetaItems meta_items)
{
TRACE_FUNCTION;
@@ -458,7 +466,7 @@ void Parse_Struct(AST::Module& mod, TokenStream& lex, const bool is_public, cons
}
}
-AST::Trait Parse_TraitDef(TokenStream& lex, const ::std::vector<AST::MetaItem> meta_items)
+AST::Trait Parse_TraitDef(TokenStream& lex, const AST::MetaItems& meta_items)
{
TRACE_FUNCTION;
@@ -538,7 +546,7 @@ AST::Trait Parse_TraitDef(TokenStream& lex, const ::std::vector<AST::MetaItem> m
return trait;
}
-AST::Enum Parse_EnumDef(TokenStream& lex, const ::std::vector<AST::MetaItem> meta_items)
+AST::Enum Parse_EnumDef(TokenStream& lex, const AST::MetaItems meta_items)
{
TRACE_FUNCTION;
@@ -763,20 +771,98 @@ void Parse_Use(Preproc& lex, ::std::function<void(AST::Path, ::std::string)> fcn
fcn(path, name);
}
-void Parse_ModRoot(Preproc& lex, AST::Crate& crate, AST::Module& mod, const ::std::string& path)
+MacroRule Parse_MacroRules_Var(Preproc& lex)
{
TRACE_FUNCTION;
+ Token tok;
+
+ MacroRule rule;
+
+ // Pattern
+ enum eTokenType close;
+ switch(GET_TOK(tok, lex))
+ {
+ case TOK_BRACE_OPEN: close = TOK_BRACE_CLOSE; break;
+ case TOK_PAREN_OPEN: close = TOK_PAREN_CLOSE; break;
+ default:
+ throw ParseError::Unexpected(lex, tok);
+ }
+ // - Pattern entries
+ while( GET_TOK(tok, lex) != close )
+ {
+ switch(tok.type())
+ {
+ case TOK_DOLLAR:
+ switch( GET_TOK(tok, lex) )
+ {
+ case TOK_IDENT: {
+ ::std::string name = tok.str();
+ GET_CHECK_TOK(tok, lex, TOK_COLON);
+ GET_CHECK_TOK(tok, lex, TOK_IDENT);
+ ::std::string type = tok.str();
+ if( type == "expr" )
+ rule.m_pattern.push_back( MacroPatEnt(name, MacroPatEnt::PAT_EXPR) );
+ else
+ throw ParseError::Generic(FMT("Unknown fragment type " << type));
+ break; }
+ case TOK_PAREN_OPEN:
+ throw ParseError::Todo("Repetitions in macro_rules");
+ default:
+ throw ParseError::Unexpected(lex, tok);
+ }
+ break;
+ default:
+ rule.m_pattern.push_back( MacroPatEnt(tok) );
+ break;
+ }
+ }
+
+ GET_CHECK_TOK(tok, lex, TOK_FATARROW);
+
+ // Replacement
+ auto rep = Parse_TT(lex);
+
+ return rule;
+}
- const bool nested_module = (path.size() == 0); // 'mod name { code }', as opposed to 'mod name;'
+void Parse_MacroRules(Preproc& lex, AST::Module& mod, AST::MetaItems& meta_items)
+{
+ TRACE_FUNCTION;
+
+ Token tok;
+
+ GET_CHECK_TOK(tok, lex, TOK_IDENT);
+ ::std::string name = tok.str();
+
+ GET_CHECK_TOK(tok, lex, TOK_BRACE_OPEN);
+
+ ::std::vector<MacroRule> rules;
+ while( GET_TOK(tok, lex) != TOK_BRACE_CLOSE )
+ {
+ lex.putback(tok);
+
+ rules.push_back( Parse_MacroRules_Var(lex) );
+ GET_CHECK_TOK(tok, lex, TOK_SEMICOLON);
+ }
+
+ bool is_pub = meta_items.has("macro_export");
+
+ 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)
+{
+ 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(AST::Path::TagAbsolute());
- prelude_path.append( AST::PathNode("std", {}) );
- prelude_path.append( AST::PathNode("prelude", {}) );
- prelude_path.append( AST::PathNode("v1", {}) );
+ 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);
@@ -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