1macro_rules! quote {
2 ($($x:tt)*) => {{
3 use proc_macro::*;
4 quote_inner!([] [] $($x)*)
5 }};
6}
7
8macro_rules! quote_inner {
9 ([] []) => {
10 TokenStream::new()
11 };
12 ([] [$($tokens:tt)+]) => {
13 TokenStream::from_iter([$($tokens)+])
14 };
15 ([$($streams:tt)+] []) => {
16 TokenStream::from_iter([$($streams)+])
17 };
18 ([$($streams:tt)+] [$($tokens:tt)+]) => {
19 TokenStream::from_iter([
20 $($streams)+
21 TokenStream::from_iter([$($tokens)+])
22 ])
23 };
24
25 ([$($streams:tt)*] [] #S($e:expr) $($tail:tt)*) => {
27 quote_inner!([
28 $($streams)*
29 $crate::to_tokens::ToTokenStream::into_token_stream($e),
30 ] [] $($tail)*)
31 };
32 ([$($streams:tt)*] [$($tokens:tt)+] #S($e:expr) $($tail:tt)*) => {
33 quote_inner!([
34 $($streams)*
35 TokenStream::from_iter([$($tokens)+]),
36 $crate::to_tokens::ToTokenStream::into_token_stream($e),
37 ] [] $($tail)*)
38 };
39 ($streams:tt [$($tokens:tt)*] #($e:expr) $($tail:tt)*) => {
40 quote_inner!($streams [
41 $($tokens)*
42 $crate::to_tokens::ToTokenTree::into_token_tree($e),
43 ] $($tail)*)
44 };
45 ($streams:tt [$($tokens:tt)*] #[$($inner:tt)*] $($tail:tt)*) => {
46 quote_inner!($streams [
47 $($tokens)*
48 TokenTree::from(Punct::new('#', Spacing::Alone)),
49 TokenTree::from(Group::new(
50 Delimiter::Bracket,
51 quote_inner!([] [] $($inner)*),
52 )),
53 ] $($tail)*)
54 };
55
56 ($streams:tt [$($tokens:tt)*] :: $($tail:tt)*) => {
57 quote_inner!($streams [
58 $($tokens)*
59 TokenTree::from(Punct::new(':', Spacing::Joint)),
60 TokenTree::from(Punct::new(':', Spacing::Alone)),
61 ] $($tail)*)
62 };
63 ($streams:tt [$($tokens:tt)*] >> $($tail:tt)*) => {
64 quote_inner!($streams [
65 $($tokens)*
66 TokenTree::from(Punct::new('>', Spacing::Joint)),
67 TokenTree::from(Punct::new('>', Spacing::Alone)),
68 ] $($tail)*)
69 };
70 ($streams:tt [$($tokens:tt)*] -> $($tail:tt)*) => {
71 quote_inner!($streams [
72 $($tokens)*
73 TokenTree::from(Punct::new('-', Spacing::Joint)),
74 TokenTree::from(Punct::new('>', Spacing::Alone)),
75 ] $($tail)*)
76 };
77 ($streams:tt [$($tokens:tt)*] $l:lifetime $($tail:tt)*) => {
78 quote_inner!($streams [
79 $($tokens)*
80 TokenTree::from(Punct::new('\'', Spacing::Joint)),
81 TokenTree::from(Ident::new(
82 stringify!($l).trim_start_matches('\''),
83 Span::mixed_site(),
84 )),
85 ] $($tail)*)
86 };
87
88 ($streams:tt [$($tokens:tt)*] $first:tt :: $($tail:tt)*) => {
89 quote_inner!($streams [
90 $($tokens)*
91 quote_token!($first),
92 TokenTree::from(Punct::new(':', Spacing::Joint)),
93 TokenTree::from(Punct::new(':', Spacing::Alone)),
94 ] $($tail)*)
95 };
96 ($streams:tt [$($tokens:tt)*] $first:tt -> $($tail:tt)*) => {
97 quote_inner!($streams [
98 $($tokens)*
99 quote_token!($first),
100 TokenTree::from(Punct::new('-', Spacing::Joint)),
101 TokenTree::from(Punct::new('>', Spacing::Alone)),
102 ] $($tail)*)
103 };
104 ($streams:tt [$($tokens:tt)*] $first:tt # $($tail:tt)*) => {
105 quote_inner!($streams [
106 $($tokens)*
107 quote_token!($first),
108 ] # $($tail)*)
109 };
110 ($streams:tt [$($tokens:tt)*] $first:tt $second:tt $($tail:tt)*) => {
111 quote_inner!($streams [
112 $($tokens)*
113 quote_token!($first),
114 quote_token!($second),
115 ] $($tail)*)
116 };
117 ($streams:tt [$($tokens:tt)*] $token:tt $($tail:tt)*) => {
118 quote_inner!($streams [
119 $($tokens)*
120 quote_token!($token),
121 ] $($tail)*)
122 };
123}
124
125macro_rules! quote_token {
126 ($i:ident) => {
127 TokenTree::from(Ident::new(stringify!($i), Span::mixed_site()))
128 };
129 (0) => {
130 TokenTree::from(Literal::usize_unsuffixed(0))
131 };
132 ($l:literal) => {
133 TokenTree::from(Literal::string(&$l))
134 };
135 (($($inner:tt)*)) => {
136 TokenTree::from(Group::new(
137 Delimiter::Parenthesis,
138 quote_inner!([] [] $($inner)*),
139 ))
140 };
141 ([$($inner:tt)*]) => {
142 TokenTree::from(Group::new(
143 Delimiter::Bracket,
144 quote_inner!([] [] $($inner)*),
145 ))
146 };
147 ({$($inner:tt)*}) => {
148 TokenTree::from(Group::new(
149 Delimiter::Brace,
150 quote_inner!([] [] $($inner)*),
151 ))
152 };
153 (:) => { TokenTree::from(Punct::new(':', Spacing::Alone)) };
154 (=) => { TokenTree::from(Punct::new('=', Spacing::Alone)) };
155 (;) => { TokenTree::from(Punct::new(';', Spacing::Alone)) };
156 (,) => { TokenTree::from(Punct::new(',', Spacing::Alone)) };
157 (.) => { TokenTree::from(Punct::new('.', Spacing::Alone)) };
158 (&) => { TokenTree::from(Punct::new('&', Spacing::Alone)) };
159 (<) => { TokenTree::from(Punct::new('<', Spacing::Alone)) };
160 (>) => { TokenTree::from(Punct::new('>', Spacing::Alone)) };
161 (?) => { TokenTree::from(Punct::new('?', Spacing::Alone)) };
162 (!) => { TokenTree::from(Punct::new('!', Spacing::Alone)) };
163 (|) => { TokenTree::from(Punct::new('|', Spacing::Alone)) };
164 (*) => { TokenTree::from(Punct::new('*', Spacing::Alone)) };
165 (+) => { TokenTree::from(Punct::new('+', Spacing::Alone)) };
166}