Parse blocks like { if a { () } *b = c } and { if a { () }.foo() } correctly
diff --git a/src/expr.rs b/src/expr.rs
index 2b73998..79a4b56 100644
--- a/src/expr.rs
+++ b/src/expr.rs
@@ -1098,6 +1098,26 @@
         syn!(ExprRepeat) => { ExprKind::Repeat }
     ));
 
+    named!(expr_nosemi -> Expr, map!(alt!(
+        syn!(ExprIf) => { ExprKind::If }
+        |
+        syn!(ExprIfLet) => { ExprKind::IfLet }
+        |
+        syn!(ExprWhile) => { ExprKind::While }
+        |
+        syn!(ExprWhileLet) => { ExprKind::WhileLet }
+        |
+        syn!(ExprForLoop) => { ExprKind::ForLoop }
+        |
+        syn!(ExprLoop) => { ExprKind::Loop }
+        |
+        syn!(ExprMatch) => { ExprKind::Match }
+        |
+        syn!(ExprCatch) => { ExprKind::Catch }
+        |
+        syn!(ExprBlock) => { ExprKind::Block }
+    ), Expr::from));
+
     impl Synom for ExprGroup {
         named!(parse -> Self, do_parse!(
             e: grouped!(syn!(Expr)) >>
@@ -1665,6 +1685,8 @@
             |
             stmt_item
             |
+            stmt_blockexpr
+            |
             stmt_expr
         ));
     }
@@ -1716,34 +1738,31 @@
 
     named!(stmt_item -> Stmt, map!(syn!(Item), |i| Stmt::Item(Box::new(i))));
 
-    fn requires_semi(e: &Expr) -> bool {
-        match e.node {
-            ExprKind::If(_) |
-            ExprKind::IfLet(_) |
-            ExprKind::While(_) |
-            ExprKind::WhileLet(_) |
-            ExprKind::ForLoop(_) |
-            ExprKind::Loop(_) |
-            ExprKind::Match(_) |
-            ExprKind::Block(_) => false,
-
-            _ => true,
-        }
-    }
+    named!(stmt_blockexpr -> Stmt, do_parse!(
+        attrs: many0!(call!(Attribute::parse_outer)) >>
+        mut e: expr_nosemi >>
+        // If the next token is a `.` or a `?` it is special-cased to parse as
+        // an expression instead of a blockexpression.
+        not!(syn!(Dot)) >>
+        not!(syn!(Question)) >>
+        semi: option!(syn!(Semi)) >>
+        ({
+            e.attrs = attrs;
+            if let Some(semi) = semi {
+                Stmt::Semi(Box::new(e), semi)
+            } else {
+                Stmt::Expr(Box::new(e))
+            }
+        })
+    ));
 
     named!(stmt_expr -> Stmt, do_parse!(
         attrs: many0!(call!(Attribute::parse_outer)) >>
         mut e: syn!(Expr) >>
-        semi: option!(syn!(Semi)) >>
+        semi: syn!(Semi) >>
         ({
             e.attrs = attrs;
-            if let Some(s) = semi {
-                Stmt::Semi(Box::new(e), s)
-            } else if requires_semi(&e) {
-                return parse_error();
-            } else {
-                Stmt::Expr(Box::new(e))
-            }
+            Stmt::Semi(Box::new(e), semi)
         })
     ));