1 use proc_macro::{Ident, TokenStream, TokenTree}; 2 use std::iter; 3 4 macro_rules! quote { 5 () => { 6 ::proc_macro::TokenStream::new() 7 }; 8 ($($tt:tt)*) => {{ 9 let mut tokens = ::proc_macro::TokenStream::new(); 10 quote_each_token!(tokens $($tt)*); 11 tokens 12 }}; 13 } 14 15 macro_rules! quote_each_token { 16 ($tokens:ident # $var:ident $($rest:tt)*) => { 17 $crate::quote::Tokens::extend(&mut $tokens, &$var); 18 quote_each_token!($tokens $($rest)*); 19 }; 20 ($tokens:ident $ident:ident $($rest:tt)*) => { 21 <::proc_macro::TokenStream as ::std::iter::Extend<_>>::extend( 22 &mut $tokens, 23 ::std::iter::once( 24 ::proc_macro::TokenTree::Ident( 25 ::proc_macro::Ident::new( 26 stringify!($ident), 27 ::proc_macro::Span::call_site(), 28 ), 29 ), 30 ), 31 ); 32 quote_each_token!($tokens $($rest)*); 33 }; 34 ($tokens:ident ( $($inner:tt)* ) $($rest:tt)*) => { 35 <::proc_macro::TokenStream as ::std::iter::Extend<_>>::extend( 36 &mut $tokens, 37 ::std::iter::once( 38 ::proc_macro::TokenTree::Group( 39 ::proc_macro::Group::new( 40 ::proc_macro::Delimiter::Parenthesis, 41 quote!($($inner)*), 42 ), 43 ), 44 ), 45 ); 46 quote_each_token!($tokens $($rest)*); 47 }; 48 ($tokens:ident [ $($inner:tt)* ] $($rest:tt)*) => { 49 <::proc_macro::TokenStream as ::std::iter::Extend<_>>::extend( 50 &mut $tokens, 51 ::std::iter::once( 52 ::proc_macro::TokenTree::Group( 53 ::proc_macro::Group::new( 54 ::proc_macro::Delimiter::Bracket, 55 quote!($($inner)*), 56 ), 57 ), 58 ), 59 ); 60 quote_each_token!($tokens $($rest)*); 61 }; 62 ($tokens:ident { $($inner:tt)* } $($rest:tt)*) => { 63 <::proc_macro::TokenStream as ::std::iter::Extend<_>>::extend( 64 &mut $tokens, 65 ::std::iter::once( 66 ::proc_macro::TokenTree::Group( 67 ::proc_macro::Group::new( 68 ::proc_macro::Delimiter::Brace, 69 quote!($($inner)*), 70 ), 71 ), 72 ), 73 ); 74 quote_each_token!($tokens $($rest)*); 75 }; 76 ($tokens:ident $punct:tt $($rest:tt)*) => { 77 <::proc_macro::TokenStream as ::std::iter::Extend<_>>::extend( 78 &mut $tokens, 79 stringify!($punct).parse::<::proc_macro::TokenStream>(), 80 ); 81 quote_each_token!($tokens $($rest)*); 82 }; 83 ($tokens:ident) => {}; 84 } 85 86 pub trait Tokens { extend(tokens: &mut TokenStream, var: &Self)87 fn extend(tokens: &mut TokenStream, var: &Self); 88 } 89 90 impl Tokens for Ident { extend(tokens: &mut TokenStream, var: &Self)91 fn extend(tokens: &mut TokenStream, var: &Self) { 92 tokens.extend(iter::once(TokenTree::Ident(var.clone()))); 93 } 94 } 95 96 impl Tokens for TokenStream { extend(tokens: &mut TokenStream, var: &Self)97 fn extend(tokens: &mut TokenStream, var: &Self) { 98 tokens.extend(var.clone()); 99 } 100 } 101 102 impl<T: Tokens> Tokens for Option<T> { extend(tokens: &mut TokenStream, var: &Self)103 fn extend(tokens: &mut TokenStream, var: &Self) { 104 if let Some(var) = var { 105 T::extend(tokens, var); 106 } 107 } 108 } 109 110 impl<T: Tokens> Tokens for &T { extend(tokens: &mut TokenStream, var: &Self)111 fn extend(tokens: &mut TokenStream, var: &Self) { 112 T::extend(tokens, var); 113 } 114 } 115