parseal_derive/
lib.rs

1use proc_macro::TokenStream;
2use quote::{quote, ToTokens};
3use syn::{
4    parse_macro_input, spanned::Spanned, Attribute, Data, DataEnum, DataStruct, DeriveInput, Error,
5    Field, Fields, Generics, Ident, Index, Meta, MetaList,
6};
7
8#[proc_macro_derive(Parsable, attributes(whitespace, value))]
9pub fn parsable_fn(item: TokenStream) -> TokenStream {
10    let item = parse_macro_input!(item as DeriveInput);
11    match &item.data {
12        Data::Struct(value) => derive_struct(&item.ident, value, &item.generics),
13        Data::Enum(value) => derive_enum(&item.ident, value, &item.generics),
14        Data::Union(_) => TokenStream::from(
15            Error::new(item.span(), "Can not derive Parse from a union type.").to_compile_error(),
16        ),
17    }
18}
19
20fn derive_struct(ident: &Ident, value: &DataStruct, generics: &Generics) -> TokenStream {
21    let fields = value.fields.iter().collect::<Vec<_>>();
22
23    let definitions = derive_fields(fields.clone());
24    let parse_result = match &value.fields {
25        Fields::Named(fields) => {
26            let fields = fields.named.iter().map(|field| &field.ident);
27            let inner_fields = fields
28                .clone()
29                .enumerate()
30                .map(|(i, field)| inner_ident(field, i));
31            quote! {
32                ::std::result::Result::Ok(Self {
33                    #(#fields: #inner_fields),*
34                })
35            }
36        }
37        Fields::Unnamed(fields) => {
38            let inner_fields = fields
39                .unnamed
40                .iter()
41                .enumerate()
42                .map(|(i, _)| inner_ident(&None, i));
43            quote! {
44                ::std::result::Result::Ok(Self(#(#inner_fields),*))
45            }
46        }
47        Fields::Unit => {
48            return TokenStream::from(
49                Error::new(
50                    ident.span(),
51                    "Can not derive trait Parse for a unit struct.",
52                )
53                .to_compile_error(),
54            )
55        }
56    };
57
58    let first_ident = get_ident(&fields.first().unwrap().ident, 0);
59    let last_ident = get_ident(&fields.last().unwrap().ident, fields.len() - 1);
60    let (impl_generics, type_generics, where_clause) = generics.split_for_impl();
61    quote! {
62        impl #impl_generics Parse for #ident #type_generics #where_clause {
63            fn parse(value: &mut parsing::charstream::CharStream) -> ::std::result::Result<Self, parsing::ParseError> {
64                #(#definitions)*
65                #parse_result
66            }
67
68            fn span(&self) -> parsing::charstream::Span {
69                parsing::charstream::Span::new(self.#first_ident.span().start, self.#last_ident.span().end)
70            }
71        }
72    }.into()
73}
74
75fn derive_enum(ident: &Ident, value: &DataEnum, generics: &Generics) -> TokenStream {
76    let variants = value.variants.iter().map(|variant| {
77        let ident = Ident::new(
78            &format!("__parse_{}", variant.ident.to_string().to_lowercase()),
79            variant.span(),
80        );
81        (&variant.ident, ident, &variant.fields, &variant.attrs)
82    });
83    let variant_functions = match variants
84        .clone()
85        .map(|(field_ident, func_ident, fields, attrs)| {
86            derive_variant_function(field_ident, func_ident, fields, attrs)
87        })
88        .collect::<Result<Vec<_>, _>>()
89    {
90        Ok(value) => value,
91        Err(error) => return error,
92    };
93
94    let parse_variants = variants.clone().map(|(_, func_ident, _, _)| {
95        quote! {
96            let mut __value = value.clone();
97            match Self::#func_ident(&mut __value) {
98                ::std::result::Result::Ok(inner) => {
99                    let __position = __value.pos();
100                    if __position > position {
101                        position = __value.pos();
102                    }
103                    options.push(inner);
104                }
105                ::std::result::Result::Err(err) => match error {
106                    Some(__err) if err.pos() > __err.pos() =>
107                        error = ::std::option::Option::Some(err),
108                    Some(_) => {}
109                    None => error = ::std::option::Option::Some(err),
110                }
111            }
112        }
113    });
114
115    let span_variants = variants.map(|(variant_ident, _, fields, _)| {
116        let fields = fields.iter().collect::<Vec<_>>();
117        let definitions = fields
118            .iter()
119            .enumerate()
120            .map(|(i, field)| match &field.ident {
121                Some(ident) => {
122                    let inner = inner_ident(&field.ident, i);
123                    quote! {
124                        #ident: #inner
125                    }
126                }
127                None => {
128                    let ident = inner_ident(&field.ident, i);
129                    quote! {#ident}
130                }
131            });
132
133        if fields.is_empty() {
134            quote! {
135                Self::#variant_ident => parsing::charstream::Span::default(),
136            }
137        } else {
138            let first = inner_ident(&fields.first().unwrap().ident, 0);
139            let last = inner_ident(&fields.last().unwrap().ident, fields.len() - 1);
140            
141            quote! {
142                Self::#variant_ident(#(#definitions),*) =>
143                parsing::charstream::Span::new(#first.span().start, #last.span().end),
144            }    
145        }
146    });
147
148    let (impl_generics, type_generics, where_clause) = generics.split_for_impl();
149
150    quote! {
151        impl #impl_generics #ident #type_generics #where_clause {
152            #(#variant_functions)*
153        }
154
155        impl #impl_generics Parse for #ident #type_generics #where_clause {
156            fn parse(value: &mut parsing::charstream::CharStream) -> ::std::result::Result<Self, parsing::ParseError> {
157                let mut options = Vec::new();
158                let mut error: Option<parsing::ParseError> = None;
159                let mut position = value.pos();
160                #(#parse_variants)*
161                options.sort_by(|a, b| b.span().partial_cmp(&a.span()).unwrap());
162                match options.first() {
163                    Some(option) => {
164                        value.goto(position.clone())?;
165                        Ok(option.clone())
166                    }
167                    None => Err(error.unwrap()),
168                }
169            }
170
171            fn span(&self) -> parsing::charstream::Span {
172                match self {
173                    #(#span_variants)*
174                }
175            }
176        }
177    }.into()
178}
179
180fn derive_variant_function(
181    field_ident: &Ident,
182    func_ident: Ident,
183    fields: &Fields,
184    _attrs: &[Attribute],
185) -> Result<quote::__private::TokenStream, TokenStream> {
186    let definitions = derive_fields(fields.iter().collect());
187    let parse_result = match fields {
188        Fields::Named(fields) => {
189            let fields = fields.named.iter().map(|field| &field.ident);
190            let inner_fields = fields
191                .clone()
192                .enumerate()
193                .map(|(i, field)| inner_ident(field, i));
194            quote! {
195                ::std::result::Result::Ok(Self::#field_ident {
196                    #(#fields: #inner_fields),*
197                })
198            }
199        }
200        Fields::Unnamed(fields) => {
201            let inner_fields = fields
202                .unnamed
203                .iter()
204                .enumerate()
205                .map(|(i, _)| inner_ident(&None, i));
206            quote! {
207                ::std::result::Result::Ok(Self::#field_ident(#(#inner_fields),*))
208            }
209        }
210        Fields::Unit => quote! {
211            ::std::result::Result::Ok(Self::#field_ident)
212        }
213    };
214    Ok(quote! {
215        fn #func_ident(value: &mut parsing::charstream::CharStream) -> ::std::result::Result<Self, parsing::ParseError> {
216            #(#definitions)*
217            #parse_result
218        }
219    })
220}
221
222fn derive_fields(fields: Vec<&Field>) -> Vec<quote::__private::TokenStream> {
223    let fields = fields
224        .iter()
225        .enumerate()
226        .map(|(i, field)| (inner_ident(&field.ident, i), &field.ty, &field.attrs));
227    fields.map(|(ident, ty, attrs)| {
228        let whitespace_attr = get_attr(attrs, "whitespace");
229        let value_attr = get_attr(attrs, "value");
230
231        let value = match whitespace_attr {
232            Some(attr) => {
233                let whitespace = attr.nested;
234                quote! {
235                    {
236                        let mut __whitespace_value = value.clone();
237                        __whitespace_value.set_whitespace(parsing::charstream::WhitespaceType::#whitespace);
238
239                        let inner =  <#ty>::parse(&mut __whitespace_value);
240                        value.goto(__whitespace_value.pos())?;
241                        inner
242                    }
243                }
244            }
245            None => quote! {
246                <#ty>::parse(value)
247            }
248        };
249        let value = match value_attr {
250            Some(attr) => {
251                let mut values = attr.nested.iter().map(|meta| quote! {
252                    ::std::result::Result::Ok(inner) if inner == #meta => inner
253                }).collect::<Vec<_>>();
254
255                let expected = attr.nested.iter().map(|meta| quote! {
256                    #meta
257                }).collect::<Vec<_>>();
258                values.push(quote! {
259                    ::std::result::Result::Ok(inner) => return ::std::result::Result::Err(parsing::ParseError::new(&format!("Value was not one of the expected values. expected one of: {}", stringify!([#(#expected),*])), value.pos()))
260                });
261                values.push(quote! {
262                    ::std::result::Result::Err(error) => return ::std::result::Result::Err(error)
263                });
264                quote! {
265                    match #value {
266                        #(#values),*
267                    }
268                }
269            }
270            None => quote! {
271                #value?
272            }
273        };
274        quote! {
275            let #ident = #value;
276        }
277    }).collect::<Vec<_>>()
278}
279
280fn get_attr(attrs: &[Attribute], value: &str) -> Option<MetaList> {
281    attrs.iter().find_map(|attr| match attr.path.get_ident() {
282        Some(ident) if ident == value => match attr.parse_meta() {
283            Ok(Meta::List(list)) => Some(list),
284            _ => None,
285        },
286        _ => None,
287    })
288}
289
290fn inner_ident(ident: &Option<Ident>, index: usize) -> Ident {
291    let ident = get_ident(ident, index);
292    Ident::new(&format!("__inner_{}", ident), ident.span())
293}
294
295fn get_ident(ident: &Option<Ident>, index: usize) -> quote::__private::TokenStream {
296    match ident {
297        Some(ident) => <Ident as ToTokens>::to_token_stream(ident),
298        None => <Index as ToTokens>::to_token_stream(&Index::from(index)),
299    }
300}