1pub mod at;
2mod group_node;
3mod interp_node;
4mod pipe_node;
5mod tokens_node;
6
7pub use at::*;
8pub use group_node::GroupNode;
9pub use interp_node::InterpNode;
10pub use pipe_node::PipeNode;
11pub use tokens_node::TokensNode;
12
13use proc_macro2::Ident;
14use proc_macro2::Span;
15use proc_macro2::TokenStream;
16use proc_macro2::TokenTree;
17
18use quote::ToTokens;
19use quote::quote;
20
21use syn::Token;
22use syn::parse::Parse;
23use syn::parse::ParseStream;
24
25use crate::Expand;
26use crate::ident;
27
28pub enum Node {
29 Tokens(TokensNode),
30 Interp(InterpNode),
31 At(AtNode),
32 Group(GroupNode),
33}
34
35impl Node {
36 pub fn is_tokens(&self) -> bool {
37 matches!(self, Self::Tokens(_))
38 }
39
40 pub fn is_interp(&self) -> bool {
41 matches!(self, Self::Interp(_))
42 }
43
44 pub fn is_at(&self) -> bool {
45 matches!(self, Self::At(_))
46 }
47
48 pub fn is_group(&self) -> bool {
49 matches!(self, Self::Group(_))
50 }
51}
52
53impl Node {
54 pub fn as_tokens(&self) -> &TokensNode {
55 match self {
56 Self::Tokens(v) => v,
57 _ => panic!("called as_tokens on non-Tokens node"),
58 }
59 }
60
61 pub fn as_interp(&self) -> &InterpNode {
62 match self {
63 Self::Interp(v) => v,
64 _ => panic!("called as_interp on non-Interp node"),
65 }
66 }
67
68 pub fn as_at(&self) -> &AtNode {
69 match self {
70 Self::At(v) => v,
71 _ => panic!("called as_at on non-At node"),
72 }
73 }
74
75 pub fn as_group(&self) -> &GroupNode {
76 match self {
77 Self::Group(v) => v,
78 _ => panic!("called as_group on non-Group node"),
79 }
80 }
81}
82
83impl Node {
84 pub fn span(&self) -> Span {
85 match self {
86 Self::Tokens(v) => v.span(),
87 Self::Interp(v) => v.span(),
88 Self::At(v) => v.span(),
89 Self::Group(v) => v.span(),
90 }
91 }
92}
93
94impl From<TokensNode> for Node {
95 fn from(v: TokensNode) -> Self {
96 Self::Tokens(v)
97 }
98}
99
100impl From<InterpNode> for Node {
101 fn from(v: InterpNode) -> Self {
102 Self::Interp(v)
103 }
104}
105
106impl From<AtNode> for Node {
107 fn from(v: AtNode) -> Self {
108 Self::At(v)
109 }
110}
111
112impl From<GroupNode> for Node {
113 fn from(v: GroupNode) -> Self {
114 Self::Group(v)
115 }
116}
117
118impl Node {
119 pub fn parse_brace(input: ParseStream) -> syn::Result<Self> {
120 let content;
121 let brace = syn::braced!(content in input);
122 let span = brace.span.join();
123
124 let fork = content.fork();
125 let is_interp = if fork.peek(syn::token::Brace) {
126 let inner;
127 syn::braced!(inner in fork);
128 fork.is_empty()
129 } else {
130 false
131 };
132
133 if is_interp {
134 let inner;
135 syn::braced!(inner in content);
136
137 let mut expr = TokenStream::new();
138 let mut pipes = Vec::new();
139
140 while !inner.is_empty() {
141 if inner.peek(Token![|]) {
142 inner.parse::<Token![|]>()?;
143 pipes.push(inner.parse::<PipeNode>()?);
144 } else if pipes.is_empty() {
145 let tt: TokenTree = inner.parse()?;
146 tt.to_tokens(&mut expr);
147 } else {
148 break;
149 }
150 }
151
152 if expr.is_empty() {
153 return Err(syn::Error::new(span, "empty interpolation"));
154 }
155
156 Ok(InterpNode { span, expr, pipes }.into())
157 } else {
158 let body = content.parse::<Element>()?;
159 Ok(GroupNode {
160 span,
161 delimiter: proc_macro2::Delimiter::Brace,
162 body: Box::new(body),
163 }
164 .into())
165 }
166 }
167}
168
169impl Expand for Node {
170 fn expand(&self, output: &Ident, idents: &mut ident::Iter) -> TokenStream {
171 match self {
172 Self::Tokens(v) => v.expand(output, idents),
173 Self::Interp(v) => v.expand(output, idents),
174 Self::At(v) => v.expand(output, idents),
175 Self::Group(v) => v.expand(output, idents),
176 }
177 }
178}
179
180pub struct Element {
181 pub nodes: Vec<Node>,
182}
183
184impl Element {
185 pub fn span(&self) -> Span {
186 self.nodes
187 .first()
188 .map(|n| n.span())
189 .unwrap_or_else(Span::call_site)
190 }
191}
192
193impl Expand for Element {
194 fn expand(&self, output: &Ident, idents: &mut ident::Iter) -> TokenStream {
195 let mut result = TokenStream::new();
196
197 for node in &self.nodes {
198 result.extend(node.expand(output, idents));
199 }
200
201 result
202 }
203}
204
205impl Element {
206 pub fn to_token_stream(&self) -> TokenStream {
207 let mut idents = ident::Iter::new();
208 let output = idents.next().unwrap();
209 let expanded = self.expand(&output, &mut idents);
210
211 quote! {
212 {
213 let mut #output = ::zyn::proc_macro2::TokenStream::new();
214 #expanded
215 #output
216 }
217 }
218 }
219}
220
221impl Parse for Element {
222 fn parse(input: ParseStream) -> syn::Result<Self> {
223 let mut nodes = Vec::new();
224 let mut pending = TokenStream::new();
225
226 while !input.is_empty() {
227 if input.peek(Token![@]) {
228 flush(&mut pending, &mut nodes);
229 nodes.push(input.parse::<AtNode>()?.into());
230 } else if input.peek(syn::token::Brace) {
231 flush(&mut pending, &mut nodes);
232 nodes.push(Node::parse_brace(input)?);
233 } else if input.peek(syn::token::Paren) || input.peek(syn::token::Bracket) {
234 flush(&mut pending, &mut nodes);
235 nodes.push(input.parse::<GroupNode>()?.into());
236 } else {
237 let tt: TokenTree = input.parse()?;
238 tt.to_tokens(&mut pending);
239 }
240 }
241
242 flush(&mut pending, &mut nodes);
243 Ok(Self { nodes })
244 }
245}
246
247fn flush(pending: &mut TokenStream, nodes: &mut Vec<Node>) {
248 if pending.is_empty() {
249 return;
250 }
251
252 let span = pending
253 .clone()
254 .into_iter()
255 .next()
256 .map(|tt| tt.span())
257 .unwrap_or_else(Span::call_site);
258
259 nodes.push(
260 TokensNode {
261 span,
262 stream: pending.clone(),
263 }
264 .into(),
265 );
266
267 *pending = TokenStream::new();
268}