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 {
26 pub span: Span,
28 pub expr: TokenStream,
30 pub arms: Vec<(TokenStream, Template)>,
32}
33
34impl MatchNode {
35 pub fn span(&self) -> Span {
36 self.span
37 }
38}
39
40impl Parse for MatchNode {
41 fn parse(input: ParseStream) -> syn::Result<Self> {
42 let expr_content;
43 syn::parenthesized!(expr_content in input);
44 let expr: TokenStream = expr_content.parse()?;
45
46 let arms_content;
47 syn::braced!(arms_content in input);
48
49 let mut arms = Vec::new();
50
51 while !arms_content.is_empty() {
52 let mut pattern = TokenStream::new();
53
54 while !arms_content.is_empty() {
55 if arms_content.peek(Token![=>]) {
56 arms_content.parse::<Token![=>]>()?;
57 break;
58 }
59
60 let tt: TokenTree = arms_content.parse()?;
61 tt.to_tokens(&mut pattern);
62 }
63
64 let body_content;
65 syn::braced!(body_content in arms_content);
66 let body = body_content.parse::<Template>()?;
67
68 arms.push((pattern, body));
69
70 if arms_content.peek(Token![,]) {
71 arms_content.parse::<Token![,]>()?;
72 }
73 }
74
75 Ok(Self {
76 span: Span::call_site(),
77 expr,
78 arms,
79 })
80 }
81}
82
83impl Expand for MatchNode {
84 fn expand(&self, output: &Ident, idents: &mut crate::ident::Iter) -> TokenStream {
85 let expr = &self.expr;
86 let arms: Vec<TokenStream> = self
87 .arms
88 .iter()
89 .map(|(pattern, body)| {
90 let body_expanded = body.expand(output, idents);
91 quote! { #pattern => { #body_expanded } }
92 })
93 .collect();
94
95 quote! {
96 match #expr {
97 #(#arms),*
98 }
99 }
100 }
101}