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 pub fn to_display_stream(&self, injections: &[(String, TokenStream)]) -> TokenStream {
33 use quote::ToTokens;
34 let inner = self.body.to_display_stream(injections);
35 let mut ts = TokenStream::new();
36 proc_macro2::Group::new(self.delimiter, inner).to_tokens(&mut ts);
37 ts
38 }
39}
40
41impl Parse for GroupNode {
42 fn parse(input: ParseStream) -> syn::Result<Self> {
43 if input.peek(syn::token::Paren) {
44 let content;
45 let paren = syn::parenthesized!(content in input);
46 let body = content.parse::<Template>()?;
47
48 Ok(Self {
49 span: paren.span.join(),
50 delimiter: Delimiter::Parenthesis,
51 body: Box::new(body),
52 })
53 } else if input.peek(syn::token::Bracket) {
54 let content;
55 let bracket = syn::bracketed!(content in input);
56 let body = content.parse::<Template>()?;
57
58 Ok(Self {
59 span: bracket.span.join(),
60 delimiter: Delimiter::Bracket,
61 body: Box::new(body),
62 })
63 } else {
64 Err(input.error("expected a delimited group"))
65 }
66 }
67}
68
69impl Expand for GroupNode {
70 fn expand(&self, output: &Ident, idents: &mut crate::ident::Iter) -> TokenStream {
71 let inner = idents.next().unwrap();
72 let body_expanded = self.body.expand(&inner, idents);
73
74 let delim = match self.delimiter {
75 Delimiter::Parenthesis => {
76 quote! { ::zyn::proc_macro2::Delimiter::Parenthesis }
77 }
78 Delimiter::Bracket => quote! { ::zyn::proc_macro2::Delimiter::Bracket },
79 Delimiter::Brace => quote! { ::zyn::proc_macro2::Delimiter::Brace },
80 Delimiter::None => quote! { ::zyn::proc_macro2::Delimiter::None },
81 };
82
83 quote! {
84 {
85 let mut #inner = ::zyn::proc_macro2::TokenStream::new();
86 #body_expanded
87 ::zyn::quote::ToTokens::to_tokens(
88 &::zyn::proc_macro2::Group::new(#delim, #inner),
89 &mut #output,
90 );
91 }
92 }
93 }
94}