Skip to main content

zyn_core/ast/
group_node.rs

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