How to parse nested optional tokens in macro_rules?

147 Views Asked by At

When trying to do

macro_rules! tipey {
    (Vec<$pt: tt>) => { 2 };
    (Vec<Option<$pt: tt>>) => { 3 };
    ($pt: tt) => { 1 };
}

macro_rules! structy {
    (struct $i: ident { 
        $($p: ident: $pt: tt $(<$ppt: tt $(<$gt: tt> )? > )?),+
        $(,)?
    }) => {
        const v: &[usize] = &[ $(tipey!( $pt $(<$ppt $(<$gt>)?>)?)),+ ];
    };
}

structy!(
    struct ContentDetails {
        pattern: String,
        fields: Vec<Option<String>>,
    }
);

I get

no rules expected the token >>

How do I make this parse?

1

There are 1 best solutions below

1
On

This problem is caused by your indiscriminate use of tt in your macros. This should be a last resort, as it can essentially match anything. The Rust compiler must disambiguate >> as part of a type v.s. expression based on the expected syntax. If you expect anything, then Rust must interpret >> as an operator.

Choose more appropriate metavariables such as ty (type), ident (identifier), path (fully specified path), etc.