1ea88969fSopenharmony_ciuse crate::{Error, Result}; 2ea88969fSopenharmony_ciuse proc_macro2::{Delimiter, Ident, Span, TokenStream, TokenTree}; 3ea88969fSopenharmony_ciuse quote::ToTokens; 4ea88969fSopenharmony_ciuse std::iter::Peekable; 5ea88969fSopenharmony_ci 6ea88969fSopenharmony_cipub(crate) fn parse_input( 7ea88969fSopenharmony_ci input: TokenStream, 8ea88969fSopenharmony_ci) -> Result<(Vec<Attribute>, Vec<TokenTree>, TokenTree)> { 9ea88969fSopenharmony_ci let mut input = input.into_iter().peekable(); 10ea88969fSopenharmony_ci let mut attrs = Vec::new(); 11ea88969fSopenharmony_ci 12ea88969fSopenharmony_ci while let Some(attr) = parse_next_attr(&mut input)? { 13ea88969fSopenharmony_ci attrs.push(attr); 14ea88969fSopenharmony_ci } 15ea88969fSopenharmony_ci 16ea88969fSopenharmony_ci let sig = parse_signature(&mut input); 17ea88969fSopenharmony_ci let body = input.next().ok_or_else(|| { 18ea88969fSopenharmony_ci Error::new( 19ea88969fSopenharmony_ci Span::call_site(), 20ea88969fSopenharmony_ci "`#[proc_macro_error]` can be applied only to functions".to_string(), 21ea88969fSopenharmony_ci ) 22ea88969fSopenharmony_ci })?; 23ea88969fSopenharmony_ci 24ea88969fSopenharmony_ci Ok((attrs, sig, body)) 25ea88969fSopenharmony_ci} 26ea88969fSopenharmony_ci 27ea88969fSopenharmony_cifn parse_next_attr( 28ea88969fSopenharmony_ci input: &mut Peekable<impl Iterator<Item = TokenTree>>, 29ea88969fSopenharmony_ci) -> Result<Option<Attribute>> { 30ea88969fSopenharmony_ci let shebang = match input.peek() { 31ea88969fSopenharmony_ci Some(TokenTree::Punct(ref punct)) if punct.as_char() == '#' => input.next().unwrap(), 32ea88969fSopenharmony_ci _ => return Ok(None), 33ea88969fSopenharmony_ci }; 34ea88969fSopenharmony_ci 35ea88969fSopenharmony_ci let group = match input.peek() { 36ea88969fSopenharmony_ci Some(TokenTree::Group(ref group)) if group.delimiter() == Delimiter::Bracket => { 37ea88969fSopenharmony_ci let res = group.clone(); 38ea88969fSopenharmony_ci input.next(); 39ea88969fSopenharmony_ci res 40ea88969fSopenharmony_ci } 41ea88969fSopenharmony_ci other => { 42ea88969fSopenharmony_ci let span = other.map_or(Span::call_site(), |tt| tt.span()); 43ea88969fSopenharmony_ci return Err(Error::new(span, "expected `[`".to_string())); 44ea88969fSopenharmony_ci } 45ea88969fSopenharmony_ci }; 46ea88969fSopenharmony_ci 47ea88969fSopenharmony_ci let path = match group.stream().into_iter().next() { 48ea88969fSopenharmony_ci Some(TokenTree::Ident(ident)) => Some(ident), 49ea88969fSopenharmony_ci _ => None, 50ea88969fSopenharmony_ci }; 51ea88969fSopenharmony_ci 52ea88969fSopenharmony_ci Ok(Some(Attribute { 53ea88969fSopenharmony_ci shebang, 54ea88969fSopenharmony_ci group: TokenTree::Group(group), 55ea88969fSopenharmony_ci path, 56ea88969fSopenharmony_ci })) 57ea88969fSopenharmony_ci} 58ea88969fSopenharmony_ci 59ea88969fSopenharmony_cifn parse_signature(input: &mut Peekable<impl Iterator<Item = TokenTree>>) -> Vec<TokenTree> { 60ea88969fSopenharmony_ci let mut sig = Vec::new(); 61ea88969fSopenharmony_ci loop { 62ea88969fSopenharmony_ci match input.peek() { 63ea88969fSopenharmony_ci Some(TokenTree::Group(ref group)) if group.delimiter() == Delimiter::Brace => { 64ea88969fSopenharmony_ci return sig; 65ea88969fSopenharmony_ci } 66ea88969fSopenharmony_ci None => return sig, 67ea88969fSopenharmony_ci _ => sig.push(input.next().unwrap()), 68ea88969fSopenharmony_ci } 69ea88969fSopenharmony_ci } 70ea88969fSopenharmony_ci} 71ea88969fSopenharmony_ci 72ea88969fSopenharmony_cipub(crate) struct Attribute { 73ea88969fSopenharmony_ci pub(crate) shebang: TokenTree, 74ea88969fSopenharmony_ci pub(crate) group: TokenTree, 75ea88969fSopenharmony_ci pub(crate) path: Option<Ident>, 76ea88969fSopenharmony_ci} 77ea88969fSopenharmony_ci 78ea88969fSopenharmony_ciimpl Attribute { 79ea88969fSopenharmony_ci pub(crate) fn path_is_ident(&self, ident: &str) -> bool { 80ea88969fSopenharmony_ci self.path.as_ref().map_or(false, |p| *p == ident) 81ea88969fSopenharmony_ci } 82ea88969fSopenharmony_ci} 83ea88969fSopenharmony_ci 84ea88969fSopenharmony_ciimpl ToTokens for Attribute { 85ea88969fSopenharmony_ci fn to_tokens(&self, ts: &mut TokenStream) { 86ea88969fSopenharmony_ci self.shebang.to_tokens(ts); 87ea88969fSopenharmony_ci self.group.to_tokens(ts); 88ea88969fSopenharmony_ci } 89ea88969fSopenharmony_ci} 90