Implement some atom exprs
diff --git a/src/expr.rs b/src/expr.rs
index 6503ece..1866ca8 100644
--- a/src/expr.rs
+++ b/src/expr.rs
@@ -1029,16 +1029,13 @@
 #[cfg(feature = "parsing")]
 pub mod parsing {
     use super::*;
-    use path::parsing::old_mod_style_path_segment;
+    use path;
     #[cfg(feature = "full")]
     use path::parsing::ty_no_eq_after;
 
     use parse::{Parse, ParseStream, Result};
     #[cfg(feature = "full")]
-    use parse_error;
-    #[cfg(feature = "full")]
-    use proc_macro2::TokenStream;
-    use synom::Synom;
+    use synom::ext::IdentExt;
 
     macro_rules! named2 {
         ($name:ident ($($arg:ident : $argty:ty),*) -> $ret:ty, $($rest:tt)*) => {
@@ -1055,13 +1052,6 @@
         };
     }
 
-    #[cfg(feature = "full")]
-    macro_rules! ambiguous_expr {
-        ($i:expr, $allow_struct:ident) => {
-            shim!($i, ambiguous_expr, $allow_struct, AllowBlock(true))
-        };
-    }
-
     // When we're parsing expressions which occur before blocks, like in an if
     // statement's condition, we cannot parse a struct literal.
     //
@@ -1073,24 +1063,6 @@
     #[derive(Copy, Clone)]
     pub struct AllowBlock(bool);
 
-    // When we are parsing an optional suffix expression, we cannot allow blocks
-    // if structs are not allowed.
-    //
-    // Example:
-    //
-    //     if break {} {}
-    //
-    // is ambiguous between:
-    //
-    //     if (break {}) {}
-    //     if (break) {} {}
-    #[cfg(feature = "full")]
-    macro_rules! opt_ambiguous_expr {
-        ($i:expr, $allow_struct:ident) => {
-            option!($i, shim!(ambiguous_expr, $allow_struct, AllowBlock($allow_struct.0)))
-        };
-    }
-
     impl Parse for Expr {
         fn parse(input: ParseStream) -> Result<Self> {
             ambiguous_expr(input, AllowStruct(true), AllowBlock(true))
@@ -1104,12 +1076,20 @@
 
     // Parse an arbitrary expression.
     #[cfg(feature = "full")]
-    fn ambiguous_expr(input: ParseStream, allow_struct: AllowStruct, allow_block: AllowBlock) -> Result<Expr> {
+    fn ambiguous_expr(
+        input: ParseStream,
+        allow_struct: AllowStruct,
+        allow_block: AllowBlock,
+    ) -> Result<Expr> {
         assign_expr(input, allow_struct, allow_block)
     }
 
     #[cfg(not(feature = "full"))]
-    fn ambiguous_expr(input: ParseStream, allow_struct: AllowStruct, allow_block: AllowBlock) -> Result<Expr> {
+    fn ambiguous_expr(
+        input: ParseStream,
+        allow_struct: AllowStruct,
+        allow_block: AllowBlock,
+    ) -> Result<Expr> {
         // NOTE: We intentionally skip assign_expr, placement_expr, and
         // range_expr as they are only parsed in full mode.
         or_expr(input, allow_struct, allow_block)
@@ -1118,7 +1098,11 @@
     // Parse a left-associative binary operator.
     macro_rules! binop {
         ($name:ident, $next:ident, |$var:ident| $parse_op:expr) => {
-            fn $name(input: ParseStream, allow_struct: AllowStruct, allow_block: AllowBlock) -> Result<Expr> {
+            fn $name(
+                input: ParseStream,
+                allow_struct: AllowStruct,
+                allow_block: AllowBlock,
+            ) -> Result<Expr> {
                 let $var = input;
                 let mut e: Expr = $next(input, allow_struct, allow_block)?;
                 while let Some(op) = $parse_op {
@@ -1131,7 +1115,7 @@
                 }
                 Ok(e)
             }
-        }
+        };
     }
 
     // <placement> = <placement> ..
@@ -1148,7 +1132,11 @@
     //
     // NOTE: This operator is right-associative.
     #[cfg(feature = "full")]
-    fn assign_expr(input: ParseStream, allow_struct: AllowStruct, allow_block: AllowBlock) -> Result<Expr> {
+    fn assign_expr(
+        input: ParseStream,
+        allow_struct: AllowStruct,
+        allow_block: AllowBlock,
+    ) -> Result<Expr> {
         let mut e = placement_expr(input, allow_struct, allow_block)?;
         if input.peek(Token![=]) && !input.peek(Token![==]) && !input.peek(Token![=>]) {
             e = Expr::Assign(ExprAssign {
@@ -1187,7 +1175,11 @@
     //
     // NOTE: This operator is right-associative.
     #[cfg(feature = "full")]
-    fn placement_expr(input: ParseStream, allow_struct: AllowStruct, allow_block: AllowBlock) -> Result<Expr> {
+    fn placement_expr(
+        input: ParseStream,
+        allow_struct: AllowStruct,
+        allow_block: AllowBlock,
+    ) -> Result<Expr> {
         let mut e = range_expr(input, allow_struct, allow_block)?;
         if input.peek(Token![<-]) {
             e = Expr::InPlace(ExprInPlace {
@@ -1212,7 +1204,11 @@
     // NOTE: The form of ranges which don't include a preceding expression are
     // parsed by `atom_expr`, rather than by this function.
     #[cfg(feature = "full")]
-    fn range_expr(input: ParseStream, allow_struct: AllowStruct, allow_block: AllowBlock) -> Result<Expr> {
+    fn range_expr(
+        input: ParseStream,
+        allow_struct: AllowStruct,
+        allow_block: AllowBlock,
+    ) -> Result<Expr> {
         let mut e = or_expr(input, allow_struct, allow_block)?;
         while input.peek(Token![..]) {
             e = Expr::Range(ExprRange {
@@ -1228,9 +1224,12 @@
                         None
                     } else {
                         // We don't want to allow blocks here if we don't allow
-                        // structs. See the reasoning for `opt_ambiguous_expr!`
-                        // above.
-                        Some(Box::new(or_expr(input, allow_struct, AllowBlock(allow_struct.0))?))
+                        // structs.
+                        Some(Box::new(or_expr(
+                            input,
+                            allow_struct,
+                            AllowBlock(allow_struct.0),
+                        )?))
                     }
                 },
             });
@@ -1239,21 +1238,17 @@
     }
 
     // <and> || <and> ...
-    binop!(or_expr, and_expr, |input| {
-        if input.peek(Token![||]) {
-            Some(BinOp::Or(input.parse()?))
-        } else {
-            None
-        }
+    binop!(or_expr, and_expr, |input| if input.peek(Token![||]) {
+        Some(BinOp::Or(input.parse()?))
+    } else {
+        None
     });
 
     // <compare> && <compare> ...
-    binop!(and_expr, compare_expr, |input| {
-        if input.peek(Token![&&]) {
-            Some(BinOp::And(input.parse()?))
-        } else {
-            None
-        }
+    binop!(and_expr, compare_expr, |input| if input.peek(Token![&&]) {
+        Some(BinOp::And(input.parse()?))
+    } else {
+        None
     });
 
     // <bitor> == <bitor> ...
@@ -1354,7 +1349,11 @@
     // <unary> as <ty>
     // <unary> : <ty>
     #[cfg(feature = "full")]
-    fn cast_expr(input: ParseStream, allow_struct: AllowStruct, allow_block: AllowBlock) -> Result<Expr> {
+    fn cast_expr(
+        input: ParseStream,
+        allow_struct: AllowStruct,
+        allow_block: AllowBlock,
+    ) -> Result<Expr> {
         let mut e = unary_expr(input, allow_struct, allow_block)?;
         loop {
             if input.peek(Token![as]) {
@@ -1384,7 +1383,11 @@
 
     // <unary> as <ty>
     #[cfg(not(feature = "full"))]
-    fn cast_expr(input: ParseStream, allow_struct: AllowStruct, allow_block: AllowBlock) -> Result<Expr> {
+    fn cast_expr(
+        input: ParseStream,
+        allow_struct: AllowStruct,
+        allow_block: AllowBlock,
+    ) -> Result<Expr> {
         let mut e = unary_expr(input, allow_struct, allow_block)?;
         while input.peek(Token![as]) {
             e = Expr::Cast(ExprCast {
@@ -1404,7 +1407,11 @@
     // &mut <trailer>
     // box <trailer>
     #[cfg(feature = "full")]
-    fn unary_expr(input: ParseStream, allow_struct: AllowStruct, allow_block: AllowBlock) -> Result<Expr> {
+    fn unary_expr(
+        input: ParseStream,
+        allow_struct: AllowStruct,
+        allow_block: AllowBlock,
+    ) -> Result<Expr> {
         let ahead = input.fork();
         ahead.call(Attribute::parse_outer)?;
         if ahead.peek(Token![&])
@@ -1441,7 +1448,11 @@
 
     // XXX: This duplication is ugly
     #[cfg(not(feature = "full"))]
-    fn unary_expr(input: ParseStream, allow_struct: AllowStruct, allow_block: AllowBlock) -> Result<Expr> {
+    fn unary_expr(
+        input: ParseStream,
+        allow_struct: AllowStruct,
+        allow_block: AllowBlock,
+    ) -> Result<Expr> {
         let ahead = input.fork();
         ahead.call(Attribute::parse_outer)?;
         if ahead.peek(Token![*]) || ahead.peek(Token![!]) || ahead.peek(Token![-]) {
@@ -1476,7 +1487,11 @@
     // <atom> [ <expr> ] ...
     // <atom> ? ...
     #[cfg(feature = "full")]
-    fn trailer_expr(input: ParseStream, allow_struct: AllowStruct, allow_block: AllowBlock) -> Result<Expr> {
+    fn trailer_expr(
+        input: ParseStream,
+        allow_struct: AllowStruct,
+        allow_block: AllowBlock,
+    ) -> Result<Expr> {
         let mut e = atom_expr(input, allow_struct, allow_block)?;
 
         let mut attrs = e.replace_attrs(Vec::new());
@@ -1570,7 +1585,11 @@
 
     // XXX: Duplication == ugly
     #[cfg(not(feature = "full"))]
-    fn trailer_expr(input: ParseStream, allow_struct: AllowStruct, allow_block: AllowBlock) -> Result<Expr> {
+    fn trailer_expr(
+        input: ParseStream,
+        allow_struct: AllowStruct,
+        allow_block: AllowBlock,
+    ) -> Result<Expr> {
         let mut e = atom_expr(input, allow_struct, allow_block)?;
 
         loop {
@@ -1626,11 +1645,11 @@
         |
         syn!(ExprMacro) => { Expr::Macro } // must be before expr_path
         |
-        shim!(expr_break, allow_struct) // must be before expr_path
+        shim!(expr_break, allow_struct) => { Expr::Break } // must be before expr_path
         |
         syn!(ExprContinue) => { Expr::Continue } // must be before expr_path
         |
-        shim!(expr_ret, allow_struct) // must be before expr_path
+        shim!(expr_ret, allow_struct) => { Expr::Return } // must be before expr_path
         |
         syn!(ExprArray) => { Expr::Array }
         |
@@ -1654,12 +1673,12 @@
         |
         syn!(ExprUnsafe) => { Expr::Unsafe }
         |
-        shim!(expr_closure, allow_struct)
+        shim!(expr_closure, allow_struct) => { Expr::Closure }
         |
         cond_reduce!(allow_block.0, syn!(ExprBlock)) => { Expr::Block }
         |
         // NOTE: This is the prefix-form of range
-        shim!(expr_range, allow_struct)
+        shim!(expr_range, allow_struct) => { Expr::Range }
         |
         syn!(ExprPath) => { Expr::Path }
         |
@@ -1707,678 +1726,792 @@
         (nosemi)
     ));
 
-    impl Synom for ExprLit {
+    impl Parse for ExprLit {
         #[cfg(not(feature = "full"))]
-        named!(parse -> Self, do_parse!(
-            lit: syn!(Lit) >>
-            (ExprLit {
+        fn parse(input: ParseStream) -> Result<Self> {
+            Ok(ExprLit {
                 attrs: Vec::new(),
-                lit: lit,
+                lit: input.parse()?,
             })
-        ));
+        }
 
         #[cfg(feature = "full")]
-        named!(parse -> Self, do_parse!(
-            attrs: many0!(Attribute::old_parse_outer) >>
-            lit: syn!(Lit) >>
-            (ExprLit {
-                attrs: attrs,
-                lit: lit,
+        fn parse(input: ParseStream) -> Result<Self> {
+            Ok(ExprLit {
+                attrs: input.call(Attribute::parse_outer)?,
+                lit: input.parse()?,
             })
-        ));
+        }
     }
 
     #[cfg(feature = "full")]
-    impl Synom for ExprMacro {
-        named!(parse -> Self, do_parse!(
-            attrs: many0!(Attribute::old_parse_outer) >>
-            mac: syn!(Macro) >>
-            (ExprMacro {
-                attrs: attrs,
-                mac: mac,
+    impl Parse for ExprMacro {
+        fn parse(input: ParseStream) -> Result<Self> {
+            Ok(ExprMacro {
+                attrs: input.call(Attribute::parse_outer)?,
+                mac: input.parse()?,
             })
-        ));
+        }
     }
 
     #[cfg(feature = "full")]
-    impl Synom for ExprGroup {
-        named!(parse -> Self, do_parse!(
-            e: old_grouped!(syn!(Expr)) >>
-            (ExprGroup {
+    impl Parse for ExprGroup {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let content;
+            Ok(ExprGroup {
                 attrs: Vec::new(),
-                expr: Box::new(e.1),
-                group_token: e.0,
+                group_token: grouped!(content in input),
+                expr: content.parse()?,
             })
-        ));
+        }
     }
 
-    impl Synom for ExprParen {
+    impl Parse for ExprParen {
         #[cfg(not(feature = "full"))]
-        named!(parse -> Self, do_parse!(
-            e: parens!(syn!(Expr)) >>
-            (ExprParen {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let content;
+            Ok(ExprParen {
                 attrs: Vec::new(),
-                paren_token: e.0,
-                expr: Box::new(e.1),
+                paren_token: parenthesized!(content in input),
+                expr: content.parse()?,
             })
-        ));
+        }
 
         #[cfg(feature = "full")]
-        named!(parse -> Self, do_parse!(
-            outer_attrs: many0!(Attribute::old_parse_outer) >>
-            e: parens!(tuple!(
-                many0!(Attribute::old_parse_inner),
-                syn!(Expr),
-            )) >>
-            (ExprParen {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let outer_attrs = input.call(Attribute::parse_outer)?;
+
+            let content;
+            let paren_token = parenthesized!(content in input);
+            let inner_attrs = content.call(Attribute::parse_inner)?;
+            let expr: Expr = content.parse()?;
+
+            Ok(ExprParen {
                 attrs: {
                     let mut attrs = outer_attrs;
-                    attrs.extend((e.1).0);
+                    attrs.extend(inner_attrs);
                     attrs
                 },
-                paren_token: e.0,
-                expr: Box::new((e.1).1),
+                paren_token: paren_token,
+                expr: Box::new(expr),
             })
-        ));
+        }
     }
 
     #[cfg(feature = "full")]
-    impl Synom for ExprArray {
-        named!(parse -> Self, do_parse!(
-            outer_attrs: many0!(Attribute::old_parse_outer) >>
-            elems: brackets!(tuple!(
-                many0!(Attribute::old_parse_inner),
-                call!(Punctuated::parse_terminated),
-            )) >>
-            (ExprArray {
+    impl Parse for ExprArray {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let outer_attrs = input.call(Attribute::parse_outer)?;
+
+            let content;
+            let bracket_token = bracketed!(content in input);
+            let inner_attrs = content.call(Attribute::parse_inner)?;
+            let elems = content.parse_terminated(<Expr as Parse>::parse)?;
+
+            Ok(ExprArray {
                 attrs: {
                     let mut attrs = outer_attrs;
-                    attrs.extend((elems.1).0);
+                    attrs.extend(inner_attrs);
                     attrs
                 },
-                bracket_token: elems.0,
-                elems: (elems.1).1,
+                bracket_token: bracket_token,
+                elems: elems,
             })
-        ));
+        }
     }
 
     #[cfg(feature = "full")]
     impl Parse for GenericMethodArgument {
         // TODO parse const generics as well
         fn parse(input: ParseStream) -> Result<Self> {
-            input.parse_synom(ty_no_eq_after).map(GenericMethodArgument::Type)
+            input
+                .parse_synom(ty_no_eq_after)
+                .map(GenericMethodArgument::Type)
         }
     }
 
     #[cfg(feature = "full")]
-    impl Synom for ExprTuple {
-        named!(parse -> Self, do_parse!(
-            outer_attrs: many0!(Attribute::old_parse_outer) >>
-            elems: parens!(tuple!(
-                many0!(Attribute::old_parse_inner),
-                call!(Punctuated::parse_terminated),
-            )) >>
-            (ExprTuple {
+    impl Parse for ExprTuple {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let outer_attrs = input.call(Attribute::parse_outer)?;
+
+            let content;
+            let paren_token = parenthesized!(content in input);
+            let inner_attrs = content.call(Attribute::parse_inner)?;
+            let elems = content.parse_terminated(<Expr as Parse>::parse)?;
+
+            Ok(ExprTuple {
                 attrs: {
                     let mut attrs = outer_attrs;
-                    attrs.extend((elems.1).0);
+                    attrs.extend(inner_attrs);
                     attrs
                 },
-                elems: (elems.1).1,
-                paren_token: elems.0,
+                paren_token: paren_token,
+                elems: elems,
             })
-        ));
+        }
     }
 
     #[cfg(feature = "full")]
-    impl Synom for ExprIfLet {
-        named!(parse -> Self, do_parse!(
-            if_: keyword!(if) >>
-            let_: keyword!(let) >>
-            pats: call!(Punctuated::parse_separated_nonempty) >>
-            eq: punct!(=) >>
-            cond: shim!(expr_no_struct) >>
-            then_block: braces!(Block::old_parse_within) >>
-            else_block: option!(shim!(else_block)) >>
-            (ExprIfLet {
+    impl Parse for ExprIfLet {
+        fn parse(input: ParseStream) -> Result<Self> {
+            Ok(ExprIfLet {
                 attrs: Vec::new(),
-                pats: pats,
-                let_token: let_,
-                eq_token: eq,
-                expr: Box::new(cond),
-                then_branch: Block {
-                    brace_token: then_block.0,
-                    stmts: then_block.1,
+                if_token: input.parse()?,
+                let_token: input.parse()?,
+                pats: {
+                    let mut pats = Punctuated::new();
+                    let value: Pat = input.parse()?;
+                    pats.push_value(value);
+                    while input.peek(Token![|])
+                        && !input.peek(Token![||])
+                        && !input.peek(Token![|=])
+                    {
+                        let punct = input.parse()?;
+                        pats.push_punct(punct);
+                        let value: Pat = input.parse()?;
+                        pats.push_value(value);
+                    }
+                    pats
                 },
-                if_token: if_,
-                else_branch: else_block,
+                eq_token: input.parse()?,
+                expr: Box::new(input.call(expr_no_struct)?),
+                then_branch: input.parse()?,
+                else_branch: {
+                    if input.peek(Token![else]) {
+                        Some(input.call(else_block)?)
+                    } else {
+                        None
+                    }
+                },
             })
-        ));
+        }
     }
 
     #[cfg(feature = "full")]
-    impl Synom for ExprIf {
-        named!(parse -> Self, do_parse!(
-            if_: keyword!(if) >>
-            cond: shim!(expr_no_struct) >>
-            then_block: braces!(Block::old_parse_within) >>
-            else_block: option!(shim!(else_block)) >>
-            (ExprIf {
+    impl Parse for ExprIf {
+        fn parse(input: ParseStream) -> Result<Self> {
+            Ok(ExprIf {
                 attrs: Vec::new(),
-                cond: Box::new(cond),
-                then_branch: Block {
-                    brace_token: then_block.0,
-                    stmts: then_block.1,
+                if_token: input.parse()?,
+                cond: Box::new(input.call(expr_no_struct)?),
+                then_branch: input.parse()?,
+                else_branch: {
+                    if input.peek(Token![else]) {
+                        Some(input.call(else_block)?)
+                    } else {
+                        None
+                    }
                 },
-                if_token: if_,
-                else_branch: else_block,
             })
-        ));
+        }
     }
 
     #[cfg(feature = "full")]
-    named2!(else_block -> (Token![else], Box<Expr>), do_parse!(
-        else_: keyword!(else) >>
-        expr: alt!(
-            syn!(ExprIf) => { Expr::If }
-            |
-            syn!(ExprIfLet) => { Expr::IfLet }
-            |
-            do_parse!(
-                else_block: braces!(Block::old_parse_within) >>
-                (Expr::Block(ExprBlock {
-                    attrs: Vec::new(),
-                    label: None,
-                    block: Block {
-                        brace_token: else_block.0,
-                        stmts: else_block.1,
-                    },
-                }))
-            )
-        ) >>
-        (else_, Box::new(expr))
-    ));
+    fn else_block(input: ParseStream) -> Result<(Token![else], Box<Expr>)> {
+        let else_token: Token![else] = input.parse()?;
+
+        let lookahead = input.lookahead1();
+        let else_branch = if input.peek(Token![if]) {
+            if input.peek2(Token![let]) {
+                input.parse().map(Expr::IfLet)?
+            } else {
+                input.parse().map(Expr::If)?
+            }
+        } else if input.peek(token::Brace) {
+            Expr::Block(ExprBlock {
+                attrs: Vec::new(),
+                label: None,
+                block: input.parse()?,
+            })
+        } else {
+            return Err(lookahead.error());
+        };
+
+        Ok((else_token, Box::new(else_branch)))
+    }
 
     #[cfg(feature = "full")]
-    impl Synom for ExprForLoop {
-        named!(parse -> Self, do_parse!(
-            outer_attrs: many0!(Attribute::old_parse_outer) >>
-            label: option!(syn!(Label)) >>
-            for_: keyword!(for) >>
-            pat: syn!(Pat) >>
-            in_: keyword!(in) >>
-            expr: shim!(expr_no_struct) >>
-            block: braces!(tuple!(
-                many0!(Attribute::old_parse_inner),
-                shim!(Block::parse_within),
-            )) >>
-            (ExprForLoop {
+    impl Parse for ExprForLoop {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let outer_attrs = input.call(Attribute::parse_outer)?;
+            let label: Option<Label> = input.parse()?;
+            let for_token: Token![for] = input.parse()?;
+            let pat: Pat = input.parse()?;
+            let in_token: Token![in] = input.parse()?;
+            let expr: Expr = input.call(expr_no_struct)?;
+
+            let content;
+            let brace_token = braced!(content in input);
+            let inner_attrs = content.call(Attribute::parse_inner)?;
+            let stmts = content.call(Block::parse_within)?;
+
+            Ok(ExprForLoop {
                 attrs: {
                     let mut attrs = outer_attrs;
-                    attrs.extend((block.1).0);
+                    attrs.extend(inner_attrs);
                     attrs
                 },
                 label: label,
-                for_token: for_,
+                for_token: for_token,
                 pat: Box::new(pat),
-                in_token: in_,
+                in_token: in_token,
                 expr: Box::new(expr),
                 body: Block {
-                    brace_token: block.0,
-                    stmts: (block.1).1,
+                    brace_token: brace_token,
+                    stmts: stmts,
                 },
             })
-        ));
+        }
     }
 
     #[cfg(feature = "full")]
-    impl Synom for ExprLoop {
-        named!(parse -> Self, do_parse!(
-            outer_attrs: many0!(Attribute::old_parse_outer) >>
-            label: option!(syn!(Label)) >>
-            loop_: keyword!(loop) >>
-            block: braces!(tuple!(
-                many0!(Attribute::old_parse_inner),
-                shim!(Block::parse_within),
-            )) >>
-            (ExprLoop {
+    impl Parse for ExprLoop {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let outer_attrs = input.call(Attribute::parse_outer)?;
+            let label: Option<Label> = input.parse()?;
+            let loop_token: Token![loop] = input.parse()?;
+
+            let content;
+            let brace_token = braced!(content in input);
+            let inner_attrs = content.call(Attribute::parse_inner)?;
+            let stmts = content.call(Block::parse_within)?;
+
+            Ok(ExprLoop {
                 attrs: {
                     let mut attrs = outer_attrs;
-                    attrs.extend((block.1).0);
+                    attrs.extend(inner_attrs);
                     attrs
                 },
                 label: label,
-                loop_token: loop_,
+                loop_token: loop_token,
                 body: Block {
-                    brace_token: block.0,
-                    stmts: (block.1).1,
+                    brace_token: brace_token,
+                    stmts: stmts,
                 },
             })
-        ));
+        }
     }
 
     #[cfg(feature = "full")]
-    impl Synom for ExprMatch {
-        named!(parse -> Self, do_parse!(
-            outer_attrs: many0!(Attribute::old_parse_outer) >>
-            match_: keyword!(match) >>
-            obj: shim!(expr_no_struct) >>
-            braced_content: braces!(tuple!(
-                many0!(Attribute::old_parse_inner),
-                many0!(syn!(Arm)),
-            )) >>
-            (ExprMatch {
+    impl Parse for ExprMatch {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let outer_attrs = input.call(Attribute::parse_outer)?;
+            let match_token: Token![match] = input.parse()?;
+            let expr = expr_no_struct(input)?;
+
+            let content;
+            let brace_token = braced!(content in input);
+            let inner_attrs = content.call(Attribute::parse_inner)?;
+
+            let mut arms = Vec::new();
+            while !content.is_empty() {
+                arms.push(content.parse()?);
+            }
+
+            Ok(ExprMatch {
                 attrs: {
                     let mut attrs = outer_attrs;
-                    attrs.extend((braced_content.1).0);
+                    attrs.extend(inner_attrs);
                     attrs
                 },
-                expr: Box::new(obj),
-                match_token: match_,
-                brace_token: braced_content.0,
-                arms: (braced_content.1).1,
+                match_token: match_token,
+                expr: Box::new(expr),
+                brace_token: brace_token,
+                arms: arms,
             })
-        ));
+        }
     }
 
     #[cfg(feature = "full")]
-    impl Synom for ExprTryBlock {
-        named!(parse -> Self, do_parse!(
-            try_token: keyword!(try) >>
-            block: syn!(Block) >>
-            (ExprTryBlock {
+    impl Parse for ExprTryBlock {
+        fn parse(input: ParseStream) -> Result<Self> {
+            Ok(ExprTryBlock {
                 attrs: Vec::new(),
-                try_token: try_token,
-                block: block,
+                try_token: input.parse()?,
+                block: input.parse()?,
             })
-        ));
+        }
     }
 
     #[cfg(feature = "full")]
-    impl Synom for ExprYield {
-        named!(parse -> Self, do_parse!(
-            yield_: keyword!(yield) >>
-            expr: option!(syn!(Expr)) >>
-            (ExprYield {
+    impl Parse for ExprYield {
+        fn parse(input: ParseStream) -> Result<Self> {
+            Ok(ExprYield {
                 attrs: Vec::new(),
-                yield_token: yield_,
-                expr: expr.map(Box::new),
+                yield_token: input.parse()?,
+                expr: {
+                    if !input.is_empty() && !input.peek(Token![,]) && !input.peek(Token![;]) {
+                        Some(input.parse()?)
+                    } else {
+                        None
+                    }
+                },
             })
-        ));
+        }
     }
 
     #[cfg(feature = "full")]
-    impl Synom for Arm {
-        named!(parse -> Self, do_parse!(
-            attrs: many0!(Attribute::old_parse_outer) >>
-            leading_vert: option!(punct!(|)) >>
-            pats: call!(Punctuated::parse_separated_nonempty) >>
-            guard: option!(tuple!(keyword!(if), syn!(Expr))) >>
-            fat_arrow: punct!(=>) >>
-            body: do_parse!(
-                expr: alt!(shim!(expr_nosemi) | syn!(Expr)) >>
-                comma: switch!(value!(arm_expr_requires_comma(&expr)),
-                    true => alt!(
-                        input_end!() => { |_| None }
-                        |
-                        punct!(,) => { Some }
-                    )
-                    |
-                    false => option!(punct!(,))
-                ) >>
-                (expr, comma)
-            ) >>
-            (Arm {
-                fat_arrow_token: fat_arrow,
-                attrs: attrs,
-                leading_vert: leading_vert,
-                pats: pats,
-                guard: guard.map(|(if_, guard)| (if_, Box::new(guard))),
-                body: Box::new(body.0),
-                comma: body.1,
+    impl Parse for Arm {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let requires_comma;
+            Ok(Arm {
+                attrs: input.call(Attribute::parse_outer)?,
+                leading_vert: input.parse()?,
+                pats: {
+                    let mut pats = Punctuated::new();
+                    let value: Pat = input.parse()?;
+                    pats.push_value(value);
+                    loop {
+                        if !input.peek(Token![|]) {
+                            break;
+                        }
+                        let punct = input.parse()?;
+                        pats.push_punct(punct);
+                        let value: Pat = input.parse()?;
+                        pats.push_value(value);
+                    }
+                    pats
+                },
+                guard: {
+                    if input.peek(Token![if]) {
+                        let if_token: Token![if] = input.parse()?;
+                        let guard: Expr = input.parse()?;
+                        Some((if_token, Box::new(guard)))
+                    } else {
+                        None
+                    }
+                },
+                fat_arrow_token: input.parse()?,
+                body: {
+                    let body = if input.fork().call(expr_nosemi).is_ok() {
+                        input.call(expr_nosemi)?
+                    } else {
+                        input.parse()?
+                    };
+                    requires_comma = arm_expr_requires_comma(&body);
+                    Box::new(body)
+                },
+                comma: {
+                    if requires_comma && !input.is_empty() {
+                        Some(input.parse()?)
+                    } else {
+                        input.parse()?
+                    }
+                },
             })
-        ));
+        }
     }
 
     #[cfg(feature = "full")]
-    named2!(expr_closure(allow_struct: AllowStruct) -> Expr, do_parse!(
-        attrs: many0!(Attribute::old_parse_outer) >>
-        asyncness: option!(keyword!(async)) >>
-        movability: option!(cond_reduce!(asyncness.is_none(), keyword!(static))) >>
-        capture: option!(keyword!(move)) >>
-        or1: punct!(|) >>
-        inputs: call!(Punctuated::parse_terminated_with, fn_arg) >>
-        or2: punct!(|) >>
-        ret_and_body: alt!(
-            do_parse!(
-                arrow: punct!(->) >>
-                ty: syn!(Type) >>
-                body: syn!(Block) >>
-                (
-                    ReturnType::Type(arrow, Box::new(ty)),
-                    Expr::Block(ExprBlock {
-                        attrs: Vec::new(),
-                        label: None,
-                        block: body,
-                    },
-                ))
-            )
-            |
-            map!(ambiguous_expr!(allow_struct), |e| (ReturnType::Default, e))
-        ) >>
-        (Expr::Closure(ExprClosure {
+    fn expr_closure(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprClosure> {
+        let attrs = input.call(Attribute::parse_outer)?;
+        let asyncness: Option<Token![async]> = input.parse()?;
+        let movability: Option<Token![static]> = if asyncness.is_none() {
+            input.parse()?
+        } else {
+            None
+        };
+        let capture: Option<Token![move]> = input.parse()?;
+        let or1_token: Token![|] = input.parse()?;
+
+        let mut inputs = Punctuated::new();
+        loop {
+            if input.peek(Token![|]) {
+                break;
+            }
+            let value = fn_arg(input)?;
+            inputs.push_value(value);
+            if input.peek(Token![|]) {
+                break;
+            }
+            let punct: Token![,] = input.parse()?;
+            inputs.push_punct(punct);
+        }
+
+        let or2_token: Token![|] = input.parse()?;
+
+        let (output, body) = if input.peek(Token![->]) {
+            let arrow_token: Token![->] = input.parse()?;
+            let ty: Type = input.parse()?;
+            let body: Block = input.parse()?;
+            let output = ReturnType::Type(arrow_token, Box::new(ty));
+            let block = Expr::Block(ExprBlock {
+                attrs: Vec::new(),
+                label: None,
+                block: body,
+            });
+            (output, block)
+        } else {
+            let body = ambiguous_expr(input, allow_struct, AllowBlock(true))?;
+            (ReturnType::Default, body)
+        };
+
+        Ok(ExprClosure {
             attrs: attrs,
             asyncness: asyncness,
             movability: movability,
             capture: capture,
-            or1_token: or1,
+            or1_token: or1_token,
             inputs: inputs,
-            or2_token: or2,
-            output: ret_and_body.0,
-            body: Box::new(ret_and_body.1),
-        }))
-    ));
-
-    #[cfg(feature = "full")]
-    impl Synom for ExprAsync {
-        named!(parse -> Self, do_parse!(
-            attrs: many0!(Attribute::old_parse_outer) >>
-            async_token: keyword!(async) >>
-            capture: option!(keyword!(move)) >>
-            block: syn!(Block) >>
-            (ExprAsync {
-                attrs: attrs,
-                async_token: async_token,
-                capture: capture,
-                block: block,
-            })
-        ));
+            or2_token: or2_token,
+            output: output,
+            body: Box::new(body),
+        })
     }
 
     #[cfg(feature = "full")]
-    named!(fn_arg -> FnArg, do_parse!(
-        pat: syn!(Pat) >>
-        ty: option!(tuple!(punct!(:), syn!(Type))) >>
-        ({
-            if let Some((colon, ty)) = ty {
-                FnArg::Captured(ArgCaptured {
-                    pat: pat,
-                    colon_token: colon,
-                    ty: ty,
-                })
-            } else {
-                FnArg::Inferred(pat)
-            }
-        })
-    ));
+    impl Parse for ExprAsync {
+        fn parse(input: ParseStream) -> Result<Self> {
+            Ok(ExprAsync {
+                attrs: input.call(Attribute::parse_outer)?,
+                async_token: input.parse()?,
+                capture: input.parse()?,
+                block: input.parse()?,
+            })
+        }
+    }
 
     #[cfg(feature = "full")]
-    impl Synom for ExprWhile {
-        named!(parse -> Self, do_parse!(
-            outer_attrs: many0!(Attribute::old_parse_outer) >>
-            label: option!(syn!(Label)) >>
-            while_: keyword!(while) >>
-            cond: shim!(expr_no_struct) >>
-            block: braces!(tuple!(
-                many0!(Attribute::old_parse_inner),
-                shim!(Block::parse_within),
-            )) >>
-            (ExprWhile {
+    fn fn_arg(input: ParseStream) -> Result<FnArg> {
+        let pat: Pat = input.parse()?;
+
+        if input.peek(Token![:]) {
+            Ok(FnArg::Captured(ArgCaptured {
+                pat: pat,
+                colon_token: input.parse()?,
+                ty: input.parse()?,
+            }))
+        } else {
+            Ok(FnArg::Inferred(pat))
+        }
+    }
+
+    #[cfg(feature = "full")]
+    impl Parse for ExprWhile {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let outer_attrs = input.call(Attribute::parse_outer)?;
+            let label: Option<Label> = input.parse()?;
+            let while_token: Token![while] = input.parse()?;
+            let cond = expr_no_struct(input)?;
+
+            let content;
+            let brace_token = braced!(content in input);
+            let inner_attrs = content.call(Attribute::parse_inner)?;
+            let stmts = content.call(Block::parse_within)?;
+
+            Ok(ExprWhile {
                 attrs: {
                     let mut attrs = outer_attrs;
-                    attrs.extend((block.1).0);
+                    attrs.extend(inner_attrs);
                     attrs
                 },
                 label: label,
-                while_token: while_,
+                while_token: while_token,
                 cond: Box::new(cond),
                 body: Block {
-                    brace_token: block.0,
-                    stmts: (block.1).1,
+                    brace_token: brace_token,
+                    stmts: stmts,
                 },
             })
-        ));
+        }
     }
 
     #[cfg(feature = "full")]
-    impl Synom for ExprWhileLet {
-        named!(parse -> Self, do_parse!(
-            outer_attrs: many0!(Attribute::old_parse_outer) >>
-            label: option!(syn!(Label)) >>
-            while_: keyword!(while) >>
-            let_: keyword!(let) >>
-            pats: call!(Punctuated::parse_separated_nonempty) >>
-            eq: punct!(=) >>
-            value: shim!(expr_no_struct) >>
-            block: braces!(tuple!(
-                many0!(Attribute::old_parse_inner),
-                shim!(Block::parse_within),
-            )) >>
-            (ExprWhileLet {
+    impl Parse for ExprWhileLet {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let outer_attrs = input.call(Attribute::parse_outer)?;
+            let label: Option<Label> = input.parse()?;
+            let while_token: Token![while] = input.parse()?;
+            let let_token: Token![let] = input.parse()?;
+
+            let mut pats = Punctuated::new();
+            let value: Pat = input.parse()?;
+            pats.push_value(value);
+            while input.peek(Token![|]) && !input.peek(Token![||]) && !input.peek(Token![|=]) {
+                let punct = input.parse()?;
+                pats.push_punct(punct);
+                let value: Pat = input.parse()?;
+                pats.push_value(value);
+            }
+
+            let eq_token: Token![=] = input.parse()?;
+            let expr = expr_no_struct(input)?;
+
+            let content;
+            let brace_token = braced!(content in input);
+            let inner_attrs = content.call(Attribute::parse_inner)?;
+            let stmts = content.call(Block::parse_within)?;
+
+            Ok(ExprWhileLet {
                 attrs: {
                     let mut attrs = outer_attrs;
-                    attrs.extend((block.1).0);
+                    attrs.extend(inner_attrs);
                     attrs
                 },
                 label: label,
-                while_token: while_,
-                let_token: let_,
+                while_token: while_token,
+                let_token: let_token,
                 pats: pats,
-                eq_token: eq,
-                expr: Box::new(value),
+                eq_token: eq_token,
+                expr: Box::new(expr),
                 body: Block {
-                    brace_token: block.0,
-                    stmts: (block.1).1,
+                    brace_token: brace_token,
+                    stmts: stmts,
                 },
             })
-        ));
+        }
     }
 
     #[cfg(feature = "full")]
-    impl Synom for Label {
-        named!(parse -> Self, do_parse!(
-            name: syn!(Lifetime) >>
-            colon: punct!(:) >>
-            (Label {
-                name: name,
-                colon_token: colon,
+    impl Parse for Label {
+        fn parse(input: ParseStream) -> Result<Self> {
+            Ok(Label {
+                name: input.parse()?,
+                colon_token: input.parse()?,
             })
-        ));
+        }
     }
 
     #[cfg(feature = "full")]
-    impl Synom for ExprContinue {
-        named!(parse -> Self, do_parse!(
-            attrs: many0!(Attribute::old_parse_outer) >>
-            cont: keyword!(continue) >>
-            label: option!(syn!(Lifetime)) >>
-            (ExprContinue {
-                attrs: attrs,
-                continue_token: cont,
-                label: label,
+    impl Parse for Option<Label> {
+        fn parse(input: ParseStream) -> Result<Self> {
+            if input.peek(Lifetime) {
+                input.parse().map(Some)
+            } else {
+                Ok(None)
+            }
+        }
+    }
+
+    #[cfg(feature = "full")]
+    impl Parse for ExprContinue {
+        fn parse(input: ParseStream) -> Result<Self> {
+            Ok(ExprContinue {
+                attrs: input.call(Attribute::parse_outer)?,
+                continue_token: input.parse()?,
+                label: input.parse()?,
             })
-        ));
+        }
     }
 
     #[cfg(feature = "full")]
-    named2!(expr_break(allow_struct: AllowStruct) -> Expr, do_parse!(
-        attrs: many0!(Attribute::old_parse_outer) >>
-        break_: keyword!(break) >>
-        label: option!(syn!(Lifetime)) >>
-        // We can't allow blocks after a `break` expression when we wouldn't
-        // allow structs, as this expression is ambiguous.
-        val: opt_ambiguous_expr!(allow_struct) >>
-        (ExprBreak {
-            attrs: attrs,
-            label: label,
-            expr: val.map(Box::new),
-            break_token: break_,
-        }.into())
-    ));
-
-    #[cfg(feature = "full")]
-    named2!(expr_ret(allow_struct: AllowStruct) -> Expr, do_parse!(
-        attrs: many0!(Attribute::old_parse_outer) >>
-        return_: keyword!(return) >>
-        // NOTE: return is greedy and eats blocks after it even when in a
-        // position where structs are not allowed, such as in if statement
-        // conditions. For example:
-        //
-        // if return { println!("A") } {} // Prints "A"
-        ret_value: option!(ambiguous_expr!(allow_struct)) >>
-        (ExprReturn {
-            attrs: attrs,
-            expr: ret_value.map(Box::new),
-            return_token: return_,
-        }.into())
-    ));
-
-    #[cfg(feature = "full")]
-    impl Synom for ExprStruct {
-        named!(parse -> Self, do_parse!(
-            outer_attrs: many0!(Attribute::old_parse_outer) >>
-            path: syn!(Path) >>
-            data: braces!(do_parse!(
-                inner_attrs: many0!(Attribute::old_parse_inner) >>
-                fields: call!(Punctuated::parse_terminated) >>
-                base: option!(cond!(fields.empty_or_trailing(), do_parse!(
-                    dots: punct!(..) >>
-                    base: syn!(Expr) >>
-                    (dots, base)
-                ))) >>
-                (inner_attrs, fields, base)
-            )) >>
-            ({
-                let (brace, (inner_attrs, fields, base)) = data;
-                let (dots, rest) = match base.and_then(|b| b) {
-                    Some((dots, base)) => (Some(dots), Some(base)),
-                    None => (None, None),
-                };
-                ExprStruct {
-                    attrs: {
-                        let mut attrs = outer_attrs;
-                        attrs.extend(inner_attrs);
-                        attrs
-                    },
-                    brace_token: brace,
-                    path: path,
-                    fields: fields,
-                    dot2_token: dots,
-                    rest: rest.map(Box::new),
+    fn expr_break(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprBreak> {
+        Ok(ExprBreak {
+            attrs: input.call(Attribute::parse_outer)?,
+            break_token: input.parse()?,
+            label: input.parse()?,
+            expr: {
+                if input.is_empty()
+                    || input.peek(Token![,])
+                    || input.peek(Token![;])
+                    || !allow_struct.0 && input.peek(token::Brace)
+                {
+                    None
+                } else {
+                    // We can't allow blocks after a `break` expression when we
+                    // wouldn't allow structs, as this expression is ambiguous.
+                    let allow_block = AllowBlock(allow_struct.0);
+                    let expr = ambiguous_expr(input, allow_struct, allow_block)?;
+                    Some(Box::new(expr))
                 }
-            })
-        ));
+            },
+        })
     }
 
     #[cfg(feature = "full")]
-    impl Synom for FieldValue {
-        named!(parse -> Self, do_parse!(
-            attrs: many0!(Attribute::old_parse_outer) >>
-            field_value: alt!(
-                tuple!(syn!(Member), map!(punct!(:), Some), syn!(Expr))
-                |
-                map!(syn!(Ident), |name| (
-                    Member::Named(name.clone()),
-                    None,
-                    Expr::Path(ExprPath {
+    fn expr_ret(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprReturn> {
+        Ok(ExprReturn {
+            attrs: input.call(Attribute::parse_outer)?,
+            return_token: input.parse()?,
+            expr: {
+                if input.is_empty() || input.peek(Token![,]) || input.peek(Token![;]) {
+                    None
+                } else {
+                    // NOTE: return is greedy and eats blocks after it even when in a
+                    // position where structs are not allowed, such as in if statement
+                    // conditions. For example:
+                    //
+                    // if return { println!("A") } {} // Prints "A"
+                    let expr = ambiguous_expr(input, allow_struct, AllowBlock(true))?;
+                    Some(Box::new(expr))
+                }
+            },
+        })
+    }
+
+    #[cfg(feature = "full")]
+    impl Parse for ExprStruct {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let outer_attrs = input.call(Attribute::parse_outer)?;
+            let path: Path = input.parse()?;
+
+            let content;
+            let brace_token = braced!(content in input);
+            let inner_attrs = content.call(Attribute::parse_inner)?;
+
+            let mut fields = Punctuated::new();
+            loop {
+                let attrs = content.call(Attribute::parse_outer)?;
+                if content.fork().parse::<Member>().is_err() {
+                    if attrs.is_empty() {
+                        break;
+                    } else {
+                        return Err(content.error("expected struct field"));
+                    }
+                }
+
+                let member: Member = content.parse()?;
+                let (colon_token, value) = if content.peek(Token![:]) || !member.is_named() {
+                    let colon_token: Token![:] = content.parse()?;
+                    let value: Expr = content.parse()?;
+                    (Some(colon_token), value)
+                } else if let Member::Named(ref ident) = member {
+                    let value = Expr::Path(ExprPath {
                         attrs: Vec::new(),
                         qself: None,
-                        path: name.into(),
-                    }),
-                ))
-            ) >>
-            (FieldValue {
-                attrs: attrs,
-                member: field_value.0,
-                colon_token: field_value.1,
-                expr: field_value.2,
+                        path: Path::from(ident.clone()),
+                    });
+                    (None, value)
+                } else {
+                    unreachable!()
+                };
+
+                fields.push(FieldValue {
+                    attrs: attrs,
+                    member: member,
+                    colon_token: colon_token,
+                    expr: value,
+                });
+
+                if !content.peek(Token![,]) {
+                    break;
+                }
+                let punct: Token![,] = content.parse()?;
+                fields.push_punct(punct);
+            }
+
+            let (dot2_token, rest) = if fields.empty_or_trailing() && content.peek(Token![..]) {
+                let dot2_token: Token![..] = content.parse()?;
+                let rest: Expr = content.parse()?;
+                (Some(dot2_token), Some(Box::new(rest)))
+            } else {
+                (None, None)
+            };
+
+            Ok(ExprStruct {
+                attrs: {
+                    let mut attrs = outer_attrs;
+                    attrs.extend(inner_attrs);
+                    attrs
+                },
+                brace_token: brace_token,
+                path: path,
+                fields: fields,
+                dot2_token: dot2_token,
+                rest: rest,
             })
-        ));
+        }
     }
 
     #[cfg(feature = "full")]
-    impl Synom for ExprRepeat {
-        named!(parse -> Self, do_parse!(
-            outer_attrs: many0!(Attribute::old_parse_outer) >>
-            data: brackets!(tuple!(
-                many0!(Attribute::old_parse_inner),
-                syn!(Expr),
-                punct!(;),
-                syn!(Expr),
-            )) >>
-            (ExprRepeat {
+    impl Parse for ExprRepeat {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let outer_attrs = input.call(Attribute::parse_outer)?;
+
+            let content;
+            let bracket_token = bracketed!(content in input);
+            let inner_attrs = content.call(Attribute::parse_inner)?;
+            let expr: Expr = content.parse()?;
+            let semi_token: Token![;] = content.parse()?;
+            let len: Expr = content.parse()?;
+
+            Ok(ExprRepeat {
                 attrs: {
                     let mut attrs = outer_attrs;
-                    attrs.extend((data.1).0);
+                    attrs.extend(inner_attrs);
                     attrs
                 },
-                expr: Box::new((data.1).1),
-                len: Box::new((data.1).3),
-                bracket_token: data.0,
-                semi_token: (data.1).2,
+                bracket_token: bracket_token,
+                expr: Box::new(expr),
+                semi_token: semi_token,
+                len: Box::new(len),
             })
-        ));
+        }
     }
 
     #[cfg(feature = "full")]
-    impl Synom for ExprUnsafe {
-        named!(parse -> Self, do_parse!(
-            outer_attrs: many0!(Attribute::old_parse_outer) >>
-            unsafe_: keyword!(unsafe) >>
-            block: braces!(tuple!(
-                many0!(Attribute::old_parse_inner),
-                shim!(Block::parse_within),
-            )) >>
-            (ExprUnsafe {
+    impl Parse for ExprUnsafe {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let outer_attrs = input.call(Attribute::parse_outer)?;
+            let unsafe_token: Token![unsafe] = input.parse()?;
+
+            let content;
+            let brace_token = braced!(content in input);
+            let inner_attrs = content.call(Attribute::parse_inner)?;
+            let stmts = content.call(Block::parse_within)?;
+
+            Ok(ExprUnsafe {
                 attrs: {
                     let mut attrs = outer_attrs;
-                    attrs.extend((block.1).0);
+                    attrs.extend(inner_attrs);
                     attrs
                 },
-                unsafe_token: unsafe_,
+                unsafe_token: unsafe_token,
                 block: Block {
-                    brace_token: block.0,
-                    stmts: (block.1).1,
+                    brace_token: brace_token,
+                    stmts: stmts,
                 },
             })
-        ));
+        }
     }
 
     #[cfg(feature = "full")]
-    impl Synom for ExprBlock {
-        named!(parse -> Self, do_parse!(
-            outer_attrs: many0!(Attribute::old_parse_outer) >>
-            label: option!(syn!(Label)) >>
-            block: braces!(tuple!(
-                many0!(Attribute::old_parse_inner),
-                shim!(Block::parse_within),
-            )) >>
-            (ExprBlock {
+    impl Parse for ExprBlock {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let outer_attrs = input.call(Attribute::parse_outer)?;
+            let label: Option<Label> = input.parse()?;
+
+            let content;
+            let brace_token = braced!(content in input);
+            let inner_attrs = content.call(Attribute::parse_inner)?;
+            let stmts = content.call(Block::parse_within)?;
+
+            Ok(ExprBlock {
                 attrs: {
                     let mut attrs = outer_attrs;
-                    attrs.extend((block.1).0);
+                    attrs.extend(inner_attrs);
                     attrs
                 },
                 label: label,
                 block: Block {
-                    brace_token: block.0,
-                    stmts: (block.1).1,
+                    brace_token: brace_token,
+                    stmts: stmts,
                 },
             })
-        ));
+        }
     }
 
     #[cfg(feature = "full")]
-    named2!(expr_range(allow_struct: AllowStruct) -> Expr, do_parse!(
-        limits: syn!(RangeLimits) >>
-        hi: opt_ambiguous_expr!(allow_struct) >>
-        (ExprRange {
+    fn expr_range(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprRange> {
+        Ok(ExprRange {
             attrs: Vec::new(),
             from: None,
-            to: hi.map(Box::new),
-            limits: limits,
-        }.into())
-    ));
+            limits: input.parse()?,
+            to: {
+                if input.is_empty()
+                    || input.peek(Token![,])
+                    || input.peek(Token![;])
+                    || !allow_struct.0 && input.peek(token::Brace)
+                {
+                    None
+                } else {
+                    let to = ambiguous_expr(input, allow_struct, AllowBlock(allow_struct.0))?;
+                    Some(Box::new(to))
+                }
+            },
+        })
+    }
 
     #[cfg(feature = "full")]
     impl Parse for RangeLimits {
@@ -2397,107 +2530,32 @@
         }
     }
 
-    impl Synom for ExprPath {
-        #[cfg(not(feature = "full"))]
-        named!(parse -> Self, do_parse!(
-            pair: shim!(qpath) >>
-            (ExprPath {
-                attrs: Vec::new(),
-                qself: pair.0,
-                path: pair.1,
-            })
-        ));
+    impl Parse for ExprPath {
+        fn parse(input: ParseStream) -> Result<Self> {
+            #[cfg(not(feature = "full"))]
+            let attrs = Vec::new();
+            #[cfg(feature = "full")]
+            let attrs = input.call(Attribute::parse_outer)?;
 
-        #[cfg(feature = "full")]
-        named!(parse -> Self, do_parse!(
-            attrs: many0!(Attribute::old_parse_outer) >>
-            pair: shim!(qpath) >>
-            (ExprPath {
+            let (qself, path) = path::parsing::qpath(input, true)?;
+
+            Ok(ExprPath {
                 attrs: attrs,
-                qself: pair.0,
-                path: pair.1,
+                qself: qself,
+                path: path,
             })
-        ));
+        }
     }
 
-    named2!(path -> Path, do_parse!(
-        colon: option!(punct!(::)) >>
-        segments: call!(Punctuated::<_, Token![::]>::parse_separated_nonempty_with, path_segment) >>
-        cond_reduce!(segments.first().map_or(true, |seg| seg.value().ident != "dyn")) >>
-        (Path {
-            leading_colon: colon,
-            segments: segments,
-        })
-    ));
-
-    named!(path_segment -> PathSegment, alt!(
-        do_parse!(
-            ident: syn!(Ident) >>
-            colon2: punct!(::) >>
-            lt: punct!(<) >>
-            args: call!(Punctuated::parse_terminated) >>
-            gt: punct!(>) >>
-            (PathSegment {
-                ident: ident,
-                arguments: PathArguments::AngleBracketed(AngleBracketedGenericArguments {
-                    colon2_token: Some(colon2),
-                    lt_token: lt,
-                    args: args,
-                    gt_token: gt,
-                }),
-            })
-        )
-        |
-        old_mod_style_path_segment
-    ));
-
-    named2!(qpath -> (Option<QSelf>, Path), alt!(
-        map!(shim!(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_with, path_segment) >>
-            ({
-                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()))
-    ));
-
     #[cfg(feature = "full")]
-    impl Synom for Block {
-        named!(parse -> Self, do_parse!(
-            stmts: braces!(Block::old_parse_within) >>
-            (Block {
-                brace_token: stmts.0,
-                stmts: stmts.1,
+    impl Parse for Block {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let content;
+            Ok(Block {
+                brace_token: braced!(content in input),
+                stmts: content.call(Block::parse_within)?,
             })
-        ));
+        }
     }
 
     #[cfg(feature = "full")]
@@ -2532,234 +2590,321 @@
     }
 
     #[cfg(feature = "full")]
-    impl Synom for Stmt {
-        named!(parse -> Self, alt!(
-            shim!(stmt_mac)
-            |
-            shim!(stmt_local)
-            |
-            shim!(stmt_item)
-            |
-            shim!(stmt_blockexpr)
-            |
-            shim!(stmt_expr)
-        ));
-    }
+    impl Parse for Stmt {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let ahead = input.fork();
+            ahead.call(Attribute::parse_outer)?;
 
-    #[cfg(feature = "full")]
-    named2!(stmt_mac -> Stmt, do_parse!(
-        attrs: many0!(Attribute::old_parse_outer) >>
-        what: call!(Path::old_parse_mod_style) >>
-        bang: punct!(!) >>
-    // Only parse braces here; paren and bracket will get parsed as
-    // expression statements
-        data: braces!(syn!(TokenStream)) >>
-        semi: option!(punct!(;)) >>
-        (Stmt::Item(Item::Macro(ItemMacro {
-            attrs: attrs,
-            ident: None,
-            mac: Macro {
-                path: what,
-                bang_token: bang,
-                delimiter: MacroDelimiter::Brace(data.0),
-                tts: data.1,
-            },
-            semi_token: semi,
-        })))
-    ));
-
-    #[cfg(feature = "full")]
-    named2!(stmt_local -> Stmt, do_parse!(
-        attrs: many0!(Attribute::old_parse_outer) >>
-        let_: keyword!(let) >>
-        pats: call!(Punctuated::parse_separated_nonempty) >>
-        ty: option!(tuple!(punct!(:), syn!(Type))) >>
-        init: option!(tuple!(punct!(=), syn!(Expr))) >>
-        semi: punct!(;) >>
-        (Stmt::Local(Local {
-            attrs: attrs,
-            let_token: let_,
-            pats: pats,
-            ty: ty.map(|(colon, ty)| (colon, Box::new(ty))),
-            init: init.map(|(eq, expr)| (eq, Box::new(expr))),
-            semi_token: semi,
-        }))
-    ));
-
-    #[cfg(feature = "full")]
-    named2!(stmt_item -> Stmt, map!(syn!(Item), |i| Stmt::Item(i)));
-
-    #[cfg(feature = "full")]
-    named2!(stmt_blockexpr -> Stmt, do_parse!(
-        mut attrs: many0!(Attribute::old_parse_outer) >>
-        mut e: shim!(expr_nosemi) >>
-        semi: option!(punct!(;)) >>
-        ({
-            attrs.extend(e.replace_attrs(Vec::new()));
-            e.replace_attrs(attrs);
-            if let Some(semi) = semi {
-                Stmt::Semi(e, semi)
+            // TODO: better error messages
+            if {
+                let ahead = ahead.fork();
+                // Only parse braces here; paren and bracket will get parsed as
+                // expression statements
+                ahead.call(Path::parse_mod_style).is_ok()
+                    && ahead.parse::<Token![!]>().is_ok()
+                    && (ahead.peek(token::Brace) || ahead.peek(Ident))
+            } {
+                stmt_mac(input)
+            } else if ahead.peek(Token![let]) {
+                stmt_local(input).map(Stmt::Local)
+            } else if ahead.peek(Token![pub])
+                || ahead.peek(Token![crate]) && !ahead.peek2(Token![::])
+                || ahead.peek(Token![extern]) && !ahead.peek2(Token![::])
+                || ahead.peek(Token![use])
+                || ahead.peek(Token![static]) && (ahead.peek2(Token![mut]) || ahead.peek2(Ident))
+                || ahead.peek(Token![const])
+                || ahead.peek(Token![unsafe]) && !ahead.peek2(token::Brace)
+                || ahead.peek(Token![async]) && (ahead.peek2(Token![extern]) || ahead.peek2(Token![fn]))
+                || ahead.peek(Token![fn])
+                || ahead.peek(Token![mod])
+                || ahead.peek(Token![type])
+                || ahead.peek(Token![existential]) && ahead.peek2(Token![type])
+                || ahead.peek(Token![struct])
+                || ahead.peek(Token![enum])
+                || ahead.peek(Token![union]) && ahead.peek2(Ident)
+                || ahead.peek(Token![auto]) && ahead.peek2(Token![trait])
+                || ahead.peek(Token![trait])
+                || ahead.peek(Token![default]) && (ahead.peek2(Token![unsafe]) || ahead.peek2(Token![impl]))
+                || ahead.peek(Token![impl])
+                || ahead.peek(Token![macro])
+            {
+                input.parse().map(Stmt::Item)
+            } else if ahead.fork().call(stmt_blockexpr).is_ok() {
+                stmt_blockexpr(input)
+            } else if ahead.call(stmt_expr).is_ok() {
+                stmt_expr(input)
             } else {
-                Stmt::Expr(e)
+                Err(input.error("expected statement"))
             }
-        })
-    ));
-
-    #[cfg(feature = "full")]
-    named2!(stmt_expr -> Stmt, do_parse!(
-        mut attrs: many0!(Attribute::old_parse_outer) >>
-        mut e: syn!(Expr) >>
-        semi: punct!(;) >>
-        ({
-            attrs.extend(e.replace_attrs(Vec::new()));
-            e.replace_attrs(attrs);
-            Stmt::Semi(e, semi)
-        })
-    ));
-
-    #[cfg(feature = "full")]
-    impl Synom for Pat {
-        named!(parse -> Self, alt!(
-            syn!(PatWild) => { Pat::Wild } // must be before pat_ident
-            |
-            syn!(PatBox) => { Pat::Box }  // must be before pat_ident
-            |
-            syn!(PatRange) => { Pat::Range } // must be before pat_lit
-            |
-            syn!(PatTupleStruct) => { Pat::TupleStruct }  // must be before pat_ident
-            |
-            syn!(PatStruct) => { Pat::Struct } // must be before pat_ident
-            |
-            syn!(PatMacro) => { Pat::Macro } // must be before pat_ident
-            |
-            syn!(PatLit) => { Pat::Lit } // must be before pat_ident
-            |
-            syn!(PatIdent) => { Pat::Ident } // must be before pat_path
-            |
-            syn!(PatPath) => { Pat::Path }
-            |
-            syn!(PatTuple) => { Pat::Tuple }
-            |
-            syn!(PatRef) => { Pat::Ref }
-            |
-            syn!(PatSlice) => { Pat::Slice }
-        ));
+        }
     }
 
     #[cfg(feature = "full")]
-    impl Synom for PatWild {
-        named!(parse -> Self, map!(
-            punct!(_),
-            |u| PatWild { underscore_token: u }
-        ));
+    fn stmt_mac(input: ParseStream) -> Result<Stmt> {
+        let attrs = input.call(Attribute::parse_outer)?;
+        let path = input.call(Path::parse_mod_style)?;
+        let bang_token: Token![!] = input.parse()?;
+        let ident: Option<Ident> = input.parse()?;
+        let (delimiter, tts) = mac::parse_delimiter(input)?;
+        let semi_token: Option<Token![;]> = input.parse()?;
+
+        Ok(Stmt::Item(Item::Macro(ItemMacro {
+            attrs: attrs,
+            ident: ident,
+            mac: Macro {
+                path: path,
+                bang_token: bang_token,
+                delimiter: delimiter,
+                tts: tts,
+            },
+            semi_token: semi_token,
+        })))
     }
 
     #[cfg(feature = "full")]
-    impl Synom for PatBox {
-        named!(parse -> Self, do_parse!(
-            boxed: keyword!(box) >>
-            pat: syn!(Pat) >>
-            (PatBox {
-                pat: Box::new(pat),
-                box_token: boxed,
+    fn stmt_local(input: ParseStream) -> Result<Local> {
+        Ok(Local {
+            attrs: input.call(Attribute::parse_outer)?,
+            let_token: input.parse()?,
+            pats: {
+                let mut pats = Punctuated::new();
+                let value: Pat = input.parse()?;
+                pats.push_value(value);
+                while input.peek(Token![|]) && !input.peek(Token![||]) && !input.peek(Token![|=]) {
+                    let punct = input.parse()?;
+                    pats.push_punct(punct);
+                    let value: Pat = input.parse()?;
+                    pats.push_value(value);
+                }
+                pats
+            },
+            ty: {
+                if input.peek(Token![:]) {
+                    let colon_token: Token![:] = input.parse()?;
+                    let ty: Type = input.parse()?;
+                    Some((colon_token, Box::new(ty)))
+                } else {
+                    None
+                }
+            },
+            init: {
+                if input.peek(Token![=]) {
+                    let eq_token: Token![=] = input.parse()?;
+                    let init: Expr = input.parse()?;
+                    Some((eq_token, Box::new(init)))
+                } else {
+                    None
+                }
+            },
+            semi_token: input.parse()?,
+        })
+    }
+
+    #[cfg(feature = "full")]
+    fn stmt_blockexpr(input: ParseStream) -> Result<Stmt> {
+        let mut attrs = input.call(Attribute::parse_outer)?;
+        let mut e = expr_nosemi(input)?;
+
+        attrs.extend(e.replace_attrs(Vec::new()));
+        e.replace_attrs(attrs);
+
+        if input.peek(Token![;]) {
+            Ok(Stmt::Semi(e, input.parse()?))
+        } else {
+            Ok(Stmt::Expr(e))
+        }
+    }
+
+    #[cfg(feature = "full")]
+    fn stmt_expr(input: ParseStream) -> Result<Stmt> {
+        let mut attrs = input.call(Attribute::parse_outer)?;
+        let mut e: Expr = input.parse()?;
+        let semi_token: Token![;] = input.parse()?;
+
+        attrs.extend(e.replace_attrs(Vec::new()));
+        e.replace_attrs(attrs);
+
+        Ok(Stmt::Semi(e, semi_token))
+    }
+
+    #[cfg(feature = "full")]
+    impl Parse for Pat {
+        fn parse(input: ParseStream) -> Result<Self> {
+            // TODO: better error messages
+            let lookahead = input.lookahead1();
+            if lookahead.peek(Token![_]) {
+                input.parse().map(Pat::Wild)
+            } else if lookahead.peek(Token![box]) {
+                input.parse().map(Pat::Box)
+            } else if input.fork().parse::<PatRange>().is_ok() {
+                // must be before Pat::Lit
+                input.parse().map(Pat::Range)
+            } else if input.fork().parse::<PatTupleStruct>().is_ok() {
+                // must be before Pat::Ident
+                input.parse().map(Pat::TupleStruct)
+            } else if input.fork().parse::<PatStruct>().is_ok() {
+                // must be before Pat::Ident
+                input.parse().map(Pat::Struct)
+            } else if input.fork().parse::<PatMacro>().is_ok() {
+                // must be before Pat::Ident
+                input.parse().map(Pat::Macro)
+            } else if input.fork().parse::<PatLit>().is_ok() {
+                // must be before Pat::Ident
+                input.parse().map(Pat::Lit)
+            } else if input.fork().parse::<PatIdent>().is_ok() {
+                input.parse().map(Pat::Ident)
+            } else if input.fork().parse::<PatPath>().is_ok() {
+                input.parse().map(Pat::Path)
+            } else if lookahead.peek(token::Paren) {
+                input.parse().map(Pat::Tuple)
+            } else if lookahead.peek(Token![&]) {
+                input.parse().map(Pat::Ref)
+            } else if lookahead.peek(token::Bracket) {
+                input.parse().map(Pat::Slice)
+            } else {
+                Err(lookahead.error())
+            }
+        }
+    }
+
+    #[cfg(feature = "full")]
+    impl Parse for PatWild {
+        fn parse(input: ParseStream) -> Result<Self> {
+            Ok(PatWild {
+                underscore_token: input.parse()?,
             })
-        ));
+        }
     }
 
     #[cfg(feature = "full")]
-    impl Synom for PatIdent {
-        named!(parse -> Self, do_parse!(
-            by_ref: option!(keyword!(ref)) >>
-            mutability: option!(keyword!(mut)) >>
-            name: alt!(
-                syn!(Ident)
-                |
-                keyword!(self) => { Into::into }
-            ) >>
-            not!(punct!(<)) >>
-            not!(punct!(::)) >>
-            subpat: option!(tuple!(punct!(@), syn!(Pat))) >>
-            (PatIdent {
+    impl Parse for PatBox {
+        fn parse(input: ParseStream) -> Result<Self> {
+            Ok(PatBox {
+                box_token: input.parse()?,
+                pat: input.parse()?,
+            })
+        }
+    }
+
+    #[cfg(feature = "full")]
+    impl Parse for PatIdent {
+        fn parse(input: ParseStream) -> Result<Self> {
+            Ok(PatIdent {
+                by_ref: input.parse()?,
+                mutability: input.parse()?,
+                ident: {
+                    let ident = if input.peek(Ident) || input.peek(Token![self]) {
+                        input.call(Ident::parse_any2)?
+                    } else {
+                        return Err(input.error("expected identifier or `self`"));
+                    };
+                    if input.peek(Token![<]) || input.peek(Token![::]) {
+                        return Err(input.error("unexpected token"));
+                    }
+                    ident
+                },
+                subpat: {
+                    if input.peek(Token![@]) {
+                        let at_token: Token![@] = input.parse()?;
+                        let subpat: Pat = input.parse()?;
+                        Some((at_token, Box::new(subpat)))
+                    } else {
+                        None
+                    }
+                },
+            })
+        }
+    }
+
+    #[cfg(feature = "full")]
+    impl Parse for PatTupleStruct {
+        fn parse(input: ParseStream) -> Result<Self> {
+            Ok(PatTupleStruct {
+                path: input.parse()?,
+                pat: input.parse()?,
+            })
+        }
+    }
+
+    #[cfg(feature = "full")]
+    impl Parse for PatStruct {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let path: Path = input.parse()?;
+
+            let content;
+            let brace_token = braced!(content in input);
+
+            let mut fields = Punctuated::new();
+            while !content.is_empty() && !content.peek(Token![..]) {
+                let value: FieldPat = content.parse()?;
+                fields.push_value(value);
+                if !content.peek(Token![,]) {
+                    break;
+                }
+                let punct: Token![,] = content.parse()?;
+                fields.push_punct(punct);
+            }
+
+            let dot2_token = if fields.empty_or_trailing() && content.peek(Token![..]) {
+                Some(content.parse()?)
+            } else {
+                None
+            };
+
+            Ok(PatStruct {
+                path: path,
+                brace_token: brace_token,
+                fields: fields,
+                dot2_token: dot2_token,
+            })
+        }
+    }
+
+    #[cfg(feature = "full")]
+    impl Parse for FieldPat {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let boxed: Option<Token![box]> = input.parse()?;
+            let by_ref: Option<Token![ref]> = input.parse()?;
+            let mutability: Option<Token![mut]> = input.parse()?;
+            let member: Member = input.parse()?;
+
+            if boxed.is_none() && by_ref.is_none() && mutability.is_none() && input.peek(Token![:])
+                || member.is_unnamed()
+            {
+                return Ok(FieldPat {
+                    attrs: Vec::new(),
+                    member: member,
+                    colon_token: input.parse()?,
+                    pat: input.parse()?,
+                });
+            }
+
+            let ident = match member {
+                Member::Named(ident) => ident,
+                Member::Unnamed(_) => unreachable!(),
+            };
+
+            let mut pat = Pat::Ident(PatIdent {
                 by_ref: by_ref,
                 mutability: mutability,
-                ident: name,
-                subpat: subpat.map(|(at, pat)| (at, Box::new(pat))),
-            })
-        ));
-    }
+                ident: ident.clone(),
+                subpat: None,
+            });
 
-    #[cfg(feature = "full")]
-    impl Synom for PatTupleStruct {
-        named!(parse -> Self, do_parse!(
-            path: syn!(Path) >>
-            tuple: syn!(PatTuple) >>
-            (PatTupleStruct {
-                path: path,
-                pat: tuple,
-            })
-        ));
-    }
-
-    #[cfg(feature = "full")]
-    impl Synom for PatStruct {
-        named!(parse -> Self, do_parse!(
-            path: syn!(Path) >>
-            data: braces!(do_parse!(
-                fields: call!(Punctuated::parse_terminated) >>
-                base: option!(cond!(fields.empty_or_trailing(), punct!(..))) >>
-                (fields, base)
-            )) >>
-            (PatStruct {
-                path: path,
-                fields: (data.1).0,
-                brace_token: data.0,
-                dot2_token: (data.1).1.and_then(|m| m),
-            })
-        ));
-    }
-
-    #[cfg(feature = "full")]
-    impl Synom for FieldPat {
-        named!(parse -> Self, alt!(
-            do_parse!(
-                member: syn!(Member) >>
-                colon: punct!(:) >>
-                pat: syn!(Pat) >>
-                (FieldPat {
-                    member: member,
+            if let Some(boxed) = boxed {
+                pat = Pat::Box(PatBox {
                     pat: Box::new(pat),
-                    attrs: Vec::new(),
-                    colon_token: Some(colon),
-                })
-            )
-            |
-            do_parse!(
-                boxed: option!(keyword!(box)) >>
-                by_ref: option!(keyword!(ref)) >>
-                mutability: option!(keyword!(mut)) >>
-                ident: syn!(Ident) >>
-                ({
-                    let mut pat: Pat = PatIdent {
-                        by_ref: by_ref,
-                        mutability: mutability,
-                        ident: ident.clone(),
-                        subpat: None,
-                    }.into();
-                    if let Some(boxed) = boxed {
-                        pat = PatBox {
-                            pat: Box::new(pat),
-                            box_token: boxed,
-                        }.into();
-                    }
-                    FieldPat {
-                        member: Member::Named(ident),
-                        pat: Box::new(pat),
-                        attrs: Vec::new(),
-                        colon_token: None,
-                    }
-                })
-            )
-        ));
+                    box_token: boxed,
+                });
+            }
+
+            Ok(FieldPat {
+                member: Member::Named(ident),
+                pat: Box::new(pat),
+                attrs: Vec::new(),
+                colon_token: None,
+            })
+        }
     }
 
     impl Parse for Member {
@@ -2789,152 +2934,190 @@
     }
 
     #[cfg(feature = "full")]
-    impl Synom for PatPath {
-        named!(parse -> Self, map!(
-            syn!(ExprPath),
-            |p| PatPath { qself: p.qself, path: p.path }
-        ));
+    impl Parse for PatPath {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let p: ExprPath = input.parse()?;
+            Ok(PatPath {
+                qself: p.qself,
+                path: p.path,
+            })
+        }
     }
 
     #[cfg(feature = "full")]
-    impl Synom for PatTuple {
-        named!(parse -> Self, do_parse!(
-            data: parens!(do_parse!(
-                front: call!(Punctuated::parse_terminated) >>
-                dotdot: option!(cond_reduce!(front.empty_or_trailing(),
-                    tuple!(punct!(..), option!(punct!(,)))
-                )) >>
-                back: cond!(match dotdot {
-                                Some((_, Some(_))) => true,
-                                _ => false,
-                            },
-                            Punctuated::parse_terminated) >>
-                (front, dotdot, back)
-            )) >>
-            ({
-                let (parens, (front, dotdot, back)) = data;
-                let (dotdot, trailing) = match dotdot {
-                    Some((a, b)) => (Some(a), Some(b)),
-                    None => (None, None),
-                };
-                PatTuple {
-                    paren_token: parens,
-                    front: front,
-                    dot2_token: dotdot,
-                    comma_token: trailing.unwrap_or_default(),
-                    back: back.unwrap_or_default(),
+    impl Parse for PatTuple {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let content;
+            let paren_token = parenthesized!(content in input);
+
+            let mut front = Punctuated::new();
+            let mut dot2_token = None::<Token![..]>;
+            let mut comma_token = None::<Token![,]>;
+            loop {
+                if content.is_empty() {
+                    break;
                 }
-            })
-        ));
-    }
+                if content.peek(Token![..]) {
+                    dot2_token = Some(content.parse()?);
+                    comma_token = content.parse()?;
+                    break;
+                }
+                let value: Pat = content.parse()?;
+                front.push_value(value);
+                if content.is_empty() {
+                    break;
+                }
+                let punct = content.parse()?;
+                front.push_punct(punct);
+            }
 
-    #[cfg(feature = "full")]
-    impl Synom for PatRef {
-        named!(parse -> Self, do_parse!(
-            and: punct!(&) >>
-            mutability: option!(keyword!(mut)) >>
-            pat: syn!(Pat) >>
-            (PatRef {
-                pat: Box::new(pat),
-                mutability: mutability,
-                and_token: and,
-            })
-        ));
-    }
-
-    #[cfg(feature = "full")]
-    impl Synom for PatLit {
-        named!(parse -> Self, do_parse!(
-            lit: shim!(pat_lit_expr) >>
-            (if let Expr::Path(_) = lit {
-                return parse_error(); // these need to be parsed by pat_path
+            let back = if comma_token.is_some() {
+                content.parse_synom(Punctuated::parse_terminated)?
             } else {
-                PatLit {
-                    expr: Box::new(lit),
-                }
+                Punctuated::new()
+            };
+
+            Ok(PatTuple {
+                paren_token: paren_token,
+                front: front,
+                dot2_token: dot2_token,
+                comma_token: comma_token,
+                back: back,
             })
-        ));
+        }
     }
 
     #[cfg(feature = "full")]
-    impl Synom for PatRange {
-        named!(parse -> Self, do_parse!(
-            lo: shim!(pat_lit_expr) >>
-            limits: syn!(RangeLimits) >>
-            hi: shim!(pat_lit_expr) >>
-            (PatRange {
-                lo: Box::new(lo),
-                hi: Box::new(hi),
-                limits: limits,
+    impl Parse for PatRef {
+        fn parse(input: ParseStream) -> Result<Self> {
+            Ok(PatRef {
+                and_token: input.parse()?,
+                mutability: input.parse()?,
+                pat: input.parse()?,
             })
-        ));
+        }
     }
 
     #[cfg(feature = "full")]
-    named2!(pat_lit_expr -> Expr, do_parse!(
-        neg: option!(punct!(-)) >>
-        v: alt!(
-            syn!(ExprLit) => { Expr::Lit }
-            |
-            syn!(ExprPath) => { Expr::Path }
-        ) >>
-        (if let Some(neg) = neg {
+    impl Parse for PatLit {
+        fn parse(input: ParseStream) -> Result<Self> {
+            if input.peek(Lit) || input.peek(Token![-]) && input.peek2(Lit) {
+                Ok(PatLit {
+                    expr: input.call(pat_lit_expr)?,
+                })
+            } else {
+                Err(input.error("expected literal pattern"))
+            }
+        }
+    }
+
+    #[cfg(feature = "full")]
+    impl Parse for PatRange {
+        fn parse(input: ParseStream) -> Result<Self> {
+            Ok(PatRange {
+                lo: input.call(pat_lit_expr)?,
+                limits: input.parse()?,
+                hi: input.call(pat_lit_expr)?,
+            })
+        }
+    }
+
+    #[cfg(feature = "full")]
+    fn pat_lit_expr(input: ParseStream) -> Result<Box<Expr>> {
+        let neg: Option<Token![-]> = input.parse()?;
+
+        let lookahead = input.lookahead1();
+        let expr = if lookahead.peek(Lit) {
+            Expr::Lit(input.parse()?)
+        } else if lookahead.peek(Ident)
+            || lookahead.peek(Token![::])
+            || lookahead.peek(Token![<])
+            || lookahead.peek(Token![self])
+            || lookahead.peek(Token![Self])
+            || lookahead.peek(Token![super])
+            || lookahead.peek(Token![extern])
+            || lookahead.peek(Token![crate])
+        {
+            Expr::Path(input.parse()?)
+        } else {
+            return Err(lookahead.error());
+        };
+
+        Ok(Box::new(if let Some(neg) = neg {
             Expr::Unary(ExprUnary {
                 attrs: Vec::new(),
                 op: UnOp::Neg(neg),
-                expr: Box::new(v)
+                expr: Box::new(expr),
             })
         } else {
-            v
-        })
-    ));
-
-    #[cfg(feature = "full")]
-    impl Synom for PatSlice {
-        named!(parse -> Self, map!(
-            brackets!(do_parse!(
-                before: call!(Punctuated::parse_terminated) >>
-                middle: option!(do_parse!(
-                    dots: punct!(..) >>
-                    trailing: option!(punct!(,)) >>
-                    (dots, trailing)
-                )) >>
-                after: cond!(
-                    match middle {
-                        Some((_, ref trailing)) => trailing.is_some(),
-                        _ => false,
-                    },
-                    Punctuated::parse_terminated
-                ) >>
-                (before, middle, after)
-            )),
-            |(brackets, (before, middle, after))| {
-                let mut before: Punctuated<Pat, Token![,]> = before;
-                let after: Option<Punctuated<Pat, Token![,]>> = after;
-                let middle: Option<(Token![..], Option<Token![,]>)> = middle;
-                PatSlice {
-                    dot2_token: middle.as_ref().map(|m| Token![..](m.0.spans)),
-                    comma_token: middle.as_ref().and_then(|m| {
-                        m.1.as_ref().map(|m| Token![,](m.spans))
-                    }),
-                    bracket_token: brackets,
-                    middle: middle.and_then(|_| {
-                        if before.empty_or_trailing() {
-                            None
-                        } else {
-                            Some(Box::new(before.pop().unwrap().into_value()))
-                        }
-                    }),
-                    front: before,
-                    back: after.unwrap_or_default(),
-                }
-            }
-        ));
+            expr
+        }))
     }
 
     #[cfg(feature = "full")]
-    impl Synom for PatMacro {
-        named!(parse -> Self, map!(syn!(Macro), |mac| PatMacro { mac: mac }));
+    impl Parse for PatSlice {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let content;
+            let bracket_token = bracketed!(content in input);
+
+            let mut front = Punctuated::new();
+            let mut middle = None;
+            loop {
+                if content.is_empty() || content.peek(Token![..]) {
+                    break;
+                }
+                let value: Pat = content.parse()?;
+                if content.peek(Token![..]) {
+                    middle = Some(Box::new(value));
+                    break;
+                }
+                front.push_value(value);
+                if content.is_empty() {
+                    break;
+                }
+                let punct = content.parse()?;
+                front.push_punct(punct);
+            }
+
+            let dot2_token: Option<Token![..]> = content.parse()?;
+            let mut comma_token = None::<Token![,]>;
+            let mut back = Punctuated::new();
+            if dot2_token.is_some() {
+                comma_token = content.parse()?;
+                if comma_token.is_some() {
+                    loop {
+                        if content.is_empty() {
+                            break;
+                        }
+                        let value: Pat = content.parse()?;
+                        back.push_value(value);
+                        if content.is_empty() {
+                            break;
+                        }
+                        let punct = content.parse()?;
+                        back.push_punct(punct);
+                    }
+                }
+            }
+
+            Ok(PatSlice {
+                bracket_token: bracket_token,
+                front: front,
+                middle: middle,
+                dot2_token: dot2_token,
+                comma_token: comma_token,
+                back: back,
+            })
+        }
+    }
+
+    #[cfg(feature = "full")]
+    impl Parse for PatMacro {
+        fn parse(input: ParseStream) -> Result<Self> {
+            Ok(PatMacro {
+                mac: input.parse()?,
+            })
+        }
     }
 
     #[cfg(feature = "full")]
@@ -2945,6 +3128,13 @@
                 Member::Unnamed(_) => false,
             }
         }
+
+        fn is_unnamed(&self) -> bool {
+            match *self {
+                Member::Named(_) => false,
+                Member::Unnamed(_) => true,
+            }
+        }
     }
 }