Jack
Jack

Reputation: 1999

Macro won't parse the expression the same recursively

I'm creating a recursive Rust macro that can extract a bang ! from the beginning of an expression.

I can do that just fine like this

macro_rules! test {
    (!$e:expr) => {
        println!(stringify!($e));
    };
}

fn main() {
    test!(!'a'); //Outputs: 'a'
}

But has soon as I try to call it from within the macro itself, it no longer works and I get complier errors.

macro_rules! test {
    (@process, !$e:expr) => {
        println!(stringify!($e));
    };

    ($e:expr) => {
        test!(@process, $e);
    };
}

fn main() {
    test!(!'a');
}
no rules expected the token `!'a'`

I don't think this is a typo because I can directly call it without issue on the second example. Is Rust caching the expression and then not reevaluating it? Can I somehow force Rust to reevaluate it, or is something else happening here?

Upvotes: 1

Views: 98

Answers (1)

PitaJ
PitaJ

Reputation: 15002

This is because !'a' gets parsed as an expression $e, and when $e is passed through, it's passed as a whole expression, no longer as a token sequence (so the latter macro invocation will not see !). You can work around this by capturing it as a raw token sequence instead:

macro_rules! test {
    (@process, !$e:expr) => {
        println!(stringify!($e));
    };

    ($($e:tt)*) => {
        test!(@process, $($e)*);
    };
}

Upvotes: 3

Related Questions