Search code examples
macrosrustrust-macros

Can I repeat matching by several rules in a macro?


Can I repeat match in a Rust macro? I want to be able to do something like:

my_dsl! {
    foo <other tokens>;
    bar <other tokens>;
    foo <other tokens>;
    ...
}

Basically, an arbitrary number of semicolon-delimited statement, and each statement is handled by different rules.

I know I can have several foo!(), bar!() macros - each per statement, but ideally I'd like to avoid that.

I was thinking if I can capture something like $($t:tt)*, but excluding semicolon, and then delegate to other macros?


Solution

  • You should read The Little Book of Rust Macros and specifically for your question section 4.2: Incremental TT munchers.

    For example:

    macro_rules! my_dsl {
        () => {};
        (foo $name:ident; $($tail:tt)*) => {
            {
                println!(concat!("foo ", stringify!($name));
                my_dsl!($($tail)*);
            }
        };
        (bar $name:ident; $($tail:tt)*) => {
            {
                println!(concat!("bar ", stringify!($name));
                my_dsl!($($tail)*);
            }
        };
    }