Problems making a macro which parses a recursive expression


#1

I’m trying to make a recursive macro that parses a recursive syntax and makes an expression out of it. It looks something like this:

macro_rules! test_macro {
    (($x:tt)) => {test_macro! ($x)};
    ([$x:expr]) => {$x};
    ($x:ident : $($y:tt)*) => {($x($(test_macro! ($y)),*))};
}   

fn add(x: u32, y: u32) -> u32 {x + y}

fn main() {
    test_macro! (add: (add: [3] [2]) [1]);
}

The first pattern match was made so that the third pattern match would work in a recursive context. The macro expansion I am expecting is test_macro! (A: (B: ...) ...) => A(test_macro! ((B: ...), ...) => A(test_macro! (B: ...), ...).

However, the above code doesn’t compile, but returns the error message:

test_macro.rs:10:23: 10:24 error: expected ident, found (
test_macro.rs:10     test_macro! (add: (add: [3] [2]) [1]);

Why does this error occur? How do I make the macro behave the way I want?


#2

Now that I think about it I believe this question is more suited to Stack Overflow.


#3

The error occurs because there is no matching pattern to the part (add: [3] [2]) and rustc does its best to give a hint. Now you may think “but what about the first one?”. Yes, that’s a close one, but there is one problem: it matches only one token tree and (add: [3] [2]) contains four token trees. Changing that line to (($($x:tt)*)) => {test_macro! ($($x)*)}; matches zero or more token trees, and the code compiles.


#4

Thanks!