syn

Macro custom_keyword

Source
macro_rules! custom_keyword {
    ($ident:ident) => { ... };
}
Expand description

Define a type that supports parsing and printing a given identifier as if it were a keyword.

§Usage

As a convention, it is recommended that this macro be invoked within a module called kw or keyword and that the resulting parser be invoked with a kw:: or keyword:: prefix.

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

The generated syntax tree node supports the following operations just like any built-in keyword token.

  • Peekinginput.peek(kw::whatever)

  • Parsinginput.parse::<kw::whatever>()?

  • Printingquote!( ... #whatever_token ... )

  • Construction from a Spanlet whatever_token = kw::whatever(sp)

  • Field access to its span — let sp = whatever_token.span

§Example

This example parses input that looks like bool = true or str = "value". The key must be either the identifier bool or the identifier str. If bool, the value may be either true or false. If str, the value may be any string literal.

The symbols bool and str are not reserved keywords in Rust so these are not considered keywords in the syn::token module. Like any other identifier that is not a keyword, these can be declared as custom keywords by crates that need to use them as such.

use syn::{LitBool, LitStr, Result, Token};
use syn::parse::{Parse, ParseStream};

mod kw {
    syn::custom_keyword!(bool);
    syn::custom_keyword!(str);
}

enum Argument {
    Bool {
        bool_token: kw::bool,
        eq_token: Token![=],
        value: LitBool,
    },
    Str {
        str_token: kw::str,
        eq_token: Token![=],
        value: LitStr,
    },
}

impl Parse for Argument {
    fn parse(input: ParseStream) -> Result<Self> {
        let lookahead = input.lookahead1();
        if lookahead.peek(kw::bool) {
            Ok(Argument::Bool {
                bool_token: input.parse::<kw::bool>()?,
                eq_token: input.parse()?,
                value: input.parse()?,
            })
        } else if lookahead.peek(kw::str) {
            Ok(Argument::Str {
                str_token: input.parse::<kw::str>()?,
                eq_token: input.parse()?,
                value: input.parse()?,
            })
        } else {
            Err(lookahead.error())
        }
    }
}