Punctuated parsing
diff --git a/src/data.rs b/src/data.rs
index 9c77254..b87eaf1 100644
--- a/src/data.rs
+++ b/src/data.rs
@@ -196,9 +196,9 @@
                 ident: input.parse()?,
                 fields: {
                     if input.peek(token::Brace) {
-                        Fields::Named(input.parse_synom(FieldsNamed::parse)?)
+                        Fields::Named(input.parse()?)
                     } else if input.peek(token::Paren) {
-                        Fields::Unnamed(input.parse_synom(FieldsUnnamed::parse)?)
+                        Fields::Unnamed(input.parse()?)
                     } else {
                         Fields::Unit
                     }
@@ -214,62 +214,46 @@
         }
     }
 
-    impl Synom for FieldsNamed {
-        named!(parse -> Self, map!(
-            braces!(call!(Punctuated::parse_terminated_with, Field::parse_named)),
-            |(brace, fields)| FieldsNamed {
-                brace_token: brace,
-                named: fields,
-            }
-        ));
-
-        fn description() -> Option<&'static str> {
-            Some("named fields in a struct or struct variant")
+    impl Parse for FieldsNamed {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let content;
+            Ok(FieldsNamed {
+                brace_token: braced!(content in input),
+                named: content.parse_terminated(Field::parse_named)?,
+            })
         }
     }
 
-    impl Synom for FieldsUnnamed {
-        named!(parse -> Self, map!(
-            parens!(call!(Punctuated::parse_terminated_with, Field::parse_unnamed)),
-            |(paren, fields)| FieldsUnnamed {
-                paren_token: paren,
-                unnamed: fields,
-            }
-        ));
-
-        fn description() -> Option<&'static str> {
-            Some("unnamed fields in a tuple struct or tuple variant")
+    impl Parse for FieldsUnnamed {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let content;
+            Ok(FieldsUnnamed {
+                paren_token: parenthesized!(content in input),
+                unnamed: content.parse_terminated(Field::parse_unnamed)?,
+            })
         }
     }
 
     impl Field {
-        named!(pub parse_named -> Self, do_parse!(
-            attrs: many0!(Attribute::old_parse_outer) >>
-            vis: syn!(Visibility) >>
-            id: syn!(Ident) >>
-            colon: punct!(:) >>
-            ty: syn!(Type) >>
-            (Field {
-                ident: Some(id),
-                vis: vis,
-                attrs: attrs,
-                ty: ty,
-                colon_token: Some(colon),
+        fn parse_named(input: ParseStream) -> Result<Self> {
+            Ok(Field {
+                attrs: input.call(Attribute::parse_outer)?,
+                vis: input.parse()?,
+                ident: Some(input.parse()?),
+                colon_token: Some(input.parse()?),
+                ty: input.parse_synom(Type::parse)?,
             })
-        ));
+        }
 
-        named!(pub parse_unnamed -> Self, do_parse!(
-            attrs: many0!(Attribute::old_parse_outer) >>
-            vis: syn!(Visibility) >>
-            ty: syn!(Type) >>
-            (Field {
+        fn parse_unnamed(input: ParseStream) -> Result<Self> {
+            Ok(Field {
+                attrs: input.call(Attribute::parse_outer)?,
+                vis: input.parse()?,
                 ident: None,
                 colon_token: None,
-                vis: vis,
-                attrs: attrs,
-                ty: ty,
+                ty: input.parse_synom(Type::parse)?,
             })
-        ));
+        }
     }
 
     impl Parse for Visibility {
diff --git a/src/parse.rs b/src/parse.rs
index cfc0817..aa3043d 100644
--- a/src/parse.rs
+++ b/src/parse.rs
@@ -11,6 +11,7 @@
 
 use buffer::Cursor;
 use error;
+use punctuated::Punctuated;
 use synom::PResult;
 
 pub use error::{Error, Result};
@@ -123,6 +124,13 @@
         self.lookahead1().peek(token)
     }
 
+    pub fn parse_terminated<T, P: Parse>(
+        &self,
+        parser: fn(ParseStream) -> Result<T>,
+    ) -> Result<Punctuated<T, P>> {
+        Punctuated::parse_terminated2(self, parser)
+    }
+
     pub fn fork(&self) -> Self {
         self.clone()
     }
diff --git a/src/punctuated.rs b/src/punctuated.rs
index b4a0b3f..171e549 100644
--- a/src/punctuated.rs
+++ b/src/punctuated.rs
@@ -40,6 +40,8 @@
 #[cfg(feature = "parsing")]
 use buffer::Cursor;
 #[cfg(feature = "parsing")]
+use parse::{Parse, ParseStream, Result};
+#[cfg(feature = "parsing")]
 use parse_error;
 #[cfg(feature = "parsing")]
 use synom::{PResult, Synom};
@@ -773,6 +775,34 @@
     }
 }
 
+#[cfg(feature = "parsing")]
+impl<T, P> Punctuated<T, P>
+where
+    P: Parse,
+{
+    pub fn parse_terminated2(
+        input: ParseStream,
+        parser: fn(ParseStream) -> Result<T>,
+    ) -> Result<Self> {
+        let mut res = Punctuated::new();
+
+        loop {
+            if input.is_empty() {
+                break;
+            }
+            let value = parser(input)?;
+            res.push_value(value);
+            if input.is_empty() {
+                break;
+            }
+            let punct = input.parse()?;
+            res.push_punct(punct);
+        }
+
+        Ok(res)
+    }
+}
+
 #[cfg(feature = "printing")]
 mod printing {
     use super::*;