Skip to content

Commit 624e338

Browse files
authored
A quick and dirty hack to enable 'outer' and 'inner' attrs to be consumed in unit variants of enum (#35)
1 parent eb04129 commit 624e338

File tree

3 files changed

+50
-5
lines changed

3 files changed

+50
-5
lines changed

derive/src/attributes.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ pub(crate) enum DeriveAttribute {
3232
Rule(RuleAttribute),
3333
}
3434

35+
#[derive(Debug)]
3536
/// `#[pest_ast(..)]` for fields in `#[derive(FromPest)]`
3637
pub(crate) enum FieldAttribute {
3738
/// `outer(with(path::to),*)`
@@ -47,12 +48,14 @@ pub(crate) struct GrammarAttribute {
4748
pub(crate) lit: LitStr,
4849
}
4950

51+
#[derive(Debug)]
5052
pub(crate) struct OuterAttribute {
5153
pub(crate) outer: kw::outer,
5254
pub(crate) paren: Paren,
5355
pub(crate) with: Punctuated<WithAttribute, Token![,]>,
5456
}
5557

58+
#[derive(Debug)]
5659
pub(crate) struct InnerAttribute {
5760
pub(crate) inner: kw::inner,
5861
pub(crate) paren: Paren,
@@ -61,6 +64,7 @@ pub(crate) struct InnerAttribute {
6164
pub(crate) with: Punctuated<WithAttribute, Token![,]>,
6265
}
6366

67+
#[derive(Debug)]
6468
pub(crate) struct WithAttribute {
6569
pub(crate) with: kw::with,
6670
pub(crate) paren: Paren,

derive/src/from_pest/field.rs

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use syn::Variant;
2+
13
use {
24
proc_macro2::{Span, TokenStream},
35
syn::{
@@ -99,7 +101,44 @@ fn with_mods(stream: TokenStream, mods: Vec<Path>) -> TokenStream {
99101
.fold(stream, |stream, path| quote!(#path(#stream)))
100102
}
101103

102-
pub fn convert(name: &Path, fields: Fields) -> Result<TokenStream> {
104+
pub fn enum_convert(name: &Path, variant: &Variant) -> Result<TokenStream> {
105+
let fields = variant.fields.clone();
106+
Ok(match fields {
107+
Fields::Named(fields) => {
108+
let fields: Vec<_> = fields
109+
.named
110+
.into_iter()
111+
.map(|field| {
112+
let attrs = FieldAttribute::from_attributes(field.attrs)?;
113+
Ok(ConversionStrategy::from_attrs(attrs)?
114+
.apply(Member::Named(field.ident.unwrap())))
115+
})
116+
.collect::<Result<_>>()?;
117+
quote!(#name{#(#fields,)*})
118+
}
119+
Fields::Unnamed(fields) => {
120+
let fields: Vec<_> = fields
121+
.unnamed
122+
.into_iter()
123+
.enumerate()
124+
.map(|(i, field)| {
125+
let attrs = FieldAttribute::from_attributes(field.attrs)?;
126+
Ok(ConversionStrategy::from_attrs(attrs)?
127+
.apply(Member::Unnamed(Index::from(i))))
128+
})
129+
.collect::<Result<_>>()?;
130+
quote!(#name(#(#fields),*))
131+
}
132+
Fields::Unit => {
133+
let attrs = FieldAttribute::from_attributes(variant.attrs.clone())?;
134+
let real_name =
135+
ConversionStrategy::from_attrs(attrs)?.apply(Member::Unnamed(Index::from(0)));
136+
quote!(#real_name)
137+
}
138+
})
139+
}
140+
141+
pub fn struct_convert(name: &Path, fields: Fields) -> Result<TokenStream> {
103142
Ok(match fields {
104143
Fields::Named(fields) => {
105144
let fields: Vec<_> = fields
@@ -126,6 +165,8 @@ pub fn convert(name: &Path, fields: Fields) -> Result<TokenStream> {
126165
.collect::<Result<_>>()?;
127166
quote!(#name(#(#fields),*))
128167
}
129-
Fields::Unit => quote!(#name),
168+
Fields::Unit => {
169+
quote!(#name)
170+
}
130171
})
131172
}

derive/src/from_pest/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ fn derive_for_struct(
133133
unimplemented!("Grammar introspection not implemented yet")
134134
}
135135

136-
let construct = field::convert(&parse_quote!(#name), fields)?;
136+
let construct = field::struct_convert(&parse_quote!(#name), fields)?;
137137

138138
let extraneous = crate::trace(
139139
quote! { "when converting {}, found extraneous {:?}", stringify!(#name), inner},
@@ -177,8 +177,8 @@ fn derive_for_enum(
177177
let convert_variants: Vec<TokenStream> = variants
178178
.into_iter()
179179
.map(|variant| {
180-
let variant_name = variant.ident;
181-
let construct_variant = field::convert(&parse_quote!(#name::#variant_name), variant.fields)?;
180+
let variant_name = &variant.ident;
181+
let construct_variant = field::enum_convert(&parse_quote!(#name::#variant_name), &variant)?;
182182
let extraneous = crate::trace(quote! {
183183
"when converting {}, found extraneous {:?}", stringify!(#name), stringify!(#variant_name)
184184
});

0 commit comments

Comments
 (0)