Parse types
diff --git a/src/attr.rs b/src/attr.rs
index 73af023..7b1cfa9 100644
--- a/src/attr.rs
+++ b/src/attr.rs
@@ -427,7 +427,7 @@
                 pound: punct!(#) >>
                 bang: punct!(!) >>
                 path_and_tts: brackets!(tuple!(
-                    call!(Path::parse_mod_style),
+                    call!(Path::old_parse_mod_style),
                     syn!(TokenStream),
                 )) >>
                 ({
@@ -465,7 +465,7 @@
             do_parse!(
                 pound: punct!(#) >>
                 path_and_tts: brackets!(tuple!(
-                    call!(Path::parse_mod_style),
+                    call!(Path::old_parse_mod_style),
                     syn!(TokenStream),
                 )) >>
                 ({
diff --git a/src/data.rs b/src/data.rs
index 36ba136..c8e9e06 100644
--- a/src/data.rs
+++ b/src/data.rs
@@ -241,7 +241,7 @@
                 vis: input.parse()?,
                 ident: Some(input.parse()?),
                 colon_token: Some(input.parse()?),
-                ty: input.parse_synom(Type::parse)?,
+                ty: input.parse()?,
             })
         }
 
@@ -251,7 +251,7 @@
                 vis: input.parse()?,
                 ident: None,
                 colon_token: None,
-                ty: input.parse_synom(Type::parse)?,
+                ty: input.parse()?,
             })
         }
     }
@@ -292,7 +292,7 @@
                         pub_token: pub_token,
                         paren_token: parenthesized!(content in input),
                         in_token: Some(content.parse()?),
-                        path: Box::new(content.parse_synom(Path::parse_mod_style)?),
+                        path: Box::new(content.parse_synom(Path::old_parse_mod_style)?),
                     }));
                 }
             }
