Macro expansion with parenthesis

macro_rules! re {
    (($e:expr)) => { 1 + re!($e) };
    ($e:expr) => { 0 };

fn main () {
    println!("{:?}", re!((((0)))));


I was trying to write a macro that removes parenthesis, such that I can generate some code for the thing inside of it without the parenthesis, but somehow after removing the outermost layer of parenthesis any following macro invocations no longer match on them, does anyone have any idea what is going on here? I've created an example macro that replaces macro!((x)) with 1 + macro!(x), and then call it with macro!((((0)))), which in my mind should then recursively expand to 1 + 1 + 1 + 0, i.e. 3. But when running my example program I get 1 instead.

1 Like

Instead of taking expression tokens (expr), you should take token trees instead (tt):

macro_rules! re {
    (($e:tt)) => { 1 + re!($e) };
    ($e:tt) => { 0 };

See Rust Playground

The issue with using an expression, is that parenthesis can be used as part of an expression.
For example, this is syntactically valid:

let x = (((4)));

The compiler treats the entire right side as an expression, but discards those redundant parenthesis.

The same thing is happening in your macro. When you pass in (((0))) as the argument, the macro is matching it like this:
( ((0)) )
Where the outermost parenthesis are matching the macro rule, and any remaining parenthesis are just being treated as part of the expression and getting eaten.

By using a token tree, these parenthesis are preserved and passed into the next recursive macro call.

1 Like

Right! That was the part that I was missing! Thank you so much!

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.