diff options
| author | Keegan McAllister <kmcallister@mozilla.com> | 2014-09-15 18:27:28 -0700 |
|---|---|---|
| committer | Keegan McAllister <kmcallister@mozilla.com> | 2015-01-05 11:38:12 -0800 |
| commit | ad7c64777380a780b42028855ad0d09932a11623 (patch) | |
| tree | e07587239681150b7c9a9d4464411d18eed31714 /src/libsyntax/ext | |
| parent | 5e5924b79915326d81db2aebfe73d2a20b8506f1 (diff) | |
| download | rust-ad7c64777380a780b42028855ad0d09932a11623.tar.gz rust-ad7c64777380a780b42028855ad0d09932a11623.zip | |
Add a special macro nonterminal $crate
Diffstat (limited to 'src/libsyntax/ext')
| -rw-r--r-- | src/libsyntax/ext/expand.rs | 12 | ||||
| -rw-r--r-- | src/libsyntax/ext/tt/macro_rules.rs | 8 | ||||
| -rw-r--r-- | src/libsyntax/ext/tt/transcribe.rs | 29 |
3 files changed, 43 insertions, 6 deletions
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index a1a13f23064..325d8aa594a 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -432,7 +432,7 @@ pub fn expand_item(it: P<ast::Item>, fld: &mut MacroExpander) } let mut new_items = match it.node { - ast::ItemMac(..) => expand_item_mac(it, fld), + ast::ItemMac(..) => expand_item_mac(it, None, fld), ast::ItemMod(_) | ast::ItemForeignMod(_) => { let valid_ident = it.ident.name != parse::token::special_idents::invalid.name; @@ -529,8 +529,9 @@ fn contains_macro_escape(attrs: &[ast::Attribute]) -> bool { // Support for item-position macro invocations, exactly the same // logic as for expression-position macro invocations. -pub fn expand_item_mac(it: P<ast::Item>, fld: &mut MacroExpander) - -> SmallVector<P<ast::Item>> { +pub fn expand_item_mac(it: P<ast::Item>, + imported_from: Option<ast::Ident>, + fld: &mut MacroExpander) -> SmallVector<P<ast::Item>> { let (extname, path_span, tts) = match it.node { ItemMac(codemap::Spanned { node: MacInvocTT(ref pth, ref tts, _), @@ -611,7 +612,8 @@ pub fn expand_item_mac(it: P<ast::Item>, fld: &mut MacroExpander) }); // DON'T mark before expansion. let MacroDef { name, ext } - = macro_rules::add_new_extension(fld.cx, it.span, it.ident, tts); + = macro_rules::add_new_extension(fld.cx, it.span, it.ident, + imported_from, tts); fld.cx.syntax_env.insert(intern(name.as_slice()), ext); if attr::contains_name(it.attrs.as_slice(), "macro_export") { @@ -1190,7 +1192,7 @@ pub fn expand_crate(parse_sess: &parse::ParseSess, expander.cx.cfg(), expander.cx.parse_sess()) .expect("expected a serialized item"); - expand_item_mac(item, &mut expander); + expand_item_mac(item, Some(crate_name), &mut expander); } } diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index 15b75442ca2..a278604b167 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -110,6 +110,7 @@ impl<'a> MacResult for ParserAnyMacro<'a> { struct MacroRulesMacroExpander { name: Ident, + imported_from: Option<Ident>, lhses: Vec<Rc<NamedMatch>>, rhses: Vec<Rc<NamedMatch>>, } @@ -123,6 +124,7 @@ impl TTMacroExpander for MacroRulesMacroExpander { generic_extension(cx, sp, self.name, + self.imported_from, arg, self.lhses[], self.rhses[]) @@ -133,6 +135,7 @@ impl TTMacroExpander for MacroRulesMacroExpander { fn generic_extension<'cx>(cx: &'cx ExtCtxt, sp: Span, name: Ident, + imported_from: Option<Ident>, arg: &[ast::TokenTree], lhses: &[Rc<NamedMatch>], rhses: &[Rc<NamedMatch>]) @@ -157,6 +160,7 @@ fn generic_extension<'cx>(cx: &'cx ExtCtxt, // `None` is because we're not interpolating let mut arg_rdr = new_tt_reader(&cx.parse_sess().span_diagnostic, None, + None, arg.iter() .map(|x| (*x).clone()) .collect()); @@ -177,6 +181,7 @@ fn generic_extension<'cx>(cx: &'cx ExtCtxt, // rhs has holes ( `$id` and `$(...)` that need filled) let trncbr = new_tt_reader(&cx.parse_sess().span_diagnostic, Some(named_matches), + imported_from, rhs); let p = Parser::new(cx.parse_sess(), cx.cfg(), box trncbr); // Let the context choose how to interpret the result. @@ -209,6 +214,7 @@ fn generic_extension<'cx>(cx: &'cx ExtCtxt, pub fn add_new_extension<'cx>(cx: &'cx mut ExtCtxt, sp: Span, name: Ident, + imported_from: Option<Ident>, arg: Vec<ast::TokenTree> ) -> MacroDef { @@ -247,6 +253,7 @@ pub fn add_new_extension<'cx>(cx: &'cx mut ExtCtxt, // Parse the macro_rules! invocation (`none` is for no interpolations): let arg_reader = new_tt_reader(&cx.parse_sess().span_diagnostic, None, + None, arg.clone()); let argument_map = parse_or_else(cx.parse_sess(), cx.cfg(), @@ -266,6 +273,7 @@ pub fn add_new_extension<'cx>(cx: &'cx mut ExtCtxt, let exp = box MacroRulesMacroExpander { name: name, + imported_from: imported_from, lhses: lhses, rhses: rhses, }; diff --git a/src/libsyntax/ext/tt/transcribe.rs b/src/libsyntax/ext/tt/transcribe.rs index 86e81ede8b0..e4e6f5ac6b0 100644 --- a/src/libsyntax/ext/tt/transcribe.rs +++ b/src/libsyntax/ext/tt/transcribe.rs @@ -15,7 +15,7 @@ use codemap::{Span, DUMMY_SP}; use diagnostic::SpanHandler; use ext::tt::macro_parser::{NamedMatch, MatchedSeq, MatchedNonterminal}; use parse::token::{Eof, DocComment, Interpolated, MatchNt, SubstNt}; -use parse::token::{Token, NtIdent}; +use parse::token::{Token, NtIdent, SpecialMacroVar}; use parse::token; use parse::lexer::TokenAndSpan; @@ -39,6 +39,10 @@ pub struct TtReader<'a> { stack: Vec<TtFrame>, /* for MBE-style macro transcription */ interpolations: HashMap<Ident, Rc<NamedMatch>>, + imported_from: Option<Ident>, + + // Some => return imported_from as the next token + crate_name_next: Option<Span>, repeat_idx: Vec<uint>, repeat_len: Vec<uint>, /* cached: */ @@ -53,6 +57,7 @@ pub struct TtReader<'a> { /// should) be none. pub fn new_tt_reader<'a>(sp_diag: &'a SpanHandler, interp: Option<HashMap<Ident, Rc<NamedMatch>>>, + imported_from: Option<Ident>, src: Vec<ast::TokenTree> ) -> TtReader<'a> { let mut r = TtReader { @@ -71,6 +76,8 @@ pub fn new_tt_reader<'a>(sp_diag: &'a SpanHandler, None => HashMap::new(), Some(x) => x, }, + imported_from: imported_from, + crate_name_next: None, repeat_idx: Vec::new(), repeat_len: Vec::new(), desugar_doc_comments: false, @@ -162,6 +169,14 @@ pub fn tt_next_token(r: &mut TtReader) -> TokenAndSpan { sp: r.cur_span.clone(), }; loop { + match r.crate_name_next.take() { + None => (), + Some(sp) => { + r.cur_span = sp; + r.cur_tok = token::Ident(r.imported_from.unwrap(), token::Plain); + return ret_val; + }, + } let should_pop = match r.stack.last() { None => { assert_eq!(ret_val.tok, token::Eof); @@ -307,6 +322,18 @@ pub fn tt_next_token(r: &mut TtReader) -> TokenAndSpan { sep: None }); } + TtToken(sp, token::SpecialVarNt(SpecialMacroVar::CrateMacroVar)) => { + r.stack.last_mut().unwrap().idx += 1; + + if r.imported_from.is_some() { + r.cur_span = sp; + r.cur_tok = token::ModSep; + r.crate_name_next = Some(sp); + return ret_val; + } + + // otherwise emit nothing and proceed to the next token + } TtToken(sp, tok) => { r.cur_span = sp; r.cur_tok = tok; |
