summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--src/ast/pattern.hpp7
-rw-r--r--src/common.hpp22
-rw-r--r--src/macros.cpp18
-rw-r--r--src/parse/expr.cpp4
-rw-r--r--src/parse/root.cpp127
6 files changed, 126 insertions, 54 deletions
diff --git a/Makefile b/Makefile
index 95358ea0..0919e5d2 100644
--- a/Makefile
+++ b/Makefile
@@ -31,7 +31,7 @@ clean:
output/%.ast: samples/%.rs $(BIN)
@mkdir -p output/
- $(DBG) $(BIN) $< --emit ast -o $@ 2>&1 | tee $@_dbg.txt ; test $${PIPESTATUS[0]} -eq 0
+ $(DBG) $(BIN) $< --emit ast -o $@ 2>&1 | tee $@_dbg.txt | tail -n 20 ; test $${PIPESTATUS[0]} -eq 0
TEST_FILE = ../../../Source/rust/rustc-nightly/src/libcore/lib.rs
test: $(TEST_FILE) $(BIN) output/std.ast output/log.ast output/env_logger.ast output/getopts.ast
diff --git a/src/ast/pattern.hpp b/src/ast/pattern.hpp
index 7544d53c..a2f9a24b 100644
--- a/src/ast/pattern.hpp
+++ b/src/ast/pattern.hpp
@@ -69,6 +69,13 @@ public:
m_class(ANY)
{}
+ // Wildcard = '..', distinct from '_'
+ // TODO: Store wildcard as a different pattern type
+ struct TagWildcard {};
+ Pattern(TagWildcard):
+ m_class(ANY)
+ {}
+
struct TagBind {};
Pattern(TagBind, ::std::string name):
m_class(ANY),
diff --git a/src/common.hpp b/src/common.hpp
index 545a0adf..01c710b9 100644
--- a/src/common.hpp
+++ b/src/common.hpp
@@ -62,6 +62,12 @@ inline ::std::ostream& operator<<(::std::ostream& os, const ::std::vector<T>& v)
}
template <typename T, typename U>
+inline ::std::ostream& operator<<(::std::ostream& os, const ::std::pair<T,U>& v) {
+ os << "(" << v.first << ", " << v.second << ")";
+ return os;
+}
+
+template <typename T, typename U>
inline ::std::ostream& operator<<(::std::ostream& os, const ::std::map<T,U>& v) {
if( v.size() > 0 )
{
@@ -77,6 +83,22 @@ inline ::std::ostream& operator<<(::std::ostream& os, const ::std::map<T,U>& v)
return os;
}
+template <typename T, typename U, class Cmp>
+inline ::std::ostream& operator<<(::std::ostream& os, const ::std::multimap<T,U,Cmp>& v) {
+ if( v.size() > 0 )
+ {
+ bool is_first = true;
+ for( const auto& i : v )
+ {
+ if(!is_first)
+ os << ", ";
+ is_first = false;
+ os << i.first << ": " << i.second;
+ }
+ }
+ return os;
+}
+
}
#endif
diff --git a/src/macros.cpp b/src/macros.cpp
index 3b6147e3..45175620 100644
--- a/src/macros.cpp
+++ b/src/macros.cpp
@@ -27,7 +27,13 @@ public:
struct cmp_mk {
bool operator()(const t_mapping_key& a, const t_mapping_key& b) const {
- return a.first < b.first || ::std::strcmp(a.second, b.second) < 0;
+ if( a.first < b.first )
+ return true;
+ if( a.first == b.first ) {
+ if( ::std::strcmp(a.second, b.second) < 0 )
+ return true;
+ }
+ return false;
}
};
typedef ::std::multimap<t_mapping_key, TokenTree, cmp_mk> t_mappings;
@@ -281,6 +287,10 @@ void Macro_HandlePattern(TTStream& lex, const MacroPatEnt& pat, unsigned int lay
//GET_CHECK_TOK(tok, lex, close);
GET_CHECK_TOK(tok, lex, TOK_EOF);
DEBUG( rule.m_contents.size() << " rule contents bound to " << bound_tts.size() << " values - " << name );
+ for( const auto& v : bound_tts )
+ {
+ DEBUG("- " << v.first.first << "#" << v.first.second << " = [" << v.second << "]");
+ }
return ::std::unique_ptr<TokenStream>( (TokenStream*)new MacroExpander(olex, rule.m_contents, bound_tts, g_crate_path_tt) );
}
catch(const ParseError::Base& e)
@@ -399,9 +409,11 @@ Token MacroExpander::realGetToken()
{
// - Name
const size_t iter_idx = m_offsets.back().second;
+ DEBUG("m_mappings = " << m_mappings);
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) );
+ if( tt_i.first == tt_i.second ) {
+ throw ParseError::Generic(*this, FMT("Cannot find mapping name: " << ent.name << " for layer " << layer) );
+ }
size_t i = 0;
for( auto it = tt_i.first; it != tt_i.second; it ++ )
diff --git a/src/parse/expr.cpp b/src/parse/expr.cpp
index 88bb021f..e568bcbb 100644
--- a/src/parse/expr.cpp
+++ b/src/parse/expr.cpp
@@ -160,6 +160,8 @@ AST::Pattern Parse_PatternReal1(TokenStream& lex)
{
case TOK_UNDERSCORE:
return AST::Pattern( );
+ case TOK_DOUBLE_DOT:
+ return AST::Pattern( AST::Pattern::TagWildcard() );
case TOK_AMP:
DEBUG("Ref");
if( GET_TOK(tok, lex) == TOK_RWORD_MUT )
@@ -326,8 +328,6 @@ ExprNodeP Parse_ExprBlockNode(TokenStream& lex)
/// - use/extern/const/let
ExprNodeP Parse_ExprBlockLine(TokenStream& lex, bool *expect_end)
{
- TRACE_FUNCTION;
-
Token tok;
if( GET_TOK(tok, lex) == TOK_LIFETIME )
diff --git a/src/parse/root.cpp b/src/parse/root.cpp
index acd0e9e9..e721017a 100644
--- a/src/parse/root.cpp
+++ b/src/parse/root.cpp
@@ -607,7 +607,6 @@ AST::Function Parse_FunctionDef(TokenStream& lex, ::std::string abi, AST::MetaIt
AST::Function Parse_FunctionDefWithCode(TokenStream& lex, ::std::string abi, AST::MetaItems attrs, bool allow_self)
{
- TRACE_FUNCTION;
Token tok;
auto ret = Parse_FunctionDef(lex, abi, ::std::move(attrs), allow_self, false);
GET_CHECK_TOK(tok, lex, TOK_BRACE_OPEN);
@@ -946,6 +945,9 @@ AST::MetaItem Parse_MetaItem(TokenStream& lex)
}
}
+AST::Impl Parse_Impl(TokenStream& lex, bool is_unsafe/*=false*/);
+void Parse_Impl_Item(TokenStream& lex, AST::Impl& impl);
+
AST::Impl Parse_Impl(TokenStream& lex, bool is_unsafe/*=false*/)
{
TRACE_FUNCTION;
@@ -1018,59 +1020,88 @@ AST::Impl Parse_Impl(TokenStream& lex, bool is_unsafe/*=false*/)
// A sequence of method implementations
while( GET_TOK(tok, lex) != TOK_BRACE_CLOSE )
{
- AST::MetaItems item_attrs;
- while( tok.type() == TOK_ATTR_OPEN )
+ lex.putback(tok);
+ Parse_Impl_Item(lex, impl);
+ }
+
+ return impl;
+}
+
+void Parse_Impl_Item(TokenStream& lex, AST::Impl& impl)
+{
+ Token tok;
+
+ GET_TOK(tok, lex);
+
+ AST::MetaItems item_attrs;
+ while( tok.type() == TOK_ATTR_OPEN )
+ {
+ item_attrs.push_back( Parse_MetaItem(lex) );
+ GET_CHECK_TOK(tok, lex, TOK_SQUARE_CLOSE);
+ GET_TOK(tok, lex);
+ }
+
+ bool is_public = false;
+ if(tok.type() == TOK_RWORD_PUB) {
+ is_public = true;
+ GET_TOK(tok, lex);
+ }
+
+ if(tok.type() == TOK_RWORD_UNSAFE) {
+ item_attrs.push_back( AST::MetaItem("#UNSAFE") );
+ GET_TOK(tok, lex);
+ }
+
+ ::std::string abi = "rust";
+ switch(tok.type())
+ {
+ case TOK_MACRO:
{
- item_attrs.push_back( Parse_MetaItem(lex) );
- GET_CHECK_TOK(tok, lex, TOK_SQUARE_CLOSE);
- GET_TOK(tok, lex);
- }
-
- bool is_public = false;
- if(tok.type() == TOK_RWORD_PUB) {
- is_public = true;
- GET_TOK(tok, lex);
+ TokenTree tt = Parse_TT(lex, true);
+ if( tt.is_token() ) {
+ DEBUG("TT was a single token (not a sub-tree)");
+ throw ParseError::Unexpected(lex, tt.tok());
+ }
+
+ auto expanded_macro = Macro_Invoke(lex, tok.str().c_str(), tt);
+ auto& lex = *expanded_macro;
+ while( GET_TOK(tok, lex) != TOK_EOF )
+ {
+ lex.putback(tok);
+ Parse_Impl_Item(lex, impl);
+ }
}
-
- if(tok.type() == TOK_RWORD_UNSAFE) {
- item_attrs.push_back( AST::MetaItem("#UNSAFE") );
+ if(GET_TOK(tok, lex) != TOK_SEMICOLON)
+ lex.putback(tok);
+ break;
+ case TOK_RWORD_TYPE: {
+ GET_CHECK_TOK(tok, lex, TOK_IDENT);
+ ::std::string name = tok.str();
+ GET_CHECK_TOK(tok, lex, TOK_EQUAL);
+ impl.add_type(is_public, name, Parse_Type(lex));
+ GET_CHECK_TOK(tok, lex, TOK_SEMICOLON);
+ break; }
+ case TOK_RWORD_EXTERN:
+ {
+ abi = "C";
+ if( GET_TOK(tok, lex) == TOK_STRING )
+ abi = tok.str();
+ else
+ lex.putback(tok);
+
GET_TOK(tok, lex);
}
-
- ::std::string abi = "rust";
- switch(tok.type())
- {
- case TOK_RWORD_TYPE: {
- GET_CHECK_TOK(tok, lex, TOK_IDENT);
- ::std::string name = tok.str();
- GET_CHECK_TOK(tok, lex, TOK_EQUAL);
- impl.add_type(is_public, name, Parse_Type(lex));
- GET_CHECK_TOK(tok, lex, TOK_SEMICOLON);
- break; }
- case TOK_RWORD_EXTERN:
- {
- abi = "C";
- if( GET_TOK(tok, lex) == TOK_STRING )
- abi = tok.str();
- else
- lex.putback(tok);
-
- GET_TOK(tok, lex);
- }
- CHECK_TOK(tok, TOK_RWORD_FN);
- case TOK_RWORD_FN: {
- GET_CHECK_TOK(tok, lex, TOK_IDENT);
- ::std::string name = tok.str();
- // - Self allowed, can't be prototype-form
- impl.add_function(is_public, ::std::move(name), Parse_FunctionDefWithCode(lex, abi, ::std::move(item_attrs), true));
- break; }
+ CHECK_TOK(tok, TOK_RWORD_FN);
+ case TOK_RWORD_FN: {
+ GET_CHECK_TOK(tok, lex, TOK_IDENT);
+ ::std::string name = tok.str();
+ // - Self allowed, can't be prototype-form
+ impl.add_function(is_public, ::std::move(name), Parse_FunctionDefWithCode(lex, abi, ::std::move(item_attrs), true));
+ break; }
- default:
- throw ParseError::Unexpected(lex, tok);
- }
+ default:
+ throw ParseError::Unexpected(lex, tok);
}
-
- return impl;
}
void Parse_ExternBlock(TokenStream& lex, AST::Module& mod, ::std::string abi)