Implement Block::parse_within
diff --git a/src/expr.rs b/src/expr.rs
index bbaaee7..9776aa9 100644
--- a/src/expr.rs
+++ b/src/expr.rs
@@ -1007,7 +1007,7 @@
 
 #[cfg(any(feature = "parsing", feature = "printing"))]
 #[cfg(feature = "full")]
-fn arm_expr_requires_comma(expr: &Expr) -> bool {
+fn requires_terminator(expr: &Expr) -> bool {
     // see https://github.com/rust-lang/rust/blob/eb8f2586e/src/libsyntax/parse/classify.rs#L17-L37
     match *expr {
         Expr::Unsafe(..)
@@ -2027,7 +2027,7 @@
             fat_arrow_token: input.parse()?,
             body: {
                 let body = input.call(expr_early)?;
-                requires_comma = arm_expr_requires_comma(&body);
+                requires_comma = requires_terminator(&body);
                 Box::new(body)
             },
             comma: {
@@ -2431,77 +2431,72 @@
     #[cfg(feature = "full")]
     impl Block {
         pub fn parse_within(input: ParseStream) -> Result<Vec<Stmt>> {
-            input.step_cursor(|cursor| Self::old_parse_within(*cursor))
-        }
+            while input.peek(Token![;]) {
+                input.parse::<Token![;]>()?;
+            }
 
-        named!(old_parse_within -> Vec<Stmt>, do_parse!(
-            many0!(punct!(;)) >>
-            mut standalone: many0!(do_parse!(
-                stmt: syn!(Stmt) >>
-                many0!(punct!(;)) >>
-                (stmt)
-            )) >>
-            last: option!(do_parse!(
-                attrs: many0!(Attribute::old_parse_outer) >>
-                mut e: syn!(Expr) >>
-                ({
-                    e.replace_attrs(attrs);
-                    Stmt::Expr(e)
-                })
-            )) >>
-            (match last {
-                None => standalone,
-                Some(last) => {
-                    standalone.push(last);
-                    standalone
+            let mut stmts = Vec::new();
+            while !input.is_empty() {
+                let s = parse_stmt(input, true)?;
+                if let Stmt::Expr(ref s) = s {
+                    if requires_terminator(s) && !input.is_empty() {
+                        return Err(input.error("unexpected token"));
+                    }
                 }
-            })
-        ));
+                stmts.push(s);
+            }
+            Ok(stmts)
+        }
     }
 
     #[cfg(feature = "full")]
     impl Parse for Stmt {
         fn parse(input: ParseStream) -> Result<Self> {
-            let ahead = input.fork();
-            ahead.call(Attribute::parse_outer)?;
+            parse_stmt(input, false)
+        }
+    }
 
-            // 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 {
-                input.call(stmt_expr)
-            }
+    #[cfg(feature = "full")]
+    fn parse_stmt(input: ParseStream, allow_nosemi: bool) -> Result<Stmt> {
+        let ahead = input.fork();
+        ahead.call(Attribute::parse_outer)?;
+
+        // 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 {
+            stmt_expr(input, allow_nosemi)
         }
     }
 
@@ -2567,7 +2562,7 @@
     }
 
     #[cfg(feature = "full")]
-    fn stmt_expr(input: ParseStream) -> Result<Stmt> {
+    fn stmt_expr(input: ParseStream, allow_nosemi: bool) -> Result<Stmt> {
         let mut attrs = input.call(Attribute::parse_outer)?;
         let mut e = expr_early(input)?;
 
@@ -2578,21 +2573,10 @@
             return Ok(Stmt::Semi(e, input.parse()?));
         }
 
-        match e {
-            Expr::IfLet(_) |
-            Expr::If(_) |
-            Expr::WhileLet(_) |
-            Expr::While(_) |
-            Expr::ForLoop(_) |
-            Expr::Loop(_) |
-            Expr::Match(_) |
-            Expr::TryBlock(_) |
-            Expr::Yield(_) |
-            Expr::Unsafe(_) |
-            Expr::Block(_) => Ok(Stmt::Expr(e)),
-            _ => {
-                Err(input.error("expected semicolon"))
-            }
+        if allow_nosemi && !requires_terminator(&e) {
+            Ok(Stmt::Expr(e))
+        } else {
+            Err(input.error("expected semicolon"))
         }
     }
 
@@ -3269,7 +3253,7 @@
                     // Ensure that we have a comma after a non-block arm, except
                     // for the last one.
                     let is_last = i == self.arms.len() - 1;
-                    if !is_last && arm_expr_requires_comma(&arm.body) && arm.comma.is_none() {
+                    if !is_last && requires_terminator(&arm.body) && arm.comma.is_none() {
                         <Token![,]>::default().to_tokens(tokens);
                     }
                 }