Implement syn::DeriveInput
diff --git a/src/derive.rs b/src/derive.rs
index b7bfa12..7a1e406 100644
--- a/src/derive.rs
+++ b/src/derive.rs
@@ -79,115 +79,135 @@
pub mod parsing {
use super::*;
- use synom::Synom;
+ use parse::{Parse, ParseStream, Result};
- enum DeriveInputKind {
- Struct(Token![struct]),
- Enum(Token![enum]),
- Union(Token![union]),
- }
+ impl Parse for DeriveInput {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let attrs = input.call(Attribute::parse_outer)?;
+ let vis = input.parse::<Visibility>()?;
- impl Synom for DeriveInputKind {
- named!(parse -> Self, alt!(
- keyword!(struct) => { DeriveInputKind::Struct }
- |
- keyword!(enum) => { DeriveInputKind::Enum }
- |
- keyword!(union) => { DeriveInputKind::Union }
- ));
- }
-
- impl Synom for DeriveInput {
- named!(parse -> Self, do_parse!(
- attrs: many0!(Attribute::old_parse_outer) >>
- vis: syn!(Visibility) >>
- which: syn!(DeriveInputKind) >>
- id: syn!(Ident) >>
- generics: syn!(Generics) >>
- item: switch!(value!(which),
- DeriveInputKind::Struct(s) => map!(data_struct, move |(wh, fields, semi)| DeriveInput {
- ident: id,
- vis: vis,
+ let lookahead = input.lookahead1();
+ if lookahead.peek(Token![struct]) {
+ let struct_token = input.parse::<Token![struct]>()?;
+ let ident = input.parse::<Ident>()?;
+ let generics = input.parse_synom(Generics::parse)?;
+ let (where_clause, fields, semi) = data_struct(input)?;
+ Ok(DeriveInput {
attrs: attrs,
+ vis: vis,
+ ident: ident,
generics: Generics {
- where_clause: wh,
+ where_clause: where_clause,
..generics
},
data: Data::Struct(DataStruct {
- struct_token: s,
+ struct_token: struct_token,
fields: fields,
semi_token: semi,
}),
})
- |
- DeriveInputKind::Enum(e) => map!(data_enum, move |(wh, brace, variants)| DeriveInput {
- ident: id,
- vis: vis,
+ } else if lookahead.peek(Token![enum]) {
+ let enum_token = input.parse::<Token![enum]>()?;
+ let ident = input.parse::<Ident>()?;
+ let generics = input.parse_synom(Generics::parse)?;
+ let (where_clause, brace, variants) = data_enum(input)?;
+ Ok(DeriveInput {
attrs: attrs,
+ vis: vis,
+ ident: ident,
generics: Generics {
- where_clause: wh,
+ where_clause: where_clause,
..generics
},
data: Data::Enum(DataEnum {
- variants: variants,
+ enum_token: enum_token,
brace_token: brace,
- enum_token: e,
+ variants: variants,
}),
})
- |
- DeriveInputKind::Union(u) => map!(data_union, move |(wh, fields)| DeriveInput {
- ident: id,
- vis: vis,
+ } else if lookahead.peek(Token![union]) {
+ let union_token = input.parse::<Token![union]>()?;
+ let ident = input.parse::<Ident>()?;
+ let generics = input.parse_synom(Generics::parse)?;
+ let (where_clause, fields) = data_union(input)?;
+ Ok(DeriveInput {
attrs: attrs,
+ vis: vis,
+ ident: ident,
generics: Generics {
- where_clause: wh,
+ where_clause: where_clause,
..generics
},
data: Data::Union(DataUnion {
- union_token: u,
+ union_token: union_token,
fields: fields,
}),
})
- ) >>
- (item)
- ));
-
- fn description() -> Option<&'static str> {
- Some("derive input")
+ } else {
+ Err(lookahead.error())
+ }
}
}
- named!(data_struct -> (Option<WhereClause>, Fields, Option<Token![;]>), alt!(
- do_parse!(
- wh: option!(syn!(WhereClause)) >>
- fields: syn!(FieldsNamed) >>
- (wh, Fields::Named(fields), None)
- )
- |
- do_parse!(
- fields: syn!(FieldsUnnamed) >>
- wh: option!(syn!(WhereClause)) >>
- semi: punct!(;) >>
- (wh, Fields::Unnamed(fields), Some(semi))
- )
- |
- do_parse!(
- wh: option!(syn!(WhereClause)) >>
- semi: punct!(;) >>
- (wh, Fields::Unit, Some(semi))
- )
- ));
+ fn data_struct(input: ParseStream) -> Result<(Option<WhereClause>, Fields, Option<Token![;]>)> {
+ let mut lookahead = input.lookahead1();
+ let mut where_clause = None;
+ if lookahead.peek(Token![where]) {
+ where_clause = Some(input.parse_synom(WhereClause::parse)?);
+ lookahead = input.lookahead1();
+ }
- named!(data_enum -> (Option<WhereClause>, token::Brace, Punctuated<Variant, Token![,]>), do_parse!(
- wh: option!(syn!(WhereClause)) >>
- data: braces!(Punctuated::parse_terminated) >>
- (wh, data.0, data.1)
- ));
+ if where_clause.is_none() && lookahead.peek(token::Paren) {
+ let fields = input.parse()?;
- named!(data_union -> (Option<WhereClause>, FieldsNamed), tuple!(
- option!(syn!(WhereClause)),
- syn!(FieldsNamed),
- ));
+ lookahead = input.lookahead1();
+ if lookahead.peek(Token![where]) {
+ where_clause = Some(input.parse_synom(WhereClause::parse)?);
+ lookahead = input.lookahead1();
+ }
+
+ if lookahead.peek(Token![;]) {
+ let semi = input.parse()?;
+ Ok((where_clause, Fields::Unnamed(fields), Some(semi)))
+ } else {
+ Err(lookahead.error())
+ }
+ } else if lookahead.peek(token::Brace) {
+ let fields = input.parse()?;
+ Ok((where_clause, Fields::Named(fields), None))
+ } else if lookahead.peek(Token![;]) {
+ let semi = input.parse()?;
+ Ok((where_clause, Fields::Unit, Some(semi)))
+ } else {
+ Err(lookahead.error())
+ }
+ }
+
+ fn data_enum(input: ParseStream) -> Result<(Option<WhereClause>, token::Brace, Punctuated<Variant, Token![,]>)> {
+ let where_clause = if input.peek(Token![where]) {
+ Some(input.parse_synom(WhereClause::parse)?)
+ } else {
+ None
+ };
+
+ let content;
+ let brace = braced!(content in input);
+ let variants = content.parse_terminated(<Variant as Parse>::parse)?;
+
+ Ok((where_clause, brace, variants))
+ }
+
+ fn data_union(input: ParseStream) -> Result<(Option<WhereClause>, FieldsNamed)> {
+ let where_clause = if input.peek(Token![where]) {
+ Some(input.parse_synom(WhereClause::parse)?)
+ } else {
+ None
+ };
+
+ let fields = input.parse()?;
+
+ Ok((where_clause, fields))
+ }
}
#[cfg(feature = "printing")]