1 macro_rules! quote {
2     () => (::proc_macro::TokenStream::new());
3     ($($x:tt)*) => (quote_internal!([] $($x)*));
4 }
5 
6 macro_rules! quote_internal {
7     // Base case
8     ([]) => (::proc_macro::TokenStream::new());
9     ([$($expanded:tt)*]) => {
10         [$($expanded)*].iter().cloned().collect::<::proc_macro::TokenStream>()
11     };
12 
13     // Symbols and symbol pairs
14     ([$($expanded:tt)*] :: $($tail:tt)*) => (quote_internal!([$($expanded)*
15         ::proc_macro::TokenStream::from(::proc_macro::TokenTree::from(
16             ::proc_macro::Punct::new(':', ::proc_macro::Spacing::Joint)
17         )),
18         ::proc_macro::TokenStream::from(::proc_macro::TokenTree::from(
19             ::proc_macro::Punct::new(':', ::proc_macro::Spacing::Alone)
20         )),
21     ] $($tail)*));
22     ([$($expanded:tt)*] .. $($tail:tt)*) => (quote_internal!([$($expanded)*
23         ::proc_macro::TokenStream::from(::proc_macro::TokenTree::from(
24             ::proc_macro::Punct::new('.', ::proc_macro::Spacing::Joint)
25         )),
26         ::proc_macro::TokenStream::from(::proc_macro::TokenTree::from(
27             ::proc_macro::Punct::new('.', ::proc_macro::Spacing::Alone)
28         )),
29     ] $($tail)*));
30     ([$($expanded:tt)*] : $($tail:tt)*) => (quote_internal!([$($expanded)*
31         ::proc_macro::TokenStream::from(::proc_macro::TokenTree::from(
32             ::proc_macro::Punct::new(':', ::proc_macro::Spacing::Alone)
33         )),
34     ] $($tail)*));
35     ([$($expanded:tt)*] = $($tail:tt)*) => (quote_internal!([$($expanded)*
36         ::proc_macro::TokenStream::from(::proc_macro::TokenTree::from(
37             ::proc_macro::Punct::new('=', ::proc_macro::Spacing::Alone)
38         )),
39     ] $($tail)*));
40     ([$($expanded:tt)*] ; $($tail:tt)*) => (quote_internal!([$($expanded)*
41         ::proc_macro::TokenStream::from(::proc_macro::TokenTree::from(
42             ::proc_macro::Punct::new(';', ::proc_macro::Spacing::Alone)
43         )),
44     ] $($tail)*));
45     ([$($expanded:tt)*] , $($tail:tt)*) => (quote_internal!([$($expanded)*
46         ::proc_macro::TokenStream::from(::proc_macro::TokenTree::from(
47             ::proc_macro::Punct::new(',', ::proc_macro::Spacing::Alone)
48         )),
49     ] $($tail)*));
50     ([$($expanded:tt)*] . $($tail:tt)*) => (quote_internal!([$($expanded)*
51         ::proc_macro::TokenStream::from(::proc_macro::TokenTree::from(
52             ::proc_macro::Punct::new('.', ::proc_macro::Spacing::Alone)
53         )),
54     ] $($tail)*));
55     ([$($expanded:tt)*] & $($tail:tt)*) => (quote_internal!([$($expanded)*
56         ::proc_macro::TokenStream::from(::proc_macro::TokenTree::from(
57             ::proc_macro::Punct::new('&', ::proc_macro::Spacing::Alone)
58         )),
59     ] $($tail)*));
60     ([$($expanded:tt)*] '_ $($tail:tt)*) => (quote_internal!([$($expanded)*
61         ::proc_macro::TokenStream::from(::proc_macro::TokenTree::from(
62             ::proc_macro::Punct::new('\'', ::proc_macro::Spacing::Joint)
63         )),
64         ::proc_macro::TokenStream::from(::proc_macro::TokenTree::from(
65             ::proc_macro::Ident::new("_", ::proc_macro::Span::mixed_site())
66         )),
67     ] $($tail)*));
68     ([$($expanded:tt)*] < $($tail:tt)*) => (quote_internal!([$($expanded)*
69         ::proc_macro::TokenStream::from(::proc_macro::TokenTree::from(
70             ::proc_macro::Punct::new('<', ::proc_macro::Spacing::Alone)
71         )),
72     ] $($tail)*));
73     ([$($expanded:tt)*] > $($tail:tt)*) => (quote_internal!([$($expanded)*
74         ::proc_macro::TokenStream::from(::proc_macro::TokenTree::from(
75             ::proc_macro::Punct::new('>', ::proc_macro::Spacing::Alone)
76         )),
77     ] $($tail)*));
78 
79     // Identifier
80     ([$($expanded:tt)*] $i:ident $($tail:tt)*) => (quote_internal!([$($expanded)*
81         ::proc_macro::TokenStream::from(::proc_macro::TokenTree::from(
82             ::proc_macro::Ident::new(stringify!($i), ::proc_macro::Span::mixed_site())
83         )),
84     ] $($tail)*));
85 
86     // Groups
87     ([$($expanded:tt)*] ($($inner:tt)*) $($tail:tt)*) => (quote_internal!([$($expanded)*
88         ::proc_macro::TokenStream::from(::proc_macro::TokenTree::from(::proc_macro::Group::new(
89             ::proc_macro::Delimiter::Parenthesis,
90             quote_internal!([] $($inner)*))
91         )),
92     ] $($tail)*));
93     ([$($expanded:tt)*] {$($inner:tt)*} $($tail:tt)*) => (quote_internal!([$($expanded)*
94         ::proc_macro::TokenStream::from(::proc_macro::TokenTree::from(::proc_macro::Group::new(
95             ::proc_macro::Delimiter::Brace,
96             quote_internal!([] $($inner)*)
97         ))),
98     ] $($tail)*));
99     ([$($expanded:tt)*] [$($inner:tt)*] $($tail:tt)*) => (quote_internal!([$($expanded)*
100         ::proc_macro::TokenStream::from(::proc_macro::TokenTree::from(::proc_macro::Group::new(
101             ::proc_macro::Delimiter::Bracket,
102             quote_internal!([] $($inner)*)
103         ))),
104     ] $($tail)*));
105 
106     // Interpolated values
107     ([$($expanded:tt)*] #($e:expr) $($tail:tt)*) => (quote_internal!([$($expanded)*
108         $crate::to_tokens::ToTokens::into_token_stream($e),
109     ] $($tail)*));
110 }
111