zyn_core/ast/
group_node.rs1use proc_macro2::Delimiter;
2use proc_macro2::Ident;
3use proc_macro2::Span;
4use proc_macro2::TokenStream;
5
6use quote::quote;
7
8use syn::parse::Parse;
9use syn::parse::ParseStream;
10
11use crate::template::Template;
12
13use crate::Expand;
14
15pub struct GroupNode {
19 pub span: Span,
21 pub delimiter: Delimiter,
23 pub body: Box<Template>,
25}
26
27impl GroupNode {
28 pub fn span(&self) -> Span {
29 self.span
30 }
31}
32
33impl Parse for GroupNode {
34 fn parse(input: ParseStream) -> syn::Result<Self> {
35 if input.peek(syn::token::Paren) {
36 let content;
37 let paren = syn::parenthesized!(content in input);
38 let body = content.parse::<Template>()?;
39
40 Ok(Self {
41 span: paren.span.join(),
42 delimiter: Delimiter::Parenthesis,
43 body: Box::new(body),
44 })
45 } else if input.peek(syn::token::Bracket) {
46 let content;
47 let bracket = syn::bracketed!(content in input);
48 let body = content.parse::<Template>()?;
49
50 Ok(Self {
51 span: bracket.span.join(),
52 delimiter: Delimiter::Bracket,
53 body: Box::new(body),
54 })
55 } else {
56 Err(input.error("expected a delimited group"))
57 }
58 }
59}
60
61impl Expand for GroupNode {
62 fn expand(&self, output: &Ident, idents: &mut crate::ident::Iter) -> TokenStream {
63 let inner = idents.next().unwrap();
64 let body_expanded = self.body.expand(&inner, idents);
65
66 let delim = match self.delimiter {
67 Delimiter::Parenthesis => {
68 quote! { ::zyn::proc_macro2::Delimiter::Parenthesis }
69 }
70 Delimiter::Bracket => quote! { ::zyn::proc_macro2::Delimiter::Bracket },
71 Delimiter::Brace => quote! { ::zyn::proc_macro2::Delimiter::Brace },
72 Delimiter::None => quote! { ::zyn::proc_macro2::Delimiter::None },
73 };
74
75 quote! {
76 {
77 let mut #inner = ::zyn::proc_macro2::TokenStream::new();
78 #body_expanded
79 ::zyn::quote::ToTokens::to_tokens(
80 &::zyn::proc_macro2::Group::new(#delim, #inner),
81 &mut #output,
82 );
83 }
84 }
85 }
86}