Implement BinOp parser
diff --git a/src/expr.rs b/src/expr.rs
index b27062c..d8e1fec 100644
--- a/src/expr.rs
+++ b/src/expr.rs
@@ -1115,33 +1115,19 @@
 
     // Parse a left-associative binary operator.
     macro_rules! binop {
-        (
-            $name: ident,
-            $next: ident,
-            $submac: ident!( $($args:tt)* )
-        ) => {
+        ($name:ident, $next:ident, |$var:ident| $parse_op:expr) => {
             fn $name(input: ParseStream, allow_struct: AllowStruct, allow_block: AllowBlock) -> Result<Expr> {
-                mod synom {
-                    use super::*;
-
-                    named!(pub $name(allow_struct: AllowStruct, allow_block: AllowBlock) -> Expr, do_parse!(
-                        mut e: shim!($next, allow_struct, allow_block) >>
-                        many0!(do_parse!(
-                            op: $submac!($($args)*) >>
-                            rhs: shim!($next, allow_struct, AllowBlock(true)) >>
-                            ({
-                                e = ExprBinary {
-                                    attrs: Vec::new(),
-                                    left: Box::new(e.into()),
-                                    op: op,
-                                    right: Box::new(rhs.into()),
-                                }.into();
-                            })
-                        )) >>
-                        (e)
-                    ));
+                let $var = input;
+                let mut e: Expr = $next(input, allow_struct, allow_block)?;
+                while let Some(op) = $parse_op {
+                    e = Expr::Binary(ExprBinary {
+                        attrs: Vec::new(),
+                        left: Box::new(e),
+                        op: op,
+                        right: Box::new($next(input, allow_struct, AllowBlock(true))?),
+                    });
                 }
-                input.step_cursor(|cursor| synom::$name(*cursor, allow_struct, allow_block))
+                Ok(e)
             }
         }
     }
@@ -1258,10 +1244,22 @@
     ));
 
     // <and> || <and> ...
-    binop!(or_expr, and_expr, map!(punct!(||), BinOp::Or));
+    binop!(or_expr, and_expr, |input| {
+        if input.peek(Token![||]) {
+            Some(BinOp::Or(input.parse()?))
+        } else {
+            None
+        }
+    });
 
     // <compare> && <compare> ...
-    binop!(and_expr, compare_expr, map!(punct!(&&), BinOp::And));
+    binop!(and_expr, compare_expr, |input| {
+        if input.peek(Token![&&]) {
+            Some(BinOp::And(input.parse()?))
+        } else {
+            None
+        }
+    });
 
     // <bitor> == <bitor> ...
     // <bitor> != <bitor> ...
@@ -1272,96 +1270,91 @@
     //
     // NOTE: This operator appears to be parsed as left-associative, but errors
     // if it is used in a non-associative manner.
-    binop!(
-        compare_expr,
-        bitor_expr,
-        alt!(
-        punct!(==) => { BinOp::Eq }
-        |
-        punct!(!=) => { BinOp::Ne }
-        |
-        // must be above Lt
-        punct!(<=) => { BinOp::Le }
-        |
-        // must be above Gt
-        punct!(>=) => { BinOp::Ge }
-        |
-        do_parse!(
-            // Make sure that we don't eat the < part of a <- operator
-            not!(punct!(<-)) >>
-            t: punct!(<) >>
-            (BinOp::Lt(t))
-        )
-        |
-        punct!(>) => { BinOp::Gt }
-    )
-    );
+    binop!(compare_expr, bitor_expr, |input| {
+        if input.peek(Token![==]) {
+            Some(BinOp::Eq(input.parse()?))
+        } else if input.peek(Token![!=]) {
+            Some(BinOp::Ne(input.parse()?))
+        // must be before `<`
+        } else if input.peek(Token![<=]) {
+            Some(BinOp::Le(input.parse()?))
+        // must be before `>`
+        } else if input.peek(Token![>=]) {
+            Some(BinOp::Ge(input.parse()?))
+        } else if input.peek(Token![<]) && !input.peek(Token![<<]) && !input.peek(Token![<-]) {
+            Some(BinOp::Lt(input.parse()?))
+        } else if input.peek(Token![>]) && !input.peek(Token![>>]) {
+            Some(BinOp::Gt(input.parse()?))
+        } else {
+            None
+        }
+    });
 
     // <bitxor> | <bitxor> ...
