1use proc_macro2::{Span, TokenStream};
4use quote::{format_ident, quote, quote_spanned, ToTokens};
5use std::convert::{TryFrom, TryInto};
6use syn::parse::{Parse, ParseStream};
7use syn::spanned::Spanned;
8use syn::{AttrStyle, Attribute, Expr, Fields, Ident, Path, Result, Token, Type};
9
10pub(crate) fn generate_fn_body(
11 base_tyname: &impl ToTokens,
12 fields: Fields,
13 with_return: bool,
14) -> Result<TokenStream> {
15 let initialize_self = initialize_type_or_variant(base_tyname, &fields);
16 let parse_fields = fields
17 .into_iter()
18 .enumerate()
19 .map(parse_field)
20 .collect::<Result<Vec<_>>>()?;
21
22 let maybe_return = match with_return {
23 true => Token).into_token_stream(),
24 false => TokenStream::new(),
25 };
26
27 Ok(quote! {
28 #( #parse_fields )*
29
30 #maybe_return Ok(#initialize_self)
31 })
32}
33
34enum FieldAttr {
35 Inside(Ident),
36 Tree(TreeKind),
37 Call(Expr),
38 ParseTerminated(Path),
39 Peek(PeekAttr),
40 Prefix(NeighborAttr),
41 Postfix(NeighborAttr),
42}
43
44enum TreeKind {
45 Paren,
46 Bracket,
47 Brace,
48}
49
50enum ParseMethod {
51 Tree(TreeKind, Span),
52 Call(Expr),
53 ParseTerminated(Path),
54 Default,
55}
56
57enum PeekAttr {
58 Peek(Expr),
59 PeekWith(Expr),
60 ParseIf(Expr),
61}
62
63struct NeighborAttr {
70 parse_ty: Type,
71 maybe_named: Option<Ident>,
72 maybe_inside: Option<Ident>,
73}
74
75impl Parse for NeighborAttr {
76 fn parse(input: ParseStream) -> syn::Result<Self> {
77 let parse_ty = input.parse()?;
78 let as_token: Option<Token![as]> = input.parse()?;
79 let maybe_named = match as_token.is_some() {
80 true => Some(input.parse()?),
81 false => None,
82 };
83
84 let in_token: Option<Token![in]> = input.parse()?;
85 let maybe_inside = match in_token.is_some() {
86 true => Some(input.parse()?),
87 false => None,
88 };
89
90 Ok(NeighborAttr {
91 parse_ty,
92 maybe_named,
93 maybe_inside,
94 })
95 }
96}
97
98impl ParseMethod {
99 fn is_default(&self) -> bool {
100 matches!(self, Self::Default)
101 }
102}
103
104struct FieldAttrs {
105 prefix: Vec<NeighborAttr>,
106 postfix: Vec<NeighborAttr>,
107 inside: Option<Ident>,
108 parse_method: ParseMethod,
109 peek: Option<PeekAttr>,
110}
111
112struct ParseField {
113 required_var_defs: Option<Ident>,
114 parse_expr: TokenStream,
115 pre_parse: TokenStream,
116 post_parse: TokenStream,
117}
118
119fn initialize_type_or_variant(name: &impl ToTokens, fields: &syn::Fields) -> TokenStream {
130 use syn::Fields::{Named, Unit, Unnamed};
131
132 match fields {
133 Unit => name.to_token_stream(),
134 Named(fields) => {
135 let iter = fields.named.iter().map(|f| {
136 f.ident
137 .as_ref()
138 .expect("named field was unnamed! the impossible is now possible!")
139 });
140 quote! {
141 #name { #( #iter, )* }
142 }
143 }
144 Unnamed(fields) => {
145 let iter = fields
146 .unnamed
147 .iter()
148 .enumerate()
149 .map(|(i, f)| field_name_for_idx(i, f.span()));
150 quote! {
151 #name( #( #iter, )* )
152 }
153 }
154 }
155}
156
157fn field_name_for_idx(idx: usize, span: Span) -> Ident {
158 format_ident!("_field_{}", idx, span = span)
159}
160
161fn parse_field((idx, field): (usize, syn::Field)) -> Result<TokenStream> {
162 let span = field.span();
163
164 let assigned_name = field.ident.unwrap_or_else(|| field_name_for_idx(idx, span));
165
166 let attrs = (field.attrs)
167 .into_iter()
168 .filter_map(try_as_field_attr)
169 .collect::<Result<Vec<_>>>()?
170 .try_into()?;
171
172 let ParseField {
173 required_var_defs,
174 parse_expr,
175 pre_parse,
176 post_parse,
177 } = handle_field_attrs(&assigned_name, field.ty.span(), attrs);
178
179 let required_var_defs = required_var_defs.into_iter();
181 let field_ty = field.ty;
182 Ok(quote_spanned! {
183 span=>
184 #( let #required_var_defs; )*
185 #pre_parse
186 let #assigned_name: #field_ty = #parse_expr;
187 #post_parse
188 })
189}
190
191fn try_as_field_attr(attr: Attribute) -> Option<Result<(FieldAttr, Span)>> {
192 let name = attr.path().get_ident()?.to_string();
193 let span = attr.span();
194
195 macro_rules! expect_outer_attr {
196 ($name:literal) => {{
197 if let AttrStyle::Inner(_) = attr.style {
198 return Some(Err(syn::Error::new(
199 span,
200 concat!(
201 "the `#[",
202 $name,
203 "]` parsing attribute can only be used as an outer attribute"
204 ),
205 )));
206 }
207 }};
208 }
209
210 #[rustfmt::skip]
211 macro_rules! expect_no_attr_args {
212 ($name:expr) => {{
213 use syn::Meta::*;
214 match attr.meta {
215 List(args) => return Some(Err(syn::Error::new(
216 span,
217 format!("the `#[{}]` parsing attribute does not expect arguments {:?}", $name, args.tokens.to_string()),
218 ))),
219 NameValue(val) => return Some(Err(syn::Error::new(
220 span,
221 format!("the `#[{}]` parsing attribute does not expect value {:?}", $name, val.value.to_token_stream().to_string()),
222 ))),
223 _ => {}
224 }
225 }};
226 }
227
228 macro_rules! expect_parenthesis {
229 ($attr_lit:literal) => {{
230 use syn::{MacroDelimiter::*, Meta};
231 match attr.meta {
232 Meta::List(ref ml) => match ml.delimiter {
233 Paren(_) => {}
234 Brace(_) => {
235 return Some(Err(syn::Error::new(
236 span,
237 concat!(
238 "expected parenthesis in `#[",
239 $attr_lit,
240 "(...)]`, found braces"
241 ),
242 )))
243 }
244 Bracket(_) => {
245 return Some(Err(syn::Error::new(
246 span,
247 concat!(
248 "expected parenthesis in `#[",
249 $attr_lit,
250 "(...)]`, found brackets"
251 ),
252 )))
253 }
254 },
255 _ => {
256 return Some(Err(syn::Error::new(
257 span,
258 concat!("expected parenthesis in `#[", $attr_lit, "(...)]`"),
259 )))
260 }
261 }
262 }};
263 }
264 match name.as_str() {
265 "inside" => {
266 expect_outer_attr!("inside(...)");
267 expect_parenthesis!("inside");
268 Some(
269 attr.parse_args()
270 .map(move |id| (FieldAttr::Inside(id), span)),
271 )
272 }
273 "call" => {
274 expect_outer_attr!("call(...)");
275 expect_parenthesis!("call");
276 Some(attr.parse_args().map(move |id| (FieldAttr::Call(id), span)))
277 }
278 "parse_terminated" => {
279 expect_outer_attr!("parse_terminated(...)");
280 expect_parenthesis!("parse_terminated");
281 Some(
282 attr.parse_args()
283 .map(move |id| (FieldAttr::ParseTerminated(id), span)),
284 )
285 }
286 "paren" => {
287 expect_outer_attr!("paren");
288 expect_no_attr_args!("paren");
289 Some(Ok((FieldAttr::Tree(TreeKind::Paren), span)))
290 }
291 "bracket" => {
292 expect_outer_attr!("bracket");
293 expect_no_attr_args!("bracket");
294 Some(Ok((FieldAttr::Tree(TreeKind::Bracket), span)))
295 }
296 "brace" => {
297 expect_outer_attr!("brace");
298 expect_no_attr_args!("brace");
299 Some(Ok((FieldAttr::Tree(TreeKind::Brace), span)))
300 }
301 "peek" => {
302 expect_outer_attr!("peek(...)");
303 expect_parenthesis!("peek");
304 Some(
305 attr.parse_args()
306 .map(move |id| (FieldAttr::Peek(PeekAttr::Peek(id)), span)),
307 )
308 }
309 "peek_with" => {
310 expect_outer_attr!("peek_with(...)");
311 expect_parenthesis!("peek_with");
312 Some(
313 attr.parse_args()
314 .map(move |id| (FieldAttr::Peek(PeekAttr::PeekWith(id)), span)),
315 )
316 }
317 "parse_if" => {
318 expect_outer_attr!("parse_if(...)");
319 expect_parenthesis!("parse_if");
320 Some(
321 attr.parse_args()
322 .map(move |id| (FieldAttr::Peek(PeekAttr::ParseIf(id)), span)),
323 )
324 }
325 "prefix" => {
326 expect_outer_attr!("prefix(...)");
327 expect_parenthesis!("prefix");
328 Some(
329 attr.parse_args()
330 .map(move |id| (FieldAttr::Prefix(id), span)),
331 )
332 }
333 "postfix" => {
334 expect_outer_attr!("postifx(...)");
335 expect_parenthesis!("postfix");
336 Some(
337 attr.parse_args()
338 .map(move |id| (FieldAttr::Postfix(id), span)),
339 )
340 }
341 _ => None,
342 }
343}
344
345impl TryFrom<Vec<(FieldAttr, Span)>> for FieldAttrs {
346 type Error = syn::Error;
347
348 fn try_from(vec: Vec<(FieldAttr, Span)>) -> Result<Self> {
349 use FieldAttr::{Call, Inside, ParseTerminated, Peek, Postfix, Prefix, Tree};
350
351 let mut inside = None;
352 let mut peek = None;
353 let mut parse_method = ParseMethod::Default;
354 let mut prefix = Vec::new();
355 let mut postfix = Vec::new();
356
357 for (attr, span) in vec {
358 match attr {
359 Tree(_) | Call(_) | ParseTerminated(_) if !parse_method.is_default() => {
360 return Err(syn::Error::new(span, "parsing method specified twice"));
361 }
362 Inside(_) if inside.is_some() => {
363 return Err(syn::Error::new(
364 span,
365 "containing parse stream is specified twice",
366 ));
367 }
368 Peek(_) if peek.is_some() => {
369 return Err(syn::Error::new(span, "peeking can only be specified once"));
370 }
371
372 Call(expr) => parse_method = ParseMethod::Call(expr),
373 ParseTerminated(path) => parse_method = ParseMethod::ParseTerminated(path),
374 Tree(kind) => parse_method = ParseMethod::Tree(kind, span),
375 Inside(name) => inside = Some(name),
376 Peek(p) => peek = Some(p),
377
378 Prefix(_) if inside.is_some() => {
379 return Err(syn::Error::new(
380 span,
381 "`#[prefix]` cannot be used after `#[inside]`. Perhaps try `#[prefix(<Type> in <token>)]`?",
382 ));
383 }
384
385 Postfix(_) if inside.is_some() => {
386 return Err(syn::Error::new(
387 span,
388 "`#[postfix]` cannot be used after `#[inside]`. Perhaps try `#[prefix(<Type> in <token>)]`?",
389 ));
390 }
391
392 Prefix(attr) => prefix.push(attr),
393 Postfix(attr) => postfix.push(attr),
394 }
395 }
396
397 Ok(FieldAttrs {
398 prefix,
399 postfix,
400 inside,
401 parse_method,
402 peek,
403 })
404 }
405}
406
407fn handle_field_attrs(field_name: &Ident, ty_span: Span, attrs: FieldAttrs) -> ParseField {
408 use ParseMethod::{Call, Default, ParseTerminated, Tree};
409
410 let input_source = attrs
411 .inside
412 .as_ref()
413 .map(tree_name)
414 .unwrap_or_else(crate::parse_input);
415
416 let required_var_defs;
417 let mut parse_expr;
418
419 match attrs.parse_method {
420 Default => {
421 required_var_defs = None;
422 parse_expr = quote_spanned! { ty_span=> #input_source.parse()? };
423 }
424 Call(expr) => {
425 required_var_defs = None;
426 parse_expr = quote_spanned!(expr.span()=> {
427 let result: ::syn::Result<_> = (#expr)(&#input_source);
428 result?
429 });
430 }
431 ParseTerminated(path) => {
432 required_var_defs = None;
433 parse_expr = quote_spanned! { path.span()=> #input_source.parse_terminated(#path)? };
434 }
435 Tree(tree_kind, span) => {
436 required_var_defs = Some(tree_name(field_name));
437
438 let macro_name = tree_kind.macro_name();
439 let tree_name = tree_name(field_name);
440 parse_expr = quote_spanned! { span=> ::syn::#macro_name!(#tree_name in #input_source) };
441 }
442 }
443
444 if let Some(p) = attrs.peek {
445 parse_expr = match p {
446 PeekAttr::Peek(expr) => quote_spanned!(expr.span()=> match #input_source.peek(#expr) {
447 true => Some(#parse_expr),
448 false => None,
449 }),
450 PeekAttr::PeekWith(expr) => quote_spanned!(expr.span()=> match (#expr)(#input_source) {
451 true => Some(#parse_expr),
452 false => None,
453 }),
454 PeekAttr::ParseIf(expr) => quote_spanned!(expr.span()=> match #expr {
455 true => Some(#parse_expr),
456 false => None,
457 }),
458 };
459 }
460
461 let neighbor_map = |na: NeighborAttr| -> TokenStream {
462 let assigned_name = na
463 .maybe_named
464 .unwrap_or_else(|| Ident::new("_", Span::call_site()));
465 let source = na
466 .maybe_inside
467 .as_ref()
468 .map(tree_name)
469 .unwrap_or_else(crate::parse_input);
470 let parse_ty = na.parse_ty;
471 quote! {
472 let #assigned_name: #parse_ty = #source.parse()?;
473 }
474 };
475
476 let pre_parse = attrs.prefix.into_iter().map(neighbor_map).collect();
477 let post_parse = attrs.postfix.into_iter().map(neighbor_map).collect();
478
479 ParseField {
480 required_var_defs,
481 parse_expr,
482 pre_parse,
483 post_parse,
484 }
485}
486
487fn tree_name(field_name: &Ident) -> Ident {
488 format_ident!("__{}_backing_token_stream", field_name)
489}
490
491impl TreeKind {
492 fn macro_name(&self) -> Ident {
495 let span = Span::call_site();
496 match self {
497 TreeKind::Paren => Ident::new("parenthesized", span),
498 TreeKind::Bracket => Ident::new("bracketed", span),
499 TreeKind::Brace => Ident::new("braced", span),
500 }
501 }
502}