use proc_macro2::TokenStream;
use quote::quote;
pub fn derive_snif_macro_branch(input: &TokenStream) -> TokenStream {
let token_goblin_marker = token_goblin_marker();
quote! {
(#token_goblin_marker
[($($next:tt)+) $(=> $rest:tt)*]
[($($me:ident)+)]
[$($expansions:tt)*]
[$($extra:tt)*]
) => {
$($next)+! {#token_goblin_marker
[$($rest) =>*]
[($($next)+)]
[
$($expansions)*
$($me)+ => {#input}
]
[$($extra)*]
}
};
}
}
pub fn snif_call(
first: &TokenStream,
rest: &[TokenStream],
macro_input: &TokenStream,
) -> TokenStream {
let token_goblin_marker = token_goblin_marker();
quote! {
#first!
{
#token_goblin_marker
[#( (#rest) ) => *]
[(#first)] [ ] [#macro_input]
}
}
}
pub fn munch_macro_branches() -> TokenStream {
let token_goblin_marker = token_goblin_marker();
quote! {
(#token_goblin_marker
[] [( $($me:tt)+ )] [$($macro_args:tt)*]
[$($extra:tt)*]
) => {
$($me)*! {
[$($macro_args)*]
[$($extra)*]
}
};
(#token_goblin_marker
[$($more:tt)*]
$($any:tt)*
) => {
core::compile_error!{
concat!("Unexpected input in token-goblin::snif got extra chains: [",
stringify!($($more)+), "] rest: ", stringify!($($any)*))}
};
}
}
fn token_goblin_marker() -> TokenStream {
let punct = proc_macro2::Punct::new('~', proc_macro2::Spacing::Joint);
let punct2 = proc_macro2::Punct::new('@', proc_macro2::Spacing::Alone);
quote! {
#punct #punct2 token_goblin
}
}