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 { |
87 | fn extend(tokens: &mut TokenStream, var: &Self); |
88 | } |
89 | |
90 | impl Tokens for Ident { |
91 | fn extend(tokens: &mut TokenStream, var: &Self) { |
92 | tokens.extend(iter:iter::once(TokenTree::Ident(var.clone()))); |
93 | } |
94 | } |
95 | |
96 | impl Tokens for TokenStream { |
97 | fn extend(tokens: &mut TokenStream, var: &Self) { |
98 | tokens.extend(iter:var.clone()); |
99 | } |
100 | } |
101 | |
102 | impl<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 | |
110 | impl<T: Tokens> Tokens for &T { |
111 | fn extend(tokens: &mut TokenStream, var: &Self) { |
112 | T::extend(tokens, var); |
113 | } |
114 | } |
115 | |