Macro parsel::define_keywords

source ·
macro_rules! define_keywords {
    ($vis:vis mod $modname:ident {
        $($kw:ident => $name:ident;)*
        $(_ => $underscore_name:ident;)?
    }) => { ... };
    (@private $string:expr => $name:ident;) => { ... };
}
Expand description

Declares a module containing custom keywords as defined by custom_keyword!, and a Keywords marker type for CustomIdent implementing KeywordList.

§Caveats

Due to a limitation in Rust’s macro system, if you want to match a bare underscore, _ in itself, then you need to list it as the last item in the list of keywords.

define_keywords!{
    mod kw {
        foo  => Foo;
        bar  => Bar;
        quux => Quux;
        _    => Underscore; // if present, the underscore has to be last
    }
}

// Idiom for using `CustomIdent`
type MyIdent = CustomIdent<kw::Keywords>;

// Valid keywords in this language
let id_self: MyIdent = "self".parse()?;
assert_eq!(id_self, "self");

let id_async: MyIdent = "async".parse()?;
assert_eq!(id_async, "async");

let id_baz: MyIdent = "baz".parse()?;
assert_eq!(id_baz, "baz");

let id_multi_part: MyIdent = "multi_part".parse()?;
assert_eq!(id_multi_part, "multi_part");

let _: kw::Bar = "bar".parse()?;
let _: kw::Underscore = "_".parse()?;

// Invalid keywords
let invalid: Result<MyIdent> = "quux".parse();
assert_eq!(
    invalid.unwrap_err().to_string(),
    "expected identifier, found keyword",
);

let invalid_underscore: Result<MyIdent> = "_".parse();
assert_eq!(
    invalid_underscore.unwrap_err().to_string(),
    "expected identifier, found keyword",
);

let invalid_quux: Result<kw::Quux> = "somethingelse".parse();
assert_eq!(
    invalid_quux.unwrap_err().to_string(),
    "expected keyword `quux`",
);

let kw_bar = kw::Bar::default();
let kw_quux = kw::Quux::default();
let some_stream = quote![#kw_quux #kw_bar #kw_quux];
let actual_tokens: Vec<_> = some_stream.clone().into_iter().collect();
let expected_tokens = ["quux", "bar", "quux"].map(|x| TokenTree::from(ident(x)));

assert_eq!(some_stream.to_string(), "quux bar quux");
assert!(matches!(actual_tokens, expected_tokens));

// Ensure that the generated `Keywords` struct implements `KeywordList`
// and is default-constructible, trivially-copiable
fn assert_keyword_list<K>(_: K)
where
    K: Copy + Default + KeywordList
{}

assert_keyword_list(kw::Keywords);