From b40b7ef0c429b62d0907c0de930a93b262229b92 Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Tue, 19 Jul 2016 20:01:54 +0000 Subject: [PATCH 1/2] Support nested `macro_rules!`. --- src/libsyntax/parse/parser.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 4656ba03e21c3..32107026eedf4 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -258,6 +258,7 @@ pub struct Parser<'a> { pub tokens_consumed: usize, pub restrictions: Restrictions, pub quote_depth: usize, // not (yet) related to the quasiquoter + parsing_token_tree: bool, pub reader: Box, /// The set of seen errors about obsolete syntax. Used to suppress /// extra detail when the same error is seen twice @@ -374,6 +375,7 @@ impl<'a> Parser<'a> { tokens_consumed: 0, restrictions: Restrictions::empty(), quote_depth: 0, + parsing_token_tree: false, obsolete_set: HashSet::new(), mod_path_stack: Vec::new(), filename: filename, @@ -2663,7 +2665,7 @@ impl<'a> Parser<'a> { } pub fn check_unknown_macro_variable(&mut self) { - if self.quote_depth == 0 { + if self.quote_depth == 0 && !self.parsing_token_tree { match self.token { token::SubstNt(name) => self.fatal(&format!("unknown macro variable `{}`", name)).emit(), @@ -2723,6 +2725,7 @@ impl<'a> Parser<'a> { Err(err) }, token::OpenDelim(delim) => { + let parsing_token_tree = ::std::mem::replace(&mut self.parsing_token_tree, true); // The span for beginning of the delimited section let pre_span = self.span; @@ -2787,6 +2790,7 @@ impl<'a> Parser<'a> { _ => {} } + self.parsing_token_tree = parsing_token_tree; Ok(TokenTree::Delimited(span, Rc::new(Delimited { delim: delim, open_span: open_span, From 485e2df1b1fbd4acde8dbc5bfbdf7fed3acc227c Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Tue, 19 Jul 2016 20:16:23 +0000 Subject: [PATCH 2/2] Add regression test. --- src/test/run-pass/macro-of-higher-order.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/test/run-pass/macro-of-higher-order.rs b/src/test/run-pass/macro-of-higher-order.rs index 52e19b37d7935..c982e8ac6f83e 100644 --- a/src/test/run-pass/macro-of-higher-order.rs +++ b/src/test/run-pass/macro-of-higher-order.rs @@ -16,7 +16,16 @@ macro_rules! higher_order { }); } +macro_rules! outer { + ($x:expr; $fragment:ident) => { + macro_rules! inner { ($y:$fragment) => { $x + $y } } + } +} + fn main() { let val = higher_order!(subst ($x:expr, $y:expr, $foo:expr) => (($x + $y, $foo))); assert_eq!(val, (3, "foo")); + + outer!(2; expr); + assert_eq!(inner!(3), 5); }