diff options
-rw-r--r-- | src/macro_rules/eval.cpp | 52 | ||||
-rw-r--r-- | src/macro_rules/parse.cpp | 5 |
2 files changed, 52 insertions, 5 deletions
diff --git a/src/macro_rules/eval.cpp b/src/macro_rules/eval.cpp index fc54616e..41a96bb2 100644 --- a/src/macro_rules/eval.cpp +++ b/src/macro_rules/eval.cpp @@ -761,6 +761,7 @@ namespace ::std::vector<size_t> m_offsets; size_t m_active_offset; + Token m_faked_next; size_t m_consume_count; public: TokenStreamRO(const TokenTree& tt): @@ -798,6 +799,11 @@ namespace const Token& next_tok() const { static Token eof_token = TOK_EOF; + if( m_faked_next.type() != TOK_NULL ) + { + return m_faked_next; + } + if( m_offsets.empty() && m_active_offset == m_tt.size() ) { //DEBUG(m_consume_count << " " << eof_token << "(EOF)"); @@ -815,6 +821,12 @@ namespace } void consume() { + if( m_faked_next.type() != TOK_NULL ) + { + m_faked_next = Token(TOK_NULL); + return ; + } + if( m_offsets.empty() && m_active_offset == m_tt.size() ) throw ::std::runtime_error("Attempting to consume EOS"); DEBUG(m_consume_count << " " << next_tok()); @@ -829,7 +841,7 @@ namespace // If reached the end of a tree... if(m_active_offset == cur_tree->size()) { - // If the end of the root is reached, return (leaving the state indicating EOS0 + // If the end of the root is reached, return (leaving the state indicating EOS) if( m_offsets.empty() ) return ; // Pop and continue @@ -850,6 +862,11 @@ namespace } } } + void consume_and_push(eTokenType ty) + { + consume(); + m_faked_next = Token(ty); + } // Consumes if the current token is `ty`, otherwise doesn't and returns false bool consume_if(eTokenType ty) @@ -919,7 +936,20 @@ namespace } else if( lex.next() == TOK_GT || lex.next() == TOK_DOUBLE_GT ) { - level -= (lex.next() == TOK_DOUBLE_GT ? 2 : 1); + assert(level > 0); + if( lex.next() == TOK_DOUBLE_GT ) + { + if( level == 1 ) + { + lex.consume_and_push(TOK_GT); + return true; + } + level -= 2; + } + else + { + level -= 1; + } if( level == 0 ) break; } @@ -1100,6 +1130,9 @@ namespace return true; } + if( lex.consume_if(TOK_INTERPOLATED_PATTERN) ) + return true; + for(;;) { if( lex.consume_if(TOK_UNDERSCORE) ) @@ -1115,6 +1148,13 @@ namespace if( lex.next() == TOK_BRACE_OPEN ) { return consume_tt(lex); } + else if( lex.next() == TOK_PAREN_OPEN ) { + return consume_tt(lex); + } + else if( lex.next() == TOK_EXCLAM ) { + lex.consume(); + return consume_tt(lex); + } break; case TOK_RWORD_BOX: lex.consume(); @@ -1174,12 +1214,14 @@ namespace { do { + if( lex.next() == TOK_PIPE ) + break; consume_pat(lex); if(lex.consume_if(TOK_COLON)) { consume_type(lex); } - } while(lex.next() == TOK_COMMA); + } while(lex.consume_if(TOK_COMMA)); if( !lex.consume_if(TOK_PIPE) ) return false; } @@ -1436,6 +1478,8 @@ namespace case TOK_EXCLAM_EQUAL: case TOK_DOUBLE_AMP: case TOK_DOUBLE_PIPE: + case TOK_DOUBLE_DOT: + case TOK_TRIPLE_DOT: lex.consume(); break; case TOK_EQUAL: @@ -2321,7 +2365,7 @@ Token MacroExpander::realGetToken() { const auto& ent = *next_ent_ptr; TU_IFLET(MacroExpansionEnt, ent, Token, e, - return e; + return e.clone(); ) else if( ent.is_NamedValue() ) { const auto& e = ent.as_NamedValue(); diff --git a/src/macro_rules/parse.cpp b/src/macro_rules/parse.cpp index f5b0f0e4..b3b1014e 100644 --- a/src/macro_rules/parse.cpp +++ b/src/macro_rules/parse.cpp @@ -212,7 +212,10 @@ public: // TODO: `error-chain`'s quick_error macro has an arm which refers to an undefined metavar. // - Maybe emit a warning and use a marker index. WARNING(lex.point_span(), W0000, "Macro variable $" << name << " not found"); - idx = (1<<16)-1; // NOTE: Encoded as a u16 + // Emit the literal $ <name> + ret.push_back( MacroExpansionEnt(Token(TOK_DOLLAR)) ); + ret.push_back( MacroExpansionEnt(mv$(tok)) ); + continue ; } if( var_set_ptr ) { var_set_ptr->insert( ::std::make_pair(idx,true) ); |