use proc_macro::TokenStream;
use quote::quote;
use syn::{parse, self};
struct Alphabet {
meta: Option<Vec<syn::Attribute>>,
vis: syn::Visibility,
ident: syn::Ident,
contents: String
}
#[proc_macro]
pub fn alphabet(input: TokenStream) -> TokenStream {
let Alphabet {
meta,
vis,
ident,
contents
} = syn::parse_macro_input!(input as Alphabet);
let chars: Vec<char> = contents.chars().collect();
let alphabet_len = chars.len();
TokenStream::from(match meta {
None => quote! {
#vis const #ident: [char; #alphabet_len] = [#(#chars),*];
},
Some(meta) => quote! {
#(#meta)* #vis const #ident: [char; #alphabet_len] = [#(#chars),*];
}
})
}
impl syn::parse::Parse for Alphabet {
fn parse(buf: parse::ParseStream) -> syn::Result<Self> {
let meta;
if buf.peek(syn::Token![#]) {
meta = Some(buf.call(syn::Attribute::parse_outer)?);
} else {
meta = None;
}
let vis;
if buf.peek(syn::Token![pub]) || buf.peek(syn::Token![crate]) {
vis = buf.parse::<syn::Visibility>()?;
} else {
vis = syn::Visibility::Inherited;
}
let ident: syn::Ident = buf.parse()?;
buf.parse::<syn::Token![=]>()?;
let contents: syn::LitStr = buf.parse()?;
let contents = contents.value();
if buf.peek(syn::Token![;]) {
buf.parse::<syn::Token![;]>()?;
}
Ok(Alphabet {
meta,
vis,
ident,
contents
})
}
}