1use proc_macro::{Ident, TokenStream, TokenTree};
2use std::iter;
3
4macro_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
15macro_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
86pub trait Tokens {
87 fn extend(tokens: &mut TokenStream, var: &Self);
88}
89
90impl Tokens for Ident {
91 fn extend(tokens: &mut TokenStream, var: &Self) {
92 tokens.extend(iter:iter::once(TokenTree::Ident(var.clone())));
93 }
94}
95
96impl Tokens for TokenStream {
97 fn extend(tokens: &mut TokenStream, var: &Self) {
98 tokens.extend(iter:var.clone());
99 }
100}
101
102impl<T: Tokens> Tokens for Option<T> {
103 fn extend(tokens: &mut TokenStream, var: &Self) {
104 if let Some(var: &T) = var {
105 T::extend(tokens, var);
106 }
107 }
108}
109
110impl<T: Tokens> Tokens for &T {
111 fn extend(tokens: &mut TokenStream, var: &Self) {
112 T::extend(tokens, var);
113 }
114}
115