1

I am building a macro parser with syn and need to check if a ParseStream is one of several keywords. The code currently looks similar to this:

mod kw {
    syn::custom_keyword!(a);
    syn::custom_keyword!(b);
    syn::custom_keyword!(c);
}

enum MyKeywordEnum {
    A(kw::a),
    B(kw::b),
    C(kw::c),
}

impl syn::parse::Parse for MyKeywordEnum {
    fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
        Ok(if let Ok(ret) = input.parse::<kw::a>() {
            Self::A(ret)
        } else if let Ok(ret) = input.parse::<kw::b>() {
            Self::B(ret)
        } else if let Ok(ret) = input.parse::<kw::c>() {
            Self::C(ret)
        } else {
            abort!(input.span(), "Couldn't parse primitive type"); // Via #[proc_macro_error]
        })
    }
}
  • Is there a built-in operator or macro to return immediately if an expression is Option::Some or Result::Ok?
  • Is there a better way to organize these checks?
  • Because ParseStream::parse statically compiles to the specific impl Parse type, I can't use match, right?
Gabriel Pizarro
  • 400
  • 4
  • 15

1 Answers1

2

As far as I know, there is not. You could create a macro to do this, or you could use the Result combinator functions to make things a little prettier:

impl syn::parse::Parse for MyKeywordEnum {
    fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
        input.parse::<kw::a>().map(Self::A)
            .or_else(|_| input.parse::<kw::b>().map(Self::B))
            .or_else(|_| input.parse::<kw::c>().map(Self::C))
            .or_else(|_| abort!(input.span(), "Couldn't parse primitive type"))
    }
}
PitaJ
  • 12,969
  • 6
  • 36
  • 55