]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #34925 - jseyfried:nested_macros, r=eddyb
authorbors <bors@rust-lang.org>
Sat, 23 Jul 2016 11:01:05 +0000 (04:01 -0700)
committerGitHub <noreply@github.com>
Sat, 23 Jul 2016 11:01:05 +0000 (04:01 -0700)
Support nested `macro_rules!`

Fixes #6994.
r? @eddyb

src/libsyntax/parse/parser.rs
src/test/run-pass/macro-of-higher-order.rs

index 125f1abb062bf2966b17a31cb428edd4a8fe6620..c143e190c6fc16ce814c785d88aab8e0d5889974 100644 (file)
@@ -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<Reader+'a>,
     /// The set of seen errors about obsolete syntax. Used to suppress
     /// extra detail when the same error is seen twice
@@ -374,6 +375,7 @@ pub fn new(sess: &'a ParseSess,
             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 @@ fn parse_unquoted(&mut self) -> PResult<'a, TokenTree> {
     }
 
     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 @@ pub fn parse_token_tree(&mut self) -> PResult<'a, TokenTree> {
                 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 @@ pub fn parse_token_tree(&mut self) -> PResult<'a, TokenTree> {
                     _ => {}
                 }
 
+                self.parsing_token_tree = parsing_token_tree;
                 Ok(TokenTree::Delimited(span, Rc::new(Delimited {
                     delim: delim,
                     open_span: open_span,
index 52e19b37d7935659707399c89ba330b4b6a108c4..c982e8ac6f83e2927c8e81a63b11d4152786df34 100644 (file)
@@ -16,7 +16,16 @@ macro_rules! anon { $lhs => $rhs }
     });
 }
 
+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);
 }