From 6817bc18309f903a07cb86dbd13eeed97b1ca995 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sun, 8 Mar 2015 17:33:28 +0800 Subject: Macro definitions now being used --- samples/std.rs | 13 +++-- src/include/debug.hpp | 20 +++---- src/macros.cpp | 46 +++++++++------- src/parse/expr.cpp | 136 ++++++++++++++++++++++++++++++++++++++++++------ src/parse/root.cpp | 8 +-- src/parse/tokentree.hpp | 5 +- 6 files changed, 172 insertions(+), 56 deletions(-) diff --git a/samples/std.rs b/samples/std.rs index 228be06d..100fcb5e 100644 --- a/samples/std.rs +++ b/samples/std.rs @@ -10,10 +10,15 @@ macro_rules! assert{ } #[macro_export] macro_rules! assert_eq{ - ($a:expr, $b:expr) => ({ - let left = &$a; - let right = &$b; - assert!( left == right && right == left ); + ($left:expr, $right:expr) => ({ + match (&($left), &($right)) { + (left_val, right_val) => { + // check both directions of equality.... + if !((*left_val == *right_val) && (*right_val == *left_val)) { + panic!("assertion failed: `(left == right) && (right == left)` (left: `{:?}`, right: `{:?}`)", *left_val, *right_val) + } + } + } }); } diff --git a/src/include/debug.hpp b/src/include/debug.hpp index 4da63192..8376be07 100644 --- a/src/include/debug.hpp +++ b/src/include/debug.hpp @@ -26,23 +26,15 @@ 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 ++; + TraceLog(const char* tag): m_tag(tag) { + DEBUG(">> " << m_tag); + INDENT(); } - void outdent() - { - depth --; - for(unsigned int i = 0; i < depth; i ++) - ::std::cout << " "; + ~TraceLog() { + UNINDENT(); + DEBUG("<< " << m_tag); } }; #define TRACE_FUNCTION TraceLog _tf_(__func__) diff --git a/src/macros.cpp b/src/macros.cpp index 609726a6..71e0b85e 100644 --- a/src/macros.cpp +++ b/src/macros.cpp @@ -128,7 +128,7 @@ void Macro_HandlePattern(TTStream& lex, const MacroPatEnt& pat, bool rep, single throw ParseError::Unexpected(lex, TOK_EOF); else lex.putback(tok); - val = Parse_TT(lex); + val = Parse_TT(lex, false); if(0) case MacroPatEnt::PAT_EXPR: val = Parse_TT_Expr(lex); @@ -137,7 +137,7 @@ void Macro_HandlePattern(TTStream& lex, const MacroPatEnt& pat, bool rep, single val = Parse_TT_Stmt(lex); if(0) case MacroPatEnt::PAT_PATH: - val = Parse_TT_Path(lex); + val = Parse_TT_Path(lex, false); // non-expr mode if(0) case MacroPatEnt::PAT_BLOCK: val = Parse_TT_Block(lex); @@ -159,43 +159,49 @@ void Macro_HandlePattern(TTStream& lex, const MacroPatEnt& pat, bool rep, single } -MacroExpander Macro_InvokeInt(const MacroRules& rules, TokenTree input) +MacroExpander Macro_InvokeInt(const char *name, const MacroRules& rules, TokenTree input) { + TRACE_FUNCTION; + // 2. Check input token tree against possible variants // 3. Bind names // 4. Return expander + int i = 0; for(const auto& rule : rules) { Token tok; // Create token stream for input tree TTStream lex(input); - if(GET_TOK(tok, lex) == TOK_EOF) { + /* + enum eTokenType close; + switch( GET_TOK(tok, lex) ) + { + case TOK_PAREN_OPEN: close = TOK_PAREN_CLOSE; break; + case TOK_BRACE_OPEN: close = TOK_BRACE_CLOSE; break; + default: throw ParseError::Unexpected(lex, tok); } + */ ::std::map bound_tts; ::std::multimap 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); } + + //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 ); + return MacroExpander(rule.m_contents, 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("Parse of rule " << i << " of " << name <<" failed - " << e.what()); } + i ++; } DEBUG(""); throw ParseError::Todo("Error when macro fails to match"); @@ -211,7 +217,7 @@ 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() ) { - return Macro_InvokeInt(macro_reg->second, input); + return Macro_InvokeInt(macro_reg->first.c_str(), macro_reg->second, input); } for( auto ent = g_macro_module; ent; ent = ent->m_prev ) @@ -222,7 +228,7 @@ MacroExpander Macro_Invoke(const char* name, TokenTree input) DEBUG("" << m.name); if( m.name == name ) { - return Macro_InvokeInt(m.data, input); + return Macro_InvokeInt(m.name.c_str(), m.data, input); } } @@ -231,7 +237,7 @@ MacroExpander Macro_Invoke(const char* name, TokenTree input) DEBUG("" << mi.name); if( mi.name == name ) { - return Macro_InvokeInt(*mi.data, input); + return Macro_InvokeInt(mi.name.c_str(), *mi.data, input); } } } @@ -247,11 +253,13 @@ Token MacroExpander::realGetToken() { if( m_ttstream.get() ) { + DEBUG("TTStream set"); Token rv = m_ttstream->getToken(); if( rv.type() != TOK_EOF ) return rv; m_ttstream.reset(); } + DEBUG("ofs " << m_ofs << " < " << m_contents.size()); if( m_ofs < m_contents.size() ) { const MacroRuleEnt& ent = m_contents[m_ofs]; @@ -266,6 +274,8 @@ Token MacroExpander::realGetToken() } throw ParseError::Todo("MacroExpander - realGetToken"); } + + DEBUG("EOF"); return Token(TOK_EOF); } diff --git a/src/parse/expr.cpp b/src/parse/expr.cpp index a1b9ed29..34630115 100644 --- a/src/parse/expr.cpp +++ b/src/parse/expr.cpp @@ -364,6 +364,9 @@ ExprNodeP Parse_ExprBlocks(TokenStream& lex) Token tok; switch( GET_TOK(tok, lex) ) { + case TOK_BRACE_OPEN: + lex.putback(tok); + return Parse_ExprBlockNode(lex); case TOK_RWORD_MATCH: return Parse_Expr_Match(lex); case TOK_RWORD_IF: @@ -632,9 +635,12 @@ ExprNodeP Parse_ExprVal(TokenStream& lex) return rv; } case TOK_MACRO: - //return NEWNODE( AST::ExprNode_Macro, tok.str(), Parse_TT(lex) ); { - MacroExpander expanded_macro = Macro_Invoke(tok.str().c_str(), Parse_TT(lex)); + TokenTree tt = Parse_TT(lex, true); + if( tt.size() == 0 ) { + throw ParseError::Unexpected(lex, tt.tok()); + } + MacroExpander expanded_macro = Macro_Invoke(tok.str().c_str(), tt); return Parse_Expr0(expanded_macro); } default: @@ -643,8 +649,10 @@ ExprNodeP Parse_ExprVal(TokenStream& lex) } // Token Tree Parsing -TokenTree Parse_TT(TokenStream& lex) +TokenTree Parse_TT(TokenStream& lex, bool unwrapped) { + TRACE_FUNCTION; + Token tok = lex.getToken(); eTokenType closer = TOK_PAREN_CLOSE; switch(tok.type()) @@ -663,19 +671,105 @@ TokenTree Parse_TT(TokenStream& lex) } ::std::vector items; - items.push_back(tok); + if( !unwrapped ) + items.push_back(tok); while(GET_TOK(tok, lex) != closer && tok.type() != TOK_EOF) { lex.putback(tok); - items.push_back(Parse_TT(lex)); + items.push_back(Parse_TT(lex, false)); } - items.push_back(tok); + if( !unwrapped ) + items.push_back(tok); return TokenTree(items); } -TokenTree Parse_TT_Path(TokenStream& lex) +TokenTree Parse_TT_Type(TokenStream& lex) +{ + TRACE_FUNCTION; + Token tok; + + ::std::vector ret; + switch(GET_TOK(tok, lex)) + { + case TOK_AMP: + throw ParseError::Todo("TokenTree type &-ptr"); + case TOK_STAR: + throw ParseError::Todo("TokenTree type *-ptr"); + case TOK_DOUBLE_COLON: + case TOK_IDENT: + lex.putback(tok); + return Parse_TT_Path(lex, false); + default: + throw ParseError::Unexpected(lex, tok); + } + return TokenTree(ret); +} + +TokenTree Parse_TT_Path(TokenStream& lex, bool mode_expr) { - throw ParseError::Todo("TokenTree path"); + TRACE_FUNCTION; + + Token tok; + + ::std::vector ret; + if( GET_TOK(tok, lex) == TOK_DOUBLE_COLON ) { + ret.push_back(TokenTree(tok)); + } + else { + lex.putback(tok); + } + + for(;;) + { + // Expect an ident + GET_CHECK_TOK(tok, lex, TOK_IDENT); + ret.push_back(TokenTree(tok)); + // If mode is expr, check for a double colon here + if( mode_expr ) + { + if( GET_TOK(tok, lex) != TOK_DOUBLE_COLON ) + break; + ret.push_back( TokenTree(tok) ); + } + + if( GET_TOK(tok, lex) == TOK_LT ) + { + do { + ret.push_back( TokenTree(tok) ); + ret.push_back(Parse_TT_Type(lex)); + } while(GET_TOK(tok, lex) == TOK_COMMA); + if( tok.type() != TOK_GT ) + { + if(tok.type() == TOK_DOUBLE_GT) { + ret.push_back(TokenTree(Token(TOK_GT))); + lex.putback(Token(TOK_GT)); + } + else { + CHECK_TOK(tok, TOK_GT); + } + } + else { + ret.push_back(TokenTree(tok)); + } + + if( GET_TOK(tok, lex) != TOK_DOUBLE_COLON ) + break; + ret.push_back(TokenTree(tok)); + } + else + { + lex.putback(tok); + + if( !mode_expr ) + { + if( GET_TOK(tok, lex) != TOK_DOUBLE_COLON ) + break; + ret.push_back(TokenTree(tok)); + } + } + } + lex.putback(tok); + return TokenTree(ret); } /// Parse a token tree path TokenTree Parse_TT_Val(TokenStream& lex) @@ -686,16 +780,16 @@ TokenTree Parse_TT_Val(TokenStream& lex) { case TOK_PAREN_OPEN: lex.putback(tok); - return Parse_TT(lex); + return Parse_TT(lex, false); case TOK_IDENT: case TOK_DOUBLE_COLON: { lex.putback(tok); - TokenTree inner = Parse_TT_Path(lex); + TokenTree inner = Parse_TT_Path(lex, true); if(GET_TOK(tok, lex) == TOK_BRACE_OPEN) { lex.putback(tok); ret.push_back(inner); - ret.push_back(Parse_TT(lex)); + ret.push_back(Parse_TT(lex, false)); } else { lex.putback(tok); @@ -703,17 +797,20 @@ TokenTree Parse_TT_Val(TokenStream& lex) } break; } case TOK_RWORD_SELF: + case TOK_INTEGER: + case TOK_FLOAT: + case TOK_STRING: return TokenTree(tok); case TOK_RWORD_MATCH: ret.push_back(TokenTree(tok)); - ret.push_back(Parse_TT(lex)); + ret.push_back(Parse_TT(lex, false)); break; case TOK_RWORD_IF: ret.push_back(TokenTree(tok)); - ret.push_back(Parse_TT(lex)); + ret.push_back(Parse_TT_Expr(lex)); if( GET_TOK(tok, lex) == TOK_RWORD_ELSE ) { ret.push_back(TokenTree(tok)); - ret.push_back(Parse_TT(lex)); + ret.push_back(Parse_TT(lex, false)); } else { lex.putback(tok); @@ -728,6 +825,8 @@ TokenTree Parse_TT_Val(TokenStream& lex) /// Parse a token tree expression TokenTree Parse_TT_Expr(TokenStream& lex) { + TRACE_FUNCTION; + Token tok; ::std::vector ret; @@ -740,9 +839,16 @@ TokenTree Parse_TT_Expr(TokenStream& lex) { case TOK_PLUS: case TOK_DASH: + case TOK_SLASH: + case TOK_STAR: + case TOK_PERCENT: ret.push_back(tok); ret.push_back(Parse_TT_Val(lex)); break; + case TOK_PAREN_OPEN: + lex.putback(tok); + ret.push_back(Parse_TT(lex, false)); + break; case TOK_DOT: ret.push_back(tok); GET_CHECK_TOK(tok, lex, TOK_IDENT); @@ -753,7 +859,7 @@ TokenTree Parse_TT_Expr(TokenStream& lex) throw ParseError::Todo("Generic type params in TT expr"); case TOK_PAREN_OPEN: lex.putback(tok); - ret.push_back(Parse_TT(lex)); + ret.push_back(Parse_TT(lex, false)); break; default: lex.putback(tok); diff --git a/src/parse/root.cpp b/src/parse/root.cpp index 6b857ff9..ec2589f6 100644 --- a/src/parse/root.cpp +++ b/src/parse/root.cpp @@ -7,8 +7,6 @@ #include "../macros.hpp" #include -unsigned int TraceLog::depth = 0; - extern AST::Pattern Parse_Pattern(TokenStream& lex); ::std::vector Parse_Path_GenericList(TokenStream& lex) @@ -820,7 +818,11 @@ MacroRule Parse_MacroRules_Var(Preproc& lex) GET_CHECK_TOK(tok, lex, TOK_FATARROW); // Replacement - auto rep = Parse_TT(lex); + auto rep = Parse_TT(lex, true); // - don't care about the enclosing brackets + TTStream slex(rep); + + while(GET_TOK(tok, slex) != TOK_EOF) + rule.m_contents.push_back( MacroRuleEnt(tok) ); return rule; } diff --git a/src/parse/tokentree.hpp b/src/parse/tokentree.hpp index d69a7a12..629322dd 100644 --- a/src/parse/tokentree.hpp +++ b/src/parse/tokentree.hpp @@ -47,10 +47,11 @@ protected: virtual Token realGetToken() override; }; -extern TokenTree Parse_TT(TokenStream& lex); +// unwrapped = Exclude the enclosing brackets (used by macro parse code) +extern TokenTree Parse_TT(TokenStream& lex, bool unwrapped); extern TokenTree Parse_TT_Expr(TokenStream& lex); extern TokenTree Parse_TT_Stmt(TokenStream& lex); extern TokenTree Parse_TT_Block(TokenStream& lex); -extern TokenTree Parse_TT_Path(TokenStream& lex); +extern TokenTree Parse_TT_Path(TokenStream& lex, bool mode_expr); #endif // TOKENTREE_HPP_INCLUDED -- cgit v1.2.3