diff --git a/src/expr.rs b/src/expr.rs
index 540c994..bb8b469 100644
--- a/src/expr.rs
+++ b/src/expr.rs
@@ -1029,7 +1029,7 @@
 #[cfg(feature = "parsing")]
 pub mod parsing {
     use super::*;
-    use path::parsing::mod_style_path_segment;
+    use path::parsing::old_mod_style_path_segment;
     #[cfg(feature = "full")]
     use path::parsing::ty_no_eq_after;
 
@@ -1347,7 +1347,7 @@
                 as_: keyword!(as) >>
                 // We can't accept `A + B` in cast expressions, as it's
                 // ambiguous with the + expression.
-                ty: call!(Type::without_plus) >>
+                ty: shim!(Type::without_plus) >>
                 ({
                     e = ExprCast {
                         attrs: Vec::new(),
@@ -1362,7 +1362,7 @@
                 colon: punct!(:) >>
                 // We can't accept `A + B` in cast expressions, as it's
                 // ambiguous with the + expression.
-                ty: call!(Type::without_plus) >>
+                ty: shim!(Type::without_plus) >>
                 ({
                     e = ExprType {
                         attrs: Vec::new(),
@@ -1384,7 +1384,7 @@
             as_: keyword!(as) >>
             // We can't accept `A + B` in cast expressions, as it's
             // ambiguous with the + expression.
-            ty: call!(Type::without_plus) >>
+            ty: shim!(Type::without_plus) >>
             ({
                 e = ExprCast {
                     attrs: Vec::new(),
@@ -1721,7 +1721,7 @@
     #[cfg(feature = "full")]
     impl Synom for ExprGroup {
         named!(parse -> Self, do_parse!(
-            e: grouped!(syn!(Expr)) >>
+            e: old_grouped!(syn!(Expr)) >>
             (ExprGroup {
                 attrs: Vec::new(),
                 expr: Box::new(e.1),
@@ -2542,7 +2542,7 @@
             })
         )
         |
-        mod_style_path_segment
+        old_mod_style_path_segment
     ));
 
     named!(qpath -> (Option<QSelf>, Path), alt!(
@@ -2651,7 +2651,7 @@
     #[cfg(feature = "full")]
     named!(stmt_mac -> Stmt, do_parse!(
         attrs: many0!(Attribute::old_parse_outer) >>
-        what: call!(Path::parse_mod_style) >>
+        what: call!(Path::old_parse_mod_style) >>
         bang: punct!(!) >>
     // Only parse braces here; paren and bracket will get parsed as
     // expression statements
diff --git a/src/generics.rs b/src/generics.rs
index bfcc5a5..7d96e78 100644
--- a/src/generics.rs
+++ b/src/generics.rs
@@ -670,7 +670,7 @@
                 },
                 default: {
                     if has_default {
-                        Some(input.parse_synom(Type::parse)?)
+                        Some(input.parse()?)
                     } else {
                         None
                     }
@@ -737,7 +737,7 @@
                 const_token: input.parse()?,
                 ident: input.parse()?,
                 colon_token: input.parse()?,
-                ty: input.parse_synom(Type::parse)?,
+                ty: input.parse()?,
                 eq_token: {
                     if input.peek(Token![=]) {
                         let eq_token = input.parse()?;
@@ -822,7 +822,7 @@
             } else {
                 Ok(WherePredicate::Type(PredicateType {
                     lifetimes: input.parse()?,
-                    bounded_ty: input.parse_synom(Type::parse)?,
+                    bounded_ty: input.parse()?,
                     colon_token: input.parse()?,
                     bounds: {
                         let mut bounds = Punctuated::new();
diff --git a/src/group.rs b/src/group.rs
index 28f3333..1f46f2b 100644
--- a/src/group.rs
+++ b/src/group.rs
@@ -19,8 +19,13 @@
     pub content: ParseBuffer<'a>,
 }
 
+pub struct Group<'a> {
+    pub token: token::Group,
+    pub content: ParseBuffer<'a>,
+}
+
 impl<'a> ParseBuffer<'a> {
-    fn parse_group(&self, delimiter: Delimiter) -> Result<(Span, ParseBuffer<'a>)> {
+    fn parse_delimited(&self, delimiter: Delimiter) -> Result<(Span, ParseBuffer<'a>)> {
         self.step_cursor(|cursor| {
             if let Some((content, span, rest)) = cursor.group(delimiter) {
                 let content =
@@ -31,7 +36,7 @@
                     Delimiter::Parenthesis => "expected parentheses",
                     Delimiter::Brace => "expected curly braces",
                     Delimiter::Bracket => "expected square brackets",
-                    Delimiter::None => unreachable!(),
+                    Delimiter::None => "expected invisible group",
                 };
                 Err(cursor.error(message))
             }
@@ -41,7 +46,7 @@
     // Not public API.
     #[doc(hidden)]
     pub fn parse_parens(&self) -> Result<Parens<'a>> {
-        self.parse_group(Delimiter::Parenthesis)
+        self.parse_delimited(Delimiter::Parenthesis)
             .map(|(span, content)| Parens {
                 token: token::Paren(span),
                 content: content,
@@ -51,7 +56,7 @@
     // Not public API.
     #[doc(hidden)]
     pub fn parse_braces(&self) -> Result<Braces<'a>> {
-        self.parse_group(Delimiter::Brace)
+        self.parse_delimited(Delimiter::Brace)
             .map(|(span, content)| Braces {
                 token: token::Brace(span),
                 content: content,
@@ -61,12 +66,22 @@
     // Not public API.
     #[doc(hidden)]
     pub fn parse_brackets(&self) -> Result<Brackets<'a>> {
-        self.parse_group(Delimiter::Bracket)
+        self.parse_delimited(Delimiter::Bracket)
             .map(|(span, content)| Brackets {
                 token: token::Bracket(span),
                 content: content,
             })
     }
+
+    // Not public API.
+    #[doc(hidden)]
+    pub fn parse_group(&self) -> Result<Group<'a>> {
+        self.parse_delimited(Delimiter::None)
+            .map(|(span, content)| Group {
+                token: token::Group(span),
+                content: content,
+            })
+    }
 }
 
 /// Parse a set of parentheses and expose their content to subsequent parsers.
@@ -152,3 +167,19 @@
         }
     };
 }
+
+#[doc(hidden)]
+#[macro_export]
+macro_rules! grouped {
+    ($content:ident in $cursor:expr) => {
+        match $crate::parse::ParseBuffer::parse_group(&$cursor) {
+            $crate::export::Ok(group) => {
+                $content = group.content;
+                group.token
+            }
+            $crate::export::Err(error) => {
+                return $crate::export::Err(error);
+            }
+        }
+    };
+}
diff --git a/src/item.rs b/src/item.rs
index 569c1c8..9e28808 100644
--- a/src/item.rs
+++ b/src/item.rs
@@ -806,7 +806,7 @@
 
     impl_synom!(ItemMacro "macro item" do_parse!(
         attrs: many0!(Attribute::old_parse_outer) >>
-        what: call!(Path::parse_mod_style) >>
+        what: call!(Path::old_parse_mod_style) >>
         bang: punct!(!) >>
         ident: option!(syn!(Ident)) >>
         body: call!(tt::delimited) >>
diff --git a/src/lit.rs b/src/lit.rs
index a25d2a3..908ff89 100644
--- a/src/lit.rs
+++ b/src/lit.rs
@@ -425,7 +425,6 @@
     use super::*;
     use parse::{Parse, ParseStream, Result};
     use parse_error;
-    use synom::Synom;
 
     impl Parse for Lit {
         fn parse(input: ParseStream) -> Result<Self> {
@@ -460,54 +459,75 @@
         }
     }
 
-    impl_synom!(LitStr "string literal" switch!(
-        syn!(Lit),
-        Lit::Str(lit) => value!(lit)
-        |
-        _ => reject!()
-    ));
+    impl Parse for LitStr {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let head = input.fork();
+            match input.parse()? {
+                Lit::Str(lit) => Ok(lit),
+                _ => Err(head.error("expected string literal")),
+            }
+        }
+    }
 
-    impl_synom!(LitByteStr "byte string literal" switch!(
-        syn!(Lit),
-        Lit::ByteStr(lit) => value!(lit)
-        |
-        _ => reject!()
-    ));
+    impl Parse for LitByteStr {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let head = input.fork();
+            match input.parse()? {
+                Lit::ByteStr(lit) => Ok(lit),
+                _ => Err(head.error("expected byte string literal")),
+            }
+        }
+    }
 
-    impl_synom!(LitByte "byte literal" switch!(
-        syn!(Lit),
-        Lit::Byte(lit) => value!(lit)
-        |
-        _ => reject!()
-    ));
+    impl Parse for LitByte {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let head = input.fork();
+            match input.parse()? {
+                Lit::Byte(lit) => Ok(lit),
+                _ => Err(head.error("expected byte literal")),
+            }
+        }
+    }
 
-    impl_synom!(LitChar "character literal" switch!(
-        syn!(Lit),
-        Lit::Char(lit) => value!(lit)
-        |
-        _ => reject!()
-    ));
+    impl Parse for LitChar {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let head = input.fork();
+            match input.parse()? {
+                Lit::Char(lit) => Ok(lit),
+                _ => Err(head.error("expected character literal")),
+            }
+        }
+    }
 
-    impl_synom!(LitInt "integer literal" switch!(
-        syn!(Lit),
-        Lit::Int(lit) => value!(lit)
-        |
-        _ => reject!()
-    ));
+    impl Parse for LitInt {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let head = input.fork();
+            match input.parse()? {
+                Lit::Int(lit) => Ok(lit),
+                _ => Err(head.error("expected integer literal")),
+            }
+        }
+    }
 
-    impl_synom!(LitFloat "floating point literal" switch!(
-        syn!(Lit),
-        Lit::Float(lit) => value!(lit)
-        |
-        _ => reject!()
-    ));
+    impl Parse for LitFloat {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let head = input.fork();
+            match input.parse()? {
+                Lit::Float(lit) => Ok(lit),
+                _ => Err(head.error("expected floating point literal")),
+            }
+        }
+    }
 
-    impl_synom!(LitBool "boolean literal" switch!(
-        syn!(Lit),
-        Lit::Bool(lit) => value!(lit)
-        |
-        _ => reject!()
-    ));
+    impl Parse for LitBool {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let head = input.fork();
+            match input.parse()? {
+                Lit::Bool(lit) => Ok(lit),
+                _ => Err(head.error("expected boolean literal")),
+            }
+        }
+    }
 }
 
 #[cfg(feature = "printing")]
diff --git a/src/mac.rs b/src/mac.rs
index a9219fe..b08c8a1 100644
--- a/src/mac.rs
+++ b/src/mac.rs
@@ -8,8 +8,12 @@
 
 use super::*;
 use proc_macro2::TokenStream;
+#[cfg(feature = "parsing")]
+use proc_macro2::{Delimiter, TokenTree};
 use token::{Brace, Bracket, Paren};
 
+#[cfg(feature = "parsing")]
+use parse::{ParseStream, Result};
 #[cfg(feature = "extra-traits")]
 use std::hash::{Hash, Hasher};
 #[cfg(feature = "extra-traits")]
@@ -67,26 +71,44 @@
 }
 
 #[cfg(feature = "parsing")]
+pub fn parse_delimiter(input: ParseStream) -> Result<(MacroDelimiter, TokenStream)> {
+    input.step_cursor(|cursor| {
+        if let Some((TokenTree::Group(g), rest)) = cursor.token_tree() {
+            let span = g.span();
+            let delimiter = match g.delimiter() {
+                Delimiter::Parenthesis => MacroDelimiter::Paren(Paren(span)),
+                Delimiter::Brace => MacroDelimiter::Brace(Brace(span)),
+                Delimiter::Bracket => MacroDelimiter::Bracket(Bracket(span)),
+                Delimiter::None => {
+                    return Err(cursor.error("expected delimiter"));
+                }
+            };
+            Ok(((delimiter, g.stream().clone()), rest))
+        } else {
+            Err(cursor.error("expected delimiter"))
+        }
+    })
+}
+
+#[cfg(feature = "parsing")]
 pub mod parsing {
     use super::*;
 
-    use synom::Synom;
+    use parse::{Parse, ParseStream, Result};
 
-    impl Synom for Macro {
-        named!(parse -> Self, do_parse!(
-            what: call!(Path::parse_mod_style) >>
-            bang: punct!(!) >>
-            body: call!(tt::delimited) >>
-            (Macro {
-                path: what,
-                bang_token: bang,
-                delimiter: body.0,
-                tts: body.1,
+    impl Parse for Macro {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let tts;
+            Ok(Macro {
+                path: input.call(Path::parse_mod_style)?,
+                bang_token: input.parse()?,
+                delimiter: {
+                    let (delimiter, content) = parse_delimiter(input)?;
+                    tts = content;
+                    delimiter
+                },
+                tts: tts,
             })
-        ));
-
-        fn description() -> Option<&'static str> {
-            Some("macro invocation")
         }
     }
 }
diff --git a/src/macros.rs b/src/macros.rs
index f4e7d0a..5966e38 100644
--- a/src/macros.rs
+++ b/src/macros.rs
@@ -179,10 +179,7 @@
     ($($rest:tt)*) => (ast_struct! { $($rest)* });
 }
 
-#[cfg(all(
-    feature = "parsing",
-    any(feature = "full", feature = "derive")
-))]
+#[cfg(all(feature = "parsing", feature = "full"))]
 macro_rules! impl_synom {
     ($t:ident $description:tt $($parser:tt)+) => {
         impl Synom for $t {
diff --git a/src/parse.rs b/src/parse.rs
index c87ad9f..64f972d 100644
--- a/src/parse.rs
+++ b/src/parse.rs
@@ -115,7 +115,9 @@
             return false;
         }
         let ahead = self.fork();
-        ahead.step_cursor(|cursor| Ok(cursor.token_tree().unwrap())).unwrap();
+        ahead
+            .step_cursor(|cursor| Ok(cursor.token_tree().unwrap()))
+            .unwrap();
         ahead.peek(token)
     }
 
@@ -124,8 +126,12 @@
             return false;
         }
         let ahead = self.fork();
-        ahead.step_cursor(|cursor| Ok(cursor.token_tree().unwrap())).unwrap();
-        ahead.step_cursor(|cursor| Ok(cursor.token_tree().unwrap())).unwrap();
+        ahead
+            .step_cursor(|cursor| Ok(cursor.token_tree().unwrap()))
+            .unwrap();
+        ahead
+            .step_cursor(|cursor| Ok(cursor.token_tree().unwrap()))
+            .unwrap();
         ahead.peek(token)
     }
 
@@ -216,6 +222,12 @@
     }
 }
 
+impl<T: Parse> Parse for Box<T> {
+    fn parse(input: ParseStream) -> Result<Self> {
+        input.parse().map(Box::new)
+    }
+}
+
 impl<T: Parse + Token> Parse for Option<T> {
     fn parse(input: ParseStream) -> Result<Self> {
         if T::peek(&input.lookahead1()) {
diff --git a/src/parsers.rs b/src/parsers.rs
index 400c0ca..c3c638b 100644
--- a/src/parsers.rs
+++ b/src/parsers.rs
@@ -1417,7 +1417,7 @@
 // Not public API.
 #[doc(hidden)]
 #[macro_export]
-macro_rules! grouped {
+macro_rules! old_grouped {
     ($i:expr, $submac:ident!( $($args:tt)* )) => {
         $crate::token::Group::parse($i, |i| $submac!(i, $($args)*))
     };
@@ -1426,3 +1426,19 @@
         grouped!($i, call!($f));
     };
 }
+
+macro_rules! shim {
+    ($i:expr, $parser:expr $(, $args:expr)*) => {{
+        let unexpected = ::std::rc::Rc::new(::std::cell::Cell::new(None));
+        let state = ::parse::ParseBuffer::new(::proc_macro2::Span::call_site(), $i, unexpected);
+        match $parser(&state $(, $args)*) {
+            Ok(node) => {
+                match state.check_unexpected() {
+                    Ok(()) => Ok((node, state.cursor())),
+                    Err(err) => Err(err),
+                }
+            }
+            Err(err) => Err(err),
+        }
+    }};
+}
diff --git a/src/path.rs b/src/path.rs
index 12c7549..c2ad34a 100644
--- a/src/path.rs
+++ b/src/path.rs
@@ -229,7 +229,6 @@
     use super::*;
     use parse::{Parse, ParseStream, Result};
     use synom::ext::IdentExt;
-    use synom::Synom;
 
     impl Parse for Path {
         fn parse(input: ParseStream) -> Result<Self> {
@@ -303,7 +302,7 @@
             Ok(ParenthesizedGenericArguments {
                 paren_token: parenthesized!(content in input),
                 inputs: content.parse_synom(Punctuated::parse_terminated)?,
-                output: input.parse_synom(ReturnType::without_plus)?,
+                output: input.call(ReturnType::without_plus)?,
             })
         }
     }
@@ -321,7 +320,7 @@
             }
 
             let ident = input.parse()?;
-            if input.peek(Token![<]) && !input.peek2(Token![=])
+            if input.peek(Token![<]) && !input.peek(Token![<=])
                 || input.peek(Token![::]) && input.peek3(Token![<])
             {
                 Ok(PathSegment {
@@ -339,16 +338,49 @@
             Ok(Binding {
                 ident: input.parse()?,
                 eq_token: input.parse()?,
-                ty: input.parse_synom(Type::parse)?,
+                ty: input.parse()?,
             })
         }
     }
 
     impl Path {
-        named!(pub parse_mod_style -> Self, do_parse!(
+        pub fn parse_mod_style(input: ParseStream) -> Result<Self> {
+            Ok(Path {
+                leading_colon: input.parse()?,
+                segments: {
+                    let mut segments = Punctuated::new();
+                    loop {
+                        if !input.peek(Ident)
+                            && !input.peek(Token![super])
+                            && !input.peek(Token![self])
+                            && !input.peek(Token![Self])
+                            && !input.peek(Token![crate])
+                            && !input.peek(Token![extern])
+                        {
+                            break;
+                        }
+                        let ident = Ident::parse_any2(input)?;
+                        segments.push_value(PathSegment::from(ident));
+                        if !input.peek(Token![::]) {
+                            break;
+                        }
+                        let punct = input.parse()?;
+                        segments.push_punct(punct);
+                    }
+                    if segments.is_empty() {
+                        return Err(input.error("expected path"));
+                    } else if segments.trailing_punct() {
+                        return Err(input.error("expected path segment"));
+                    }
+                    segments
+                },
+            })
+        }
+
+        named!(pub old_parse_mod_style -> Self, do_parse!(
             colon: option!(punct!(::)) >>
             segments: call!(Punctuated::parse_separated_nonempty_with,
-                            mod_style_path_segment) >>
+                            old_mod_style_path_segment) >>
             (Path {
                 leading_colon: colon,
                 segments: segments,
@@ -356,7 +388,30 @@
         ));
     }
 
-    named!(pub mod_style_path_segment -> PathSegment, alt!(
+    // FIXME
+    /*
+    pub fn mod_style_path_segment(input: ParseStream) -> Result<PathSegment> {
+        let lookahead = input.lookahead1();
+        let ident = if lookahead.peek(Ident) {
+            input.parse()?
+        } else if lookahead.peek(Token![super]) {
+            Ident::from(input.parse::<Token![super]>()?)
+        } else if lookahead.peek(Token![self]) {
+            Ident::from(input.parse::<Token![self]>()?)
+        } else if lookahead.peek(Token![Self]) {
+            Ident::from(input.parse::<Token![Self]>()?)
+        } else if lookahead.peek(Token![crate]) {
+            Ident::from(input.parse::<Token![crate]>()?)
+        } else if lookahead.peek(Token![extern]) {
+            Ident::from(input.parse::<Token![extern]>()?)
+        } else {
+            return Err(lookahead.error());
+        };
+        Ok(PathSegment::from(ident))
+    }
+    */
+
+    named!(pub old_mod_style_path_segment -> PathSegment, alt!(
         syn!(Ident) => { Into::into }
         |
         keyword!(super) => { Into::into }
@@ -370,44 +425,6 @@
         keyword!(extern) => { Into::into }
     ));
 
-    named!(pub qpath -> (Option<QSelf>, Path), alt!(
-        map!(syn!(Path), |p| (None, p))
-        |
-        do_parse!(
-            lt: punct!(<) >>
-            this: syn!(Type) >>
-            path: option!(tuple!(keyword!(as), syn!(Path))) >>
-            gt: punct!(>) >>
-            colon2: punct!(::) >>
-            rest: call!(Punctuated::parse_separated_nonempty) >>
-            ({
-                let (pos, as_, path) = match path {
-                    Some((as_, mut path)) => {
-                        let pos = path.segments.len();
-                        path.segments.push_punct(colon2);
-                        path.segments.extend(rest.into_pairs());
-                        (pos, Some(as_), path)
-                    }
-                    None => {
-                        (0, None, Path {
-                            leading_colon: Some(colon2),
-                            segments: rest,
-                        })
-                    }
-                };
-                (Some(QSelf {
-                    lt_token: lt,
-                    ty: Box::new(this),
-                    position: pos,
-                    as_token: as_,
-                    gt_token: gt,
-                }), path)
-            })
-        )
-        |
-        map!(keyword!(self), |s| (None, s.into()))
-    ));
-
     named!(pub ty_no_eq_after -> Type, do_parse!(
         ty: syn!(Type) >>
         not!(punct!(=)) >>
diff --git a/src/synom.rs b/src/synom.rs
index ed1c1b2..035b770 100644
--- a/src/synom.rs
+++ b/src/synom.rs
@@ -231,7 +231,7 @@
     fn parse(input: ParseStream) -> Result<Self> {
         input.step_cursor(|cursor| match cursor.token_tree() {
             Some((tt, rest)) => Ok((tt, rest)),
-            None => Err(cursor.error("expected token tree"))
+            None => Err(cursor.error("expected token tree")),
         })
     }
 }
diff --git a/src/token.rs b/src/token.rs
index 3ffe827..9f9b904 100644
--- a/src/token.rs
+++ b/src/token.rs
@@ -124,7 +124,7 @@
 #[cfg(feature = "parsing")]
 use lifetime::Lifetime;
 #[cfg(feature = "parsing")]
-use lit::Lit;
+use lit::{Lit, LitBool, LitByte, LitByteStr, LitChar, LitFloat, LitInt, LitStr};
 #[cfg(feature = "parsing")]
 use lookahead;
 #[cfg(feature = "parsing")]
@@ -177,6 +177,13 @@
 impl_token!(Ident "identifier");
 impl_token!(Lifetime "lifetime");
 impl_token!(Lit "literal");
+impl_token!(LitStr "string literal");
+impl_token!(LitByteStr "byte string literal");
+impl_token!(LitByte "byte literal");
+impl_token!(LitChar "character literal");
+impl_token!(LitInt "integer literal");
+impl_token!(LitFloat "floating point literal");
+impl_token!(LitBool "boolean literal");
 
 macro_rules! define_keywords {
     ($($token:tt pub struct $name:ident #[$doc:meta])*) => {
@@ -493,6 +500,17 @@
     }
 }
 
+#[cfg(feature = "parsing")]
+impl Token for Group {
+    fn peek(lookahead: &Lookahead1) -> bool {
+        lookahead::is_delimiter(lookahead, Delimiter::None)
+    }
+
+    fn display() -> String {
+        "invisible group".to_owned()
+    }
+}
+
 define_keywords! {
     "as"          pub struct As           /// `as`
     "async"       pub struct Async        /// `async`
diff --git a/src/tt.rs b/src/tt.rs
index bde82dc..3fe12f8 100644
--- a/src/tt.rs
+++ b/src/tt.rs
@@ -6,22 +6,25 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#[cfg(feature = "parsing")]
+#[cfg(all(feature = "full", feature = "parsing"))]
 use buffer::Cursor;
-#[cfg(feature = "parsing")]
+#[cfg(all(feature = "full", feature = "parsing"))]
 use synom::PResult;
-#[cfg(feature = "parsing")]
+#[cfg(all(feature = "full", feature = "parsing"))]
 use token::{Brace, Bracket, Paren};
-#[cfg(feature = "parsing")]
+#[cfg(all(feature = "full", feature = "parsing"))]
 use {parse_error, MacroDelimiter};
 
 #[cfg(feature = "extra-traits")]
 use std::hash::{Hash, Hasher};
 
-#[cfg(any(feature = "parsing", feature = "extra-traits"))]
+#[cfg(any(
+    all(feature = "full", feature = "parsing"),
+    feature = "extra-traits"
+))]
 use proc_macro2::{Delimiter, TokenStream, TokenTree};
 
-#[cfg(feature = "parsing")]
+#[cfg(all(feature = "full", feature = "parsing"))]
 pub fn delimited(input: Cursor) -> PResult<(MacroDelimiter, TokenStream)> {
     if let Some((TokenTree::Group(g), rest)) = input.token_tree() {
         let span = g.span();
diff --git a/src/ty.rs b/src/ty.rs
index 81e4df5..fa1083f 100644
--- a/src/ty.rs
+++ b/src/ty.rs
@@ -73,10 +73,10 @@
         /// *This type is available if Syn is built with the `"derive"` or
         /// `"full"` feature.*
         pub BareFn(TypeBareFn {
+            pub lifetimes: Option<BoundLifetimes>,
             pub unsafety: Option<Token![unsafe]>,
             pub abi: Option<Abi>,
             pub fn_token: Token![fn],
-            pub lifetimes: Option<BoundLifetimes>,
             pub paren_token: token::Paren,
             pub inputs: Punctuated<BareFnArg, Token![,]>,
             pub variadic: Option<Token![...]>,
@@ -249,14 +249,12 @@
 #[cfg(feature = "parsing")]
 pub mod parsing {
     use super::*;
-    use path::parsing::qpath;
+    use parse::{Parse, ParseStream, Result};
     use synom::Synom;
 
-    impl Synom for Type {
-        named!(parse -> Self, call!(ambig_ty, true));
-
-        fn description() -> Option<&'static str> {
-            Some("type")
+    impl Parse for Type {
+        fn parse(input: ParseStream) -> Result<Self> {
+            ambig_ty(input, true)
         }
     }
 
@@ -266,250 +264,389 @@
         /// contain a `+` character.
         ///
         /// This parser does not allow a `+`, while the default parser does.
-        named!(pub without_plus -> Self, call!(ambig_ty, false));
-    }
-
-    named!(ambig_ty(allow_plus: bool) -> Type, alt!(
-        syn!(TypeGroup) => { Type::Group }
-        |
-        // must be before TypeTuple
-        call!(TypeParen::parse, allow_plus) => { Type::Paren }
-        |
-        // must be before TypePath
-        syn!(TypeMacro) => { Type::Macro }
-        |
-        // must be before TypePath
-        syn!(TypeBareFn) => { Type::BareFn }
-        |
-        // must be before TypeTraitObject
-        call!(TypePath::parse, allow_plus) => { Type::Path }
-        |
-        // Don't try parsing more than one trait bound if we aren't allowing it.
-        // must be before TypeTuple
-        call!(TypeTraitObject::parse, allow_plus) => { Type::TraitObject }
-        |
-        syn!(TypeSlice) => { Type::Slice }
-        |
-        syn!(TypeArray) => { Type::Array }
-        |
-        syn!(TypePtr) => { Type::Ptr }
-        |
-        syn!(TypeReference) => { Type::Reference }
-        |
-        syn!(TypeNever) => { Type::Never }
-        |
-        syn!(TypeTuple) => { Type::Tuple }
-        |
-        syn!(TypeImplTrait) => { Type::ImplTrait }
-        |
-        syn!(TypeInfer) => { Type::Infer }
-    ));
-
-    impl Synom for TypeSlice {
-        named!(parse -> Self, map!(
-            brackets!(syn!(Type)),
-            |(b, ty)| TypeSlice {
-                elem: Box::new(ty),
-                bracket_token: b,
-            }
-        ));
-
-        fn description() -> Option<&'static str> {
-            Some("slice type")
+        pub fn without_plus(input: ParseStream) -> Result<Self> {
+            ambig_ty(input, false)
         }
     }
 
-    impl Synom for TypeArray {
-        named!(parse -> Self, map!(
-            brackets!(do_parse!(
-                elem: syn!(Type) >>
-                    semi: punct!(;) >>
-                    len: syn!(Expr) >>
-                    (elem, semi, len)
-            )),
-            |(brackets, (elem, semi, len))| {
-                TypeArray {
+    fn ambig_ty(input: ParseStream, allow_plus: bool) -> Result<Type> {
+        if input.peek(token::Group) {
+            return input.parse().map(Type::Group);
+        }
+
+        let mut lifetimes = None::<BoundLifetimes>;
+        let mut lookahead = input.lookahead1();
+        if lookahead.peek(Token![for]) {
+            lifetimes = input.parse()?;
+            lookahead = input.lookahead1();
+            if !lookahead.peek(Ident)
+                && !lookahead.peek(Token![fn])
+                && !lookahead.peek(Token![unsafe])
+                && !lookahead.peek(Token![extern])
+                && !lookahead.peek(Token![super])
+                && !lookahead.peek(Token![self])
+                && !lookahead.peek(Token![Self])
+                && !lookahead.peek(Token![crate])
+            {
+                return Err(lookahead.error());
+            }
+        }
+
+        if lookahead.peek(token::Paren) {
+            let content;
+            let paren_token = parenthesized!(content in input);
+            if content.is_empty() {
+                return Ok(Type::Tuple(TypeTuple {
+                    paren_token: paren_token,
+                    elems: Punctuated::new(),
+                }));
+            }
+            if content.peek(Lifetime) {
+                return Ok(Type::Paren(TypeParen {
+                    paren_token: paren_token,
+                    elem: Box::new(Type::TraitObject(content.parse()?)),
+                }));
+            }
+            let first: Type = content.parse()?;
+            if content.peek(Token![,]) {
+                Ok(Type::Tuple(TypeTuple {
+                    paren_token: paren_token,
+                    elems: {
+                        let mut elems = Punctuated::new();
+                        elems.push_value(first);
+                        elems.push_punct(content.parse()?);
+                        let rest: Punctuated<Type, Token![,]> =
+                            content.parse_terminated(Parse::parse)?;
+                        elems.extend(rest);
+                        elems
+                    },
+                }))
+            } else {
+                Ok(Type::Paren(TypeParen {
+                    paren_token: paren_token,
+                    elem: Box::new(first),
+                }))
+            }
+        } else if lookahead.peek(Token![fn])
+            || lookahead.peek(Token![unsafe])
+            || lookahead.peek(Token![extern]) && !input.peek2(Token![::])
+        {
+            let mut bare_fn: TypeBareFn = input.parse()?;
+            bare_fn.lifetimes = lifetimes;
+            Ok(Type::BareFn(bare_fn))
+        } else if lookahead.peek(Ident)
+            || input.peek(Token![super])
+            || input.peek(Token![self])
+            || input.peek(Token![Self])
+            || input.peek(Token![crate])
+            || input.peek(Token![extern])
+            || lookahead.peek(Token![::])
+            || lookahead.peek(Token![<])
+        {
+            if input.peek(Token![dyn]) {
+                let mut trait_object: TypeTraitObject = input.parse()?;
+                if lifetimes.is_some() {
+                    match *trait_object.bounds.iter_mut().next().unwrap() {
+                        TypeParamBound::Trait(ref mut trait_bound) => {
+                            trait_bound.lifetimes = lifetimes;
+                        }
+                        TypeParamBound::Lifetime(_) => unreachable!(),
+                    }
+                }
+                return Ok(Type::TraitObject(trait_object));
+            }
+
+            let ty: TypePath = input.parse()?;
+            if ty.qself.is_some() {
+                return Ok(Type::Path(ty));
+            }
+
+            if input.peek(Token![!]) && !input.peek(Token![!=]) {
+                let mut contains_arguments = false;
+                for segment in &ty.path.segments {
+                    match segment.arguments {
+                        PathArguments::None => {}
+                        PathArguments::AngleBracketed(_) | PathArguments::Parenthesized(_) => {
+                            contains_arguments = true;
+                        }
+                    }
+                }
+
+                if !contains_arguments {
+                    let bang_token: Token![!] = input.parse()?;
+                    let (delimiter, tts) = mac::parse_delimiter(input)?;
+                    return Ok(Type::Macro(TypeMacro {
+                        mac: Macro {
+                            path: ty.path,
+                            bang_token: bang_token,
+                            delimiter: delimiter,
+                            tts: tts,
+                        },
+                    }));
+                }
+            }
+
+            if lifetimes.is_some() || allow_plus && input.peek(Token![+]) {
+                let mut bounds = Punctuated::new();
+                bounds.push_value(TypeParamBound::Trait(TraitBound {
+                    paren_token: None,
+                    modifier: TraitBoundModifier::None,
+                    lifetimes: lifetimes,
+                    path: ty.path,
+                }));
+                if allow_plus && input.peek(Token![+]) {
+                    bounds.push_punct(input.parse()?);
+                    let rest: Punctuated<TypeParamBound, Token![+]> =
+                        input.parse_synom(Punctuated::parse_terminated_nonempty)?;
+                    bounds.extend(rest);
+                }
+                return Ok(Type::TraitObject(TypeTraitObject {
+                    dyn_token: None,
+                    bounds: bounds,
+                }));
+            }
+
+            Ok(Type::Path(ty))
+        } else if lookahead.peek(token::Bracket) {
+            let content;
+            let bracket_token = bracketed!(content in input);
+            let elem: Type = content.parse()?;
+            if content.peek(Token![;]) {
+                Ok(Type::Array(TypeArray {
+                    bracket_token: bracket_token,
                     elem: Box::new(elem),
-                    len: len,
-                    bracket_token: brackets,
-                    semi_token: semi,
-                }
+                    semi_token: content.parse()?,
+                    len: content.parse_synom(Expr::parse)?,
+                }))
+            } else {
+                Ok(Type::Slice(TypeSlice {
+                    bracket_token: bracket_token,
+                    elem: Box::new(elem),
+                }))
             }
-        ));
-
-        fn description() -> Option<&'static str> {
-            Some("array type")
+        } else if lookahead.peek(Token![*]) {
+            input.parse().map(Type::Ptr)
+        } else if lookahead.peek(Token![&]) {
+            input.parse().map(Type::Reference)
+        } else if lookahead.peek(Token![!]) && !input.peek(Token![=]) {
+            input.parse().map(Type::Never)
+        } else if lookahead.peek(Token![impl ]) {
+            input.parse().map(Type::ImplTrait)
+        } else if lookahead.peek(Token![_]) {
+            input.parse().map(Type::Infer)
+        } else if lookahead.peek(Lifetime) {
+            input.parse().map(Type::TraitObject)
+        } else {
+            Err(lookahead.error())
         }
     }
 
-    impl Synom for TypePtr {
-        named!(parse -> Self, do_parse!(
-            star: punct!(*) >>
-            mutability: alt!(
-                keyword!(const) => { |c| (None, Some(c)) }
-                |
-                keyword!(mut) => { |m| (Some(m), None) }
-            ) >>
-            target: call!(Type::without_plus) >>
-            (TypePtr {
-                const_token: mutability.1,
-                star_token: star,
-                mutability: mutability.0,
-                elem: Box::new(target),
+    impl Parse for TypeSlice {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let content;
+            Ok(TypeSlice {
+                bracket_token: bracketed!(content in input),
+                elem: content.parse()?,
             })
-        ));
-
-        fn description() -> Option<&'static str> {
-            Some("raw pointer type")
         }
     }
 
-    impl Synom for TypeReference {
-        named!(parse -> Self, do_parse!(
-            amp: punct!(&) >>
-            life: option!(syn!(Lifetime)) >>
-            mutability: option!(keyword!(mut)) >>
-            // & binds tighter than +, so we don't allow + here.
-            target: call!(Type::without_plus) >>
-            (TypeReference {
-                lifetime: life,
+    impl Parse for TypeArray {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let content;
+            Ok(TypeArray {
+                bracket_token: bracketed!(content in input),
+                elem: content.parse()?,
+                semi_token: content.parse()?,
+                len: content.parse_synom(Expr::parse)?,
+            })
+        }
+    }
+
+    impl Parse for TypePtr {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let star_token: Token![*] = input.parse()?;
+
+            let lookahead = input.lookahead1();
+            let (const_token, mutability) = if lookahead.peek(Token![const]) {
+                (Some(input.parse()?), None)
+            } else if lookahead.peek(Token![mut]) {
+                (None, Some(input.parse()?))
+            } else {
+                return Err(lookahead.error());
+            };
+
+            Ok(TypePtr {
+                star_token: star_token,
+                const_token: const_token,
                 mutability: mutability,
-                elem: Box::new(target),
-                and_token: amp,
+                elem: Box::new(input.call(Type::without_plus)?),
             })
-        ));
-
-        fn description() -> Option<&'static str> {
-            Some("reference type")
         }
     }
 
-    impl Synom for TypeBareFn {
-        named!(parse -> Self, do_parse!(
-            lifetimes: option!(syn!(BoundLifetimes)) >>
-            unsafety: option!(keyword!(unsafe)) >>
-            abi: option!(syn!(Abi)) >>
-            fn_: keyword!(fn) >>
-            parens: parens!(do_parse!(
-                inputs: call!(Punctuated::parse_terminated) >>
-                variadic: option!(cond_reduce!(inputs.empty_or_trailing(), punct!(...))) >>
-                (inputs, variadic)
-            )) >>
-            output: call!(ReturnType::without_plus) >>
-            (TypeBareFn {
-                unsafety: unsafety,
-                abi: abi,
-                lifetimes: lifetimes,
-                output: output,
-                variadic: (parens.1).1,
-                fn_token: fn_,
-                paren_token: parens.0,
-                inputs: (parens.1).0,
+    impl Parse for TypeReference {
+        fn parse(input: ParseStream) -> Result<Self> {
+            Ok(TypeReference {
+                and_token: input.parse()?,
+                lifetime: input.parse()?,
+                mutability: input.parse()?,
+                // & binds tighter than +, so we don't allow + here.
+                elem: Box::new(input.call(Type::without_plus)?),
             })
-        ));
-
-        fn description() -> Option<&'static str> {
-            Some("`fn` type")
         }
     }
 
-    impl Synom for TypeNever {
-        named!(parse -> Self, map!(
-            punct!(!),
-            |b| TypeNever { bang_token: b }
-        ));
-
-        fn description() -> Option<&'static str> {
-            Some("never type: `!`")
-        }
-    }
-
-    impl Synom for TypeInfer {
-        named!(parse -> Self, map!(
-            punct!(_),
-            |u| TypeInfer { underscore_token: u }
-        ));
-
-        fn description() -> Option<&'static str> {
-            Some("inferred type: `_`")
-        }
-    }
-
-    impl Synom for TypeTuple {
-        named!(parse -> Self, do_parse!(
-            data: parens!(Punctuated::parse_terminated) >>
-            (TypeTuple {
-                paren_token: data.0,
-                elems: data.1,
+    impl Parse for TypeBareFn {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let args;
+            let allow_variadic;
+            Ok(TypeBareFn {
+                lifetimes: input.parse()?,
+                unsafety: input.parse()?,
+                abi: input.parse()?,
+                fn_token: input.parse()?,
+                paren_token: parenthesized!(args in input),
+                inputs: {
+                    let inputs = args.parse_synom(Punctuated::parse_terminated)?;
+                    allow_variadic = inputs.empty_or_trailing();
+                    inputs
+                },
+                variadic: {
+                    if allow_variadic && args.peek(Token![...]) {
+                        Some(args.parse()?)
+                    } else {
+                        None
+                    }
+                },
+                output: input.call(ReturnType::without_plus)?,
             })
-        ));
-
-        fn description() -> Option<&'static str> {
-            Some("tuple type")
         }
     }
 
-    impl Synom for TypeMacro {
-        named!(parse -> Self, map!(syn!(Macro), |mac| TypeMacro { mac: mac }));
-
-        fn description() -> Option<&'static str> {
-            Some("macro invocation")
-        }
-    }
-
-    impl Synom for TypePath {
-        named!(parse -> Self, call!(Self::parse, false));
-
-        fn description() -> Option<&'static str> {
-            Some("type path")
-        }
-    }
-
-    impl TypePath {
-        named!(parse(allow_plus: bool) -> Self, do_parse!(
-            qpath: qpath >>
-            parenthesized: option!(cond_reduce!(
-                qpath.1.segments.last().unwrap().value().arguments.is_empty(),
-                syn!(ParenthesizedGenericArguments)
-            )) >>
-            cond!(allow_plus, not!(punct!(+))) >>
-            ({
-                let (qself, mut path) = qpath;
-                if let Some(parenthesized) = parenthesized {
-                    let parenthesized = PathArguments::Parenthesized(parenthesized);
-                    path.segments.last_mut().unwrap().value_mut().arguments = parenthesized;
-                }
-                TypePath { qself: qself, path: path }
+    impl Parse for TypeNever {
+        fn parse(input: ParseStream) -> Result<Self> {
+            Ok(TypeNever {
+                bang_token: input.parse()?,
             })
-        ));
+        }
+    }
+
+    impl Parse for TypeInfer {
+        fn parse(input: ParseStream) -> Result<Self> {
+            Ok(TypeInfer {
+                underscore_token: input.parse()?,
+            })
+        }
+    }
+
+    impl Parse for TypeTuple {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let content;
+            Ok(TypeTuple {
+                paren_token: parenthesized!(content in input),
+                elems: content.parse_terminated(<Type as Parse>::parse)?,
+            })
+        }
+    }
+
+    impl Parse for TypeMacro {
+        fn parse(input: ParseStream) -> Result<Self> {
+            Ok(TypeMacro {
+                mac: input.parse()?,
+            })
+        }
+    }
+
+    impl Parse for TypePath {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let (qself, mut path) = if input.peek(Token![<]) {
+                let lt_token: Token![<] = input.parse()?;
+                let this: Type = input.parse()?;
+                let path = if input.peek(Token![as]) {
+                    let as_token: Token![as] = input.parse()?;
+                    let path: Path = input.parse()?;
+                    Some((as_token, path))
+                } else {
+                    None
+                };
+                let gt_token: Token![>] = input.parse()?;
+                let colon2_token: Token![::] = input.parse()?;
+                let rest = input.parse_synom(Punctuated::parse_separated_nonempty)?;
+                let (position, as_token, path) = match path {
+                    Some((as_token, mut path)) => {
+                        let pos = path.segments.len();
+                        path.segments.push_punct(colon2_token);
+                        path.segments.extend(rest.into_pairs());
+                        (pos, Some(as_token), path)
+                    }
+                    None => {
+                        let path = Path {
+                            leading_colon: Some(colon2_token),
+                            segments: rest,
+                        };
+                        (0, None, path)
+                    }
+                };
+                let qself = QSelf {
+                    lt_token: lt_token,
+                    ty: Box::new(this),
+                    position: position,
+                    as_token: as_token,
+                    gt_token: gt_token,
+                };
+                (Some(qself), path)
+            } else {
+                let path: Path = input.parse()?;
+                (None, path)
+            };
+
+            let parenthesized = if path.segments.last().unwrap().value().arguments.is_empty()
+                && input.peek(token::Paren)
+            {
+                let args: ParenthesizedGenericArguments = input.parse()?;
+                Some(args)
+            } else {
+                None
+            };
+
+            if let Some(parenthesized) = parenthesized {
+                let parenthesized = PathArguments::Parenthesized(parenthesized);
+                path.segments.last_mut().unwrap().value_mut().arguments = parenthesized;
+            }
+
+            Ok(TypePath {
+                qself: qself,
+                path: path,
+            })
+        }
     }
 
     impl ReturnType {
-        named!(pub without_plus -> Self, call!(Self::parse, false));
-        named!(parse(allow_plus: bool) -> Self, alt!(
-            do_parse!(
-                arrow: punct!(->) >>
-                ty: call!(ambig_ty, allow_plus) >>
-                (ReturnType::Type(arrow, Box::new(ty)))
-            )
-            |
-            epsilon!() => { |_| ReturnType::Default }
-        ));
-    }
+        pub fn without_plus(input: ParseStream) -> Result<Self> {
+            Self::parse(input, false)
+        }
 
-    impl Synom for ReturnType {
-        named!(parse -> Self, call!(Self::parse, true));
-
-        fn description() -> Option<&'static str> {
-            Some("return type")
+        pub fn parse(input: ParseStream, allow_plus: bool) -> Result<Self> {
+            if input.peek(Token![->]) {
+                let arrow = input.parse()?;
+                let ty = ambig_ty(input, allow_plus)?;
+                Ok(ReturnType::Type(arrow, Box::new(ty)))
+            } else {
+                Ok(ReturnType::Default)
+            }
         }
     }
 
-    impl Synom for TypeTraitObject {
-        named!(parse -> Self, call!(Self::parse, true));
+    impl Parse for ReturnType {
+        fn parse(input: ParseStream) -> Result<Self> {
+            Self::parse(input, true)
+        }
+    }
 
-        fn description() -> Option<&'static str> {
-            Some("trait object type")
+    impl Parse for TypeTraitObject {
+        fn parse(input: ParseStream) -> Result<Self> {
+            Self::parse(input, true)
         }
     }
 
@@ -523,123 +660,118 @@
     }
 
     impl TypeTraitObject {
-        named!(pub without_plus -> Self, call!(Self::parse, false));
+        pub fn without_plus(input: ParseStream) -> Result<Self> {
+            Self::parse(input, false)
+        }
 
         // Only allow multiple trait references if allow_plus is true.
-        named!(parse(allow_plus: bool) -> Self, do_parse!(
-            dyn_token: option!(keyword!(dyn)) >>
-            bounds: alt!(
-                cond_reduce!(allow_plus, Punctuated::parse_terminated_nonempty)
-                |
-                syn!(TypeParamBound) => {|x| {
-                    let mut bounds = Punctuated::new();
-                    bounds.push_value(x);
+        pub fn parse(input: ParseStream, allow_plus: bool) -> Result<Self> {
+            Ok(TypeTraitObject {
+                dyn_token: input.parse()?,
+                bounds: {
+                    let bounds = if allow_plus {
+                        input.parse_synom(Punctuated::parse_terminated_nonempty)?
+                    } else {
+                        let mut bounds = Punctuated::new();
+                        bounds.push_value(input.parse()?);
+                        bounds
+                    };
+                    // Just lifetimes like `'a + 'b` is not a TraitObject.
+                    if !at_least_one_type(&bounds) {
+                        return Err(input.error("expected at least one type"));
+                    }
                     bounds
-                }}
-            ) >>
-            // Just lifetimes like `'a + 'b` is not a TraitObject.
-            cond_reduce!(at_least_one_type(&bounds)) >>
-            (TypeTraitObject {
-                dyn_token: dyn_token,
-                bounds: bounds,
+                },
             })
-        ));
-    }
-
-    impl Synom for TypeImplTrait {
-        named!(parse -> Self, do_parse!(
-            impl_: keyword!(impl) >>
-            // NOTE: rust-lang/rust#34511 includes discussion about whether or
-            // not + should be allowed in ImplTrait directly without ().
-            elem: call!(Punctuated::parse_terminated_nonempty) >>
-            (TypeImplTrait {
-                impl_token: impl_,
-                bounds: elem,
-            })
-        ));
-
-        fn description() -> Option<&'static str> {
-            Some("`impl Trait` type")
         }
     }
 
-    impl Synom for TypeGroup {
-        named!(parse -> Self, do_parse!(
-            data: grouped!(syn!(Type)) >>
-            (TypeGroup {
-                group_token: data.0,
-                elem: Box::new(data.1),
+    impl Parse for TypeImplTrait {
+        fn parse(input: ParseStream) -> Result<Self> {
+            Ok(TypeImplTrait {
+                impl_token: input.parse()?,
+                // NOTE: rust-lang/rust#34511 includes discussion about whether
+                // or not + should be allowed in ImplTrait directly without ().
+                bounds: input.parse_synom(Punctuated::parse_terminated_nonempty)?,
             })
-        ));
-
-        fn description() -> Option<&'static str> {
-            Some("type surrounded by invisible delimiters")
         }
     }
 
-    impl Synom for TypeParen {
-        named!(parse -> Self, call!(Self::parse, false));
+    impl Parse for TypeGroup {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let content;
+            Ok(TypeGroup {
+                group_token: grouped!(content in input),
+                elem: content.parse()?,
+            })
+        }
+    }
 
-        fn description() -> Option<&'static str> {
-            Some("parenthesized type")
+    impl Parse for TypeParen {
+        fn parse(input: ParseStream) -> Result<Self> {
+            Self::parse(input, false)
         }
     }
 
     impl TypeParen {
-        named!(parse(allow_plus: bool) -> Self, do_parse!(
-            data: parens!(syn!(Type)) >>
-            cond!(allow_plus, not!(punct!(+))) >>
-            (TypeParen {
-                paren_token: data.0,
-                elem: Box::new(data.1),
+        fn parse(input: ParseStream, allow_plus: bool) -> Result<Self> {
+            let content;
+            Ok(TypeParen {
+                paren_token: parenthesized!(content in input),
+                elem: Box::new(ambig_ty(&content, allow_plus)?),
             })
-        ));
-    }
-
-    impl Synom for BareFnArg {
-        named!(parse -> Self, do_parse!(
-            name: option!(do_parse!(
-                name: syn!(BareFnArgName) >>
-                not!(punct!(::)) >>
-                colon: punct!(:) >>
-                (name, colon)
-            )) >>
-            ty: syn!(Type) >>
-            (BareFnArg {
-                name: name,
-                ty: ty,
-            })
-        ));
-
-        fn description() -> Option<&'static str> {
-            Some("function type argument")
         }
     }
 
-    impl Synom for BareFnArgName {
-        named!(parse -> Self, alt!(
-            map!(syn!(Ident), BareFnArgName::Named)
-            |
-            map!(punct!(_), BareFnArgName::Wild)
-        ));
-
-        fn description() -> Option<&'static str> {
-            Some("function argument name")
+    impl Parse for BareFnArg {
+        fn parse(input: ParseStream) -> Result<Self> {
+            Ok(BareFnArg {
+                name: {
+                    if (input.peek(Ident) || input.peek(Token![_]))
+                        && !input.peek2(Token![::])
+                        && input.peek2(Token![:])
+                    {
+                        let name: BareFnArgName = input.parse()?;
+                        let colon: Token![:] = input.parse()?;
+                        Some((name, colon))
+                    } else {
+                        None
+                    }
+                },
+                ty: input.parse()?,
+            })
         }
     }
 
-    impl Synom for Abi {
-        named!(parse -> Self, do_parse!(
-            extern_: keyword!(extern) >>
-            name: option!(syn!(LitStr)) >>
-            (Abi {
-                extern_token: extern_,
-                name: name,
-            })
-        ));
+    impl Parse for BareFnArgName {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let lookahead = input.lookahead1();
+            if lookahead.peek(Ident) {
+                input.parse().map(BareFnArgName::Named)
+            } else if lookahead.peek(Token![_]) {
+                input.parse().map(BareFnArgName::Wild)
+            } else {
+                Err(lookahead.error())
+            }
+        }
+    }
 
-        fn description() -> Option<&'static str> {
-            Some("`extern` ABI qualifier")
+    impl Parse for Abi {
+        fn parse(input: ParseStream) -> Result<Self> {
+            Ok(Abi {
+                extern_token: input.parse()?,
+                name: input.parse()?,
+            })
+        }
+    }
+
+    impl Parse for Option<Abi> {
+        fn parse(input: ParseStream) -> Result<Self> {
+            if input.peek(Token![extern]) {
+                input.parse().map(Some)
+            } else {
+                Ok(None)
+            }
         }
     }
 }