6

I'm trying to make a simple macro that invokes vec! with whatever it receives then does some simple processing before returning the new vector:

macro_rules! sorted_vec {
    ($x:expr) => {
        {
            let v = vec![$x];
            v.sort();
            v
        }
    }
}

The problem is that my macro is trying to parse the syntax, so it complains about commas, etc. That makes sense, but I'm not sure how to get around it. I don't think expr is the correct fragment specifier to use. How do I get it to pass the raw input on to vec! without processing it?

Peter Hall
  • 53,120
  • 14
  • 139
  • 204
anderspitman
  • 9,230
  • 10
  • 40
  • 61

1 Answers1

9

The fragment specifier you want is tt (Token-Tree). A tt is simply an arbitrary valid rust-token like a keyword or an operator or a bracket/block/square-bracket with arbitrary tts inside. Combined with a variadic macro, you get infinite tokens that can be directly passed to another macro

macro_rules! sorted_vec {
    ($($x:tt)*) => {
        {
            let mut v = vec![$($x)*];
            v.sort();
            v
        }
    }
}
oli_obk
  • 28,729
  • 6
  • 82
  • 98
  • 1
    I guess it's not "token type", it's ["token tree"](https://github.com/rust-lang/rust/blob/master/src/libsyntax/ext/tt/macro_parser.rs#L509), but I'm just nitpicking, of course :). – Vladimir Matveev Aug 05 '15 at 20:25
  • yea, I confused http://manishearth.github.io/rust-internals-docs/syntax/parse/parser/enum.TokenType.html with http://manishearth.github.io/rust-internals-docs/syntax/ast/enum.TokenTree.html ... – oli_obk Aug 06 '15 at 06:34