Implement trailer_expr
diff --git a/src/expr.rs b/src/expr.rs
index 615fe35..6503ece 100644
--- a/src/expr.rs
+++ b/src/expr.rs
@@ -1476,102 +1476,134 @@
     // <atom> [ <expr> ] ...
     // <atom> ? ...
     #[cfg(feature = "full")]
-    named2!(trailer_expr(allow_struct: AllowStruct, allow_block: AllowBlock) -> Expr, do_parse!(
-        mut e: shim!(atom_expr, allow_struct, allow_block) >>
-        outer_attrs: value!({
-            let mut attrs = e.replace_attrs(Vec::new());
-            let outer_attrs = take_outer(&mut attrs);
-            e.replace_attrs(attrs);
-            outer_attrs
-        }) >>
-        many0!(alt!(
-            tap!(args: shim!(and_call) => {
-                let (paren, args) = args;
-                e = ExprCall {
+    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());
+        let outer_attrs = take_outer(&mut attrs);
+        e.replace_attrs(attrs);
+
+        loop {
+            if input.peek(token::Paren) {
+                let content;
+                e = Expr::Call(ExprCall {
                     attrs: Vec::new(),
                     func: Box::new(e),
-                    args: args,
-                    paren_token: paren,
-                }.into();
-            })
-            |
-            tap!(more: shim!(and_method_call) => {
-                let mut call = more;
-                call.receiver = Box::new(e);
-                e = call.into();
-            })
-            |
-            tap!(field: shim!(and_field) => {
-                let (token, member) = field;
-                e = ExprField {
+                    paren_token: parenthesized!(content in input),
+                    args: content.parse_terminated(<Expr as Parse>::parse)?,
+                });
+            } else if input.peek(Token![.]) && !input.peek(Token![..]) {
+                let dot_token: Token![.] = input.parse()?;
+                let member: Member = input.parse()?;
+                let turbofish = if member.is_named() && input.peek(Token![::]) {
+                    Some(MethodTurbofish {
+                        colon2_token: input.parse()?,
+                        lt_token: input.parse()?,
+                        args: {
+                            let mut args = Punctuated::new();
+                            loop {
+                                if input.peek(Token![>]) {
+                                    break;
+                                }
+                                let value = input.parse()?;
+                                args.push_value(value);
+                                if input.peek(Token![>]) {
+                                    break;
+                                }
+                                let punct = input.parse()?;
+                                args.push_punct(punct);
+                            }
+                            args
+                        },
+                        gt_token: input.parse()?,
+                    })
+                } else {
+                    None
+                };
+
+                if turbofish.is_some() || input.peek(token::Paren) {
+                    if let Member::Named(method) = member {
+                        let content;
+                        e = Expr::MethodCall(ExprMethodCall {
+                            attrs: Vec::new(),
+                            receiver: Box::new(e),
+                            dot_token: dot_token,
+                            method: method,
+                            turbofish: turbofish,
+                            paren_token: parenthesized!(content in input),
+                            args: content.parse_terminated(<Expr as Parse>::parse)?,
+                        });
+                        continue;
+                    }
+                }
+
+                e = Expr::Field(ExprField {
                     attrs: Vec::new(),
                     base: Box::new(e),
-                    dot_token: token,
+                    dot_token: dot_token,
                     member: member,
-                }.into();
-            })
-            |
-            tap!(i: shim!(and_index) => {
-                let (bracket, i) = i;
-                e = ExprIndex {
+                });
+            } else if input.peek(token::Bracket) {
+                let content;
+                e = Expr::Index(ExprIndex {
                     attrs: Vec::new(),
                     expr: Box::new(e),
-                    bracket_token: bracket,
-                    index: Box::new(i),
-                }.into();
-            })
-            |
-            tap!(question: punct!(?) => {
-                e = ExprTry {
+                    bracket_token: bracketed!(content in input),
+                    index: content.parse()?,
+                });
+            } else if input.peek(Token![?]) {
+                e = Expr::Try(ExprTry {
                     attrs: Vec::new(),
                     expr: Box::new(e),
-                    question_token: question,
-                }.into();
-            })
-        )) >>
-        ({
-            let mut attrs = outer_attrs;
-            attrs.extend(e.replace_attrs(Vec::new()));
-            e.replace_attrs(attrs);
-            e
-        })
-    ));
+                    question_token: input.parse()?,
+                });
+            } else {
+                break;
+            }
+        }
+
+        let mut attrs = outer_attrs;
+        attrs.extend(e.replace_attrs(Vec::new()));
+        e.replace_attrs(attrs);
+        Ok(e)
+    }
 
     // XXX: Duplication == ugly
     #[cfg(not(feature = "full"))]