-    binop!(
-        bitor_expr,
-        bitxor_expr,
-        do_parse!(not!(punct!(||)) >> not!(punct!(|=)) >> t: punct!(|) >> (BinOp::BitOr(t)))
-    );
+    binop!(bitor_expr, bitxor_expr, |input| {
+        if input.peek(Token![|]) && !input.peek(Token![||]) && !input.peek(Token![|=]) {
+            Some(BinOp::BitOr(input.parse()?))
+        } else {
+            None
+        }
+    });
 
     // <bitand> ^ <bitand> ...
-    binop!(
-        bitxor_expr,
-        bitand_expr,
-        do_parse!(
-            // NOTE: Make sure we aren't looking at ^=.
-            not!(punct!(^=)) >> t: punct!(^) >> (BinOp::BitXor(t))
-        )
-    );
+    binop!(bitxor_expr, bitand_expr, |input| {
+        if input.peek(Token![^]) && !input.peek(Token![^=]) {
+            Some(BinOp::BitXor(input.parse()?))
+        } else {
+            None
+        }
+    });
 
     // <shift> & <shift> ...
-    binop!(
-        bitand_expr,
-        shift_expr,
-        do_parse!(
-            // NOTE: Make sure we aren't looking at && or &=.
-            not!(punct!(&&)) >> not!(punct!(&=)) >> t: punct!(&) >> (BinOp::BitAnd(t))
-        )
-    );
+    binop!(bitand_expr, shift_expr, |input| {
+        if input.peek(Token![&]) && !input.peek(Token![&&]) && !input.peek(Token![&=]) {
+            Some(BinOp::BitAnd(input.parse()?))
+        } else {
+            None
+        }
+    });
 
     // <arith> << <arith> ...
     // <arith> >> <arith> ...
-    binop!(
-        shift_expr,
-        arith_expr,
-        alt!(
-        punct!(<<) => { BinOp::Shl }
-        |
-        punct!(>>) => { BinOp::Shr }
-    )
-    );
+    binop!(shift_expr, arith_expr, |input| {
+        if input.peek(Token![<<]) && !input.peek(Token![<<=]) {
+            Some(BinOp::Shl(input.parse()?))
+        } else if input.peek(Token![>>]) && !input.peek(Token![>>=]) {
+            Some(BinOp::Shr(input.parse()?))
+        } else {
+            None
+        }
+    });
 
     // <term> + <term> ...
     // <term> - <term> ...
-    binop!(
-        arith_expr,
-        term_expr,
-        alt!(
-        punct!(+) => { BinOp::Add }
-        |
-        punct!(-) => { BinOp::Sub }
-    )
-    );
+    binop!(arith_expr, term_expr, |input| {
+        if input.peek(Token![+]) && !input.peek(Token![+=]) {
+            Some(BinOp::Add(input.parse()?))
+        } else if input.peek(Token![-]) && !input.peek(Token![-=]) {
+            Some(BinOp::Sub(input.parse()?))
+        } else {
+            None
+        }
+    });
 
     // <cast> * <cast> ...
     // <cast> / <cast> ...
     // <cast> % <cast> ...
-    binop!(
-        term_expr,
-        cast_expr,
-        alt!(
-        punct!(*) => { BinOp::Mul }
-        |
-        punct!(/) => { BinOp::Div }
-        |
-        punct!(%) => { BinOp::Rem }
-    )
-    );
+    binop!(term_expr, cast_expr, |input| {
+        if input.peek(Token![*]) && !input.peek(Token![*=]) {
+            Some(BinOp::Mul(input.parse()?))
+        } else if input.peek(Token![/]) && !input.peek(Token![/=]) {
+            Some(BinOp::Div(input.parse()?))
+        } else if input.peek(Token![%]) && !input.peek(Token![%=]) {
+            Some(BinOp::Rem(input.parse()?))
+        } else {
+            None
+        }
+    });
 
     // <unary> as <ty>
     // <unary> : <ty>