zyn_core/ast/at/
match_node.rs1use proc_macro2::Ident;
2use proc_macro2::Span;
3use proc_macro2::TokenStream;
4use proc_macro2::TokenTree;
5
6use quote::ToTokens;
7use quote::quote;
8
9use syn::Token;
10use syn::parse::Parse;
11use syn::parse::ParseStream;
12
13use crate::template::Template;
14
15use crate::Expand;
16
17pub struct MatchNode {
18 pub span: Span,
19 pub expr: TokenStream,
20 pub arms: Vec<(TokenStream, Template)>,
21}
22
23impl MatchNode {
24 pub fn span(&self) -> Span {
25 self.span
26 }
27}
28
29impl Parse for MatchNode {
30 fn parse(input: ParseStream) -> syn::Result<Self> {
31 let expr_content;
32 syn::parenthesized!(expr_content in input);
33 let expr: TokenStream = expr_content.parse()?;
34
35 let arms_content;
36 syn::braced!(arms_content in input);
37
38 let mut arms = Vec::new();
39
40 while !arms_content.is_empty() {
41 let mut pattern = TokenStream::new();
42
43 while !arms_content.is_empty() {
44 if arms_content.peek(Token![=>]) {
45 arms_content.parse::<Token![=>]>()?;
46 break;
47 }
48
49 let tt: TokenTree = arms_content.parse()?;
50 tt.to_tokens(&mut pattern);
51 }
52
53 let body_content;
54 syn::braced!(body_content in arms_content);
55 let body = body_content.parse::<Template>()?;
56
57 arms.push((pattern, body));
58
59 if arms_content.peek(Token![,]) {
60 arms_content.parse::<Token![,]>()?;
61 }
62 }
63
64 Ok(Self {
65 span: Span::call_site(),
66 expr,
67 arms,
68 })
69 }
70}
71
72impl Expand for MatchNode {
73 fn expand(&self, output: &Ident, idents: &mut crate::ident::Iter) -> TokenStream {
74 let expr = &self.expr;
75 let arms: Vec<TokenStream> = self
76 .arms
77 .iter()
78 .map(|(pattern, body)| {
79 let body_expanded = body.expand(output, idents);
80 quote! { #pattern => { #body_expanded } }
81 })
82 .collect();
83
84 quote! {
85 match #expr {
86 #(#arms),*
87 }
88 }
89 }
90}