-    named2!(trailer_expr(allow_struct: AllowStruct, allow_block: AllowBlock) -> Expr, do_parse!(
-        mut e: shim!(atom_expr, allow_struct, allow_block) >>
-        many0!(alt!(
-            tap!(args: shim!(and_call) => {
-                e = ExprCall {
+    fn trailer_expr(input: ParseStream, allow_struct: AllowStruct, allow_block: AllowBlock) -> Result<Expr> {
+        let mut e = atom_expr(input, allow_struct, allow_block)?;
+
+        loop {
+            if input.peek(token::Paren) {
+                let content;
+                e = Expr::Call(ExprCall {
                     attrs: Vec::new(),
                     func: Box::new(e),
-                    paren_token: args.0,
-                    args: args.1,
-                }.into();
-            })
-            |
-            tap!(field: shim!(and_field) => {
-                let (token, member) = field;
-                e = ExprField {
+                    paren_token: parenthesized!(content in input),
+                    args: content.parse_terminated(<Expr as Parse>::parse)?,
+                });
+            } else if input.peek(Token![.]) {
+                e = Expr::Field(ExprField {
                     attrs: Vec::new(),
                     base: Box::new(e),
-                    dot_token: token,
-                    member: member,
-                }.into();
-            })
-            |
-            tap!(i: shim!(and_index) => {
-                e = ExprIndex {
+                    dot_token: input.parse()?,
+                    member: input.parse()?,
+                });
+            } else if input.peek(token::Bracket) {
+                let content;
+                e = Expr::Index(ExprIndex {
                     attrs: Vec::new(),
                     expr: Box::new(e),
-                    bracket_token: i.0,
-                    index: Box::new(i.1),
-                }.into();
-            })
-        )) >>
-        (e)
-    ));
+                    bracket_token: bracketed!(content in input),
+                    index: content.parse()?,
+                });
+            } else {
+                break;
+            }
+        }
+
+        Ok(e)
+    }
 
     // Parse all atomic expressions which don't have to worry about precedence
     // interactions, as they are fully contained.
@@ -1770,47 +1802,12 @@
         ));
     }
 
-    named2!(and_call -> (token::Paren, Punctuated<Expr, Token![,]>),
-        parens!(Punctuated::parse_terminated)
-    );
-
     #[cfg(feature = "full")]
-    named2!(and_method_call -> ExprMethodCall, do_parse!(
-        dot: punct!(.) >>
-        method: syn!(Ident) >>
-        turbofish: option!(tuple!(
-            punct!(::),
-            punct!(<),
-            call!(Punctuated::parse_terminated),
-            punct!(>),
-        )) >>
-        args: parens!(Punctuated::parse_terminated) >>
-        ({
-            ExprMethodCall {
-                attrs: Vec::new(),
-                // this expr will get overwritten after being returned
-                receiver: Box::new(Expr::Verbatim(ExprVerbatim {
-                    tts: TokenStream::new(),
-                })),
-
-                method: method,
-                turbofish: turbofish.map(|fish| MethodTurbofish {
-                    colon2_token: fish.0,
-                    lt_token: fish.1,
-                    args: fish.2,
-                    gt_token: fish.3,
-                }),
-                args: args.1,
-                paren_token: args.0,
-                dot_token: dot,
-            }
-        })
-    ));
-
-    #[cfg(feature = "full")]
-    impl Synom for GenericMethodArgument {
+    impl Parse for GenericMethodArgument {
         // TODO parse const generics as well
-        named!(parse -> Self, map!(ty_no_eq_after, GenericMethodArgument::Type));
+        fn parse(input: ParseStream) -> Result<Self> {
+            input.parse_synom(ty_no_eq_after).map(GenericMethodArgument::Type)
+        }
     }
 
     #[cfg(feature = "full")]
@@ -2492,10 +2489,6 @@
         map!(keyword!(self), |s| (None, s.into()))
     ));
 
-    named2!(and_field -> (Token![.], Member), tuple!(punct!(.), syn!(Member)));
-
-    named2!(and_index -> (token::Bracket, Expr), brackets!(syn!(Expr)));
-
     #[cfg(feature = "full")]
     impl Synom for Block {
         named!(parse -> Self, do_parse!(
@@ -2769,25 +2762,30 @@
         ));
     }
 
-    impl Synom for Member {
-        named!(parse -> Self, alt!(
-            syn!(Ident) => { Member::Named }
-            |
-            syn!(Index) => { Member::Unnamed }
-        ));
+    impl Parse for Member {
+        fn parse(input: ParseStream) -> Result<Self> {
+            if input.peek(Ident) {
+                input.parse().map(Member::Named)
+            } else if input.peek(LitInt) {
+                input.parse().map(Member::Unnamed)
+            } else {
+                Err(input.error("expected identifier or integer"))
+            }
+        }
     }
 
-    impl Synom for Index {
-        named!(parse -> Self, do_parse!(
-            lit: syn!(LitInt) >>
-            ({
-                if let IntSuffix::None = lit.suffix() {
-                    Index { index: lit.value() as u32, span: lit.span() }
-                } else {
-                    return parse_error();
-                }
-            })
-        ));
+    impl Parse for Index {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let lit: LitInt = input.parse()?;
+            if let IntSuffix::None = lit.suffix() {
+                Ok(Index {
+                    index: lit.value() as u32,
+                    span: lit.span(),
+                })
+            } else {
+                Err(input.error("expected unsuffixed integer"))
+            }
+        }
     }
 
     #[cfg(feature = "full")]
@@ -2938,6 +2936,16 @@
     impl Synom for PatMacro {
         named!(parse -> Self, map!(syn!(Macro), |mac| PatMacro { mac: mac }));
     }
+
+    #[cfg(feature = "full")]
+    impl Member {
+        fn is_named(&self) -> bool {
+            match *self {
+                Member::Named(_) => true,
+                Member::Unnamed(_) => false,
+            }
+        }
+    }
 }
 
 #[cfg(feature = "printing")]