Derive Macro parse_variants::Parse[][src]

#[derive(Parse)]
Expand description

A derive macro that allows us to parse a variant of an enumeration.

Usage

Attention This crate requires that you have the syn crate as a dependency and that you have not renamed it.

General

  • The custom derive can be applied to enumerations, which may contain struct like or tuple like variants. Each variant may contain one or multiple fields.
  • Every contained field must implement the syn::parse::Parse trait.
  • Member fields for each variants are parsed in order of declaration.
  • The first variant (in order of declaration) that is successfully parsed from the input will be returned. The input ParseBuffer is advanced accordingly.
  • If no variant can be successfully parsed from the given input, a descriptive compile error is returned.

Caveats

The enum variants are speculatively parsed in order or declaration, i.e. the first variant that can successfully parsed is be returned. Accordingly, the order matters if one variant includes other variants as in the following example

// WRONG: this can never return the Identifier variant
#[derive(parse_variants::Parse)]
enum Number {
    Expression(syn::Expr),
    Identifier(syn::Ident)
}

Since identifiers can be parsed as expressions, the Expression variant will always be chosen, even if the given tokens could also have been parsed as an identifier.

// CORRECT: the most general pattern comes last
#[derive(parse_variants::Parse)]
enum Number {
    Identifier(syn::Ident),
    Expression(syn::Expr)
}

This is why we have to pay attention to ordering the variants from least general to most general.

Restrictions

The enumeration cannot contain unit variants (i.e. without member fields), because there is no useful way to parse them.

Example

It is possible to write pretty complex parsers for variants. See this very silly example:

use syn::Ident;
use syn::Expr;

mod kw {
    syn::custom_keyword!(meters);
}

#[derive(parse_variants::Parse)]
enum SillyEnum {
    ExpressionInMeters {
        first: syn::Expr,
        _meters: kw::meters,
    },
    IdentPlusPlus(Ident, syn::Token![+], syn::Token![+]),
}

This parses the tokens 16 + 12*length meters as the first and C++ as the second variant.