notation_dsl/
util.rs

1use fehler::throws;
2use proc_macro2::TokenStream;
3use quote::{quote, ToTokens};
4use syn::parse::{Error, Parse, ParseStream, Result};
5use syn::{braced, bracketed, parenthesized, token};
6
7use notation_proto::prelude::ProtoEntry;
8
9use crate::core::chord::ChordDsl;
10use crate::core::tone::ToneDsl;
11use crate::core::word::WordDsl;
12use crate::fretted::pick::PickDsl;
13use crate::proto::bar::BarDsl;
14use crate::proto::entry::{EntryDsl, MultibleDsl};
15use crate::proto::layer::LayerDsl;
16use crate::proto::section::SectionDsl;
17use crate::proto::slice::SliceDsl;
18use crate::proto::track::TrackDsl;
19
20macro_rules! impl_dsl {
21    ($dsl_type:ident) => {
22        impl Parse for $dsl_type {
23            fn parse(input: ParseStream) -> Result<Self> {
24                if input.peek(token::Brace) {
25                    let content;
26                    braced!(content in input);
27                    Self::parse_without_brace(&content)
28                } else {
29                    Self::parse_without_brace(input)
30                }
31            }
32        }
33        #[allow(dead_code)]
34        impl $dsl_type {
35            #[throws(Error)]
36            pub fn parse_vec(input: ParseStream) -> Vec<$dsl_type> {
37                let mut result = vec![];
38                if input.peek(token::Bracket) {
39                    let content;
40                    bracketed!(content in *input);
41                    while !content.is_empty() {
42                        result.push(content.parse()?);
43                    }
44                }
45                result
46            }
47            pub fn quote_vec(v: &[$dsl_type]) -> TokenStream {
48                let item_quotes: Vec<TokenStream> = v.iter().map(
49                    |x| quote! { #x }
50                ).collect();
51                quote! {
52                    vec![
53                        #(#item_quotes),*
54                    ]
55                }
56            }
57        }
58    }
59}
60
61impl_dsl!(EntryDsl);
62impl_dsl!(SliceDsl);
63impl_dsl!(TrackDsl);
64impl_dsl!(LayerDsl);
65impl_dsl!(BarDsl);
66impl_dsl!(SectionDsl);
67
68macro_rules! impl_multible_dsl {
69    ($dsl_type:ident) => {
70        impl Parse for $dsl_type {
71            fn parse(input: ParseStream) -> Result<Self> {
72                Self::parse_multible(input, false)
73            }
74        }
75        #[allow(dead_code)]
76        impl $dsl_type {
77            fn parse_multible(input: ParseStream, multied: bool) -> Result<Self> {
78                if input.peek(token::Paren) {
79                    let content;
80                    parenthesized!(content in input);
81                    Self::parse_without_paren(&content, multied, true)
82                } else {
83                    Self::parse_without_paren(input, multied, false)
84                }
85            }
86            #[throws(Error)]
87            pub fn parse_vec(input: ParseStream) -> Vec<$dsl_type> {
88                let mut result = vec![];
89                if input.peek(token::Bracket) {
90                    let content;
91                    bracketed!(content in *input);
92                    while !content.is_empty() {
93                        result.push(Self::parse_multible(&content, true)?);
94                    }
95                }
96                result
97            }
98            pub fn quote_multible(v: &MultibleDsl<$dsl_type>) -> TokenStream {
99                let item_quotes: Vec<TokenStream> = v.items.iter().map(
100                    |x| quote! { #x }
101                ).collect();
102                quote! {
103                    vec![
104                        #(#item_quotes),*
105                    ]
106                }
107            }
108        }
109        impl Parse for MultibleDsl<$dsl_type> {
110            fn parse(input: ParseStream) -> Result<Self> {
111                let items =
112                    if input.peek(token::Bracket) {
113                        $dsl_type::parse_vec(input)?
114                    } else {
115                        vec![
116                            $dsl_type::parse(input)?
117                        ]
118                    };
119                Ok(Self { items } )
120            }
121        }
122        impl ToTokens for MultibleDsl<$dsl_type> {
123            fn to_tokens(&self, tokens: &mut TokenStream) {
124                let item_quotes: Vec<TokenStream> = self.items.iter().map(
125                    |x| quote! { #x }
126                ).collect();
127                tokens.extend(quote! {
128                    #(#item_quotes),*
129                });
130            }
131        }
132        impl MultibleDsl<$dsl_type> {
133            pub fn add_proto(&self, entries: &mut Vec<ProtoEntry>) {
134                for item in self.items.iter() {
135                    entries.push(item.to_proto());
136                }
137            }
138        }
139    }
140}
141
142impl_multible_dsl!(ToneDsl);
143impl_multible_dsl!(ChordDsl);
144impl_multible_dsl!(WordDsl);
145impl_multible_dsl!(PickDsl);