about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/libsyntax/parse/parser.rs53
-rw-r--r--src/libsyntax/print/pprust.rs4
-rw-r--r--src/test/run-pass/loop-break-cont.rs4
-rw-r--r--src/test/run-pass/weird-exprs.rs2
4 files changed, 41 insertions, 22 deletions
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 60cee541965..5f91d22f5d0 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -883,7 +883,7 @@ struct parser {
             return pexpr(self.parse_sugary_call_expr(~"do", expr_do_body));
         } else if self.eat_keyword(~"while") {
             return pexpr(self.parse_while_expr());
-        } else if self.eat_keyword(~"loop") {
+        } else if self.eat_keyword(~"again") || self.eat_keyword(~"loop") {
             return pexpr(self.parse_loop_expr());
         } else if self.eat_keyword(~"match") {
             return pexpr(self.parse_alt_expr());
@@ -969,13 +969,6 @@ struct parser {
                 ex = expr_break(None);
             }
             hi = self.span.hi;
-        } else if self.eat_keyword(~"again") {
-            if is_ident(self.token) {
-                ex = expr_again(Some(self.parse_ident()));
-            } else {
-                ex = expr_again(None);
-            }
-            hi = self.span.hi;
         } else if self.eat_keyword(~"copy") {
             let e = self.parse_expr();
             ex = expr_copy(e);
@@ -1609,18 +1602,42 @@ struct parser {
     }
 
     fn parse_loop_expr() -> @expr {
-        let opt_ident;
-        if is_ident(self.token) && !self.is_any_keyword(copy self.token) {
-            opt_ident = Some(self.parse_ident());
-            self.expect(token::COLON);
+        // loop headers look like 'loop {' or 'loop unsafe {'
+        let is_loop_header =
+            self.token == token::LBRACE
+            || (is_ident(copy self.token)
+                && self.look_ahead(1) == token::LBRACE);
+        // labeled loop headers look like 'loop foo: {'
+        let is_labeled_loop_header =
+            is_ident(self.token)
+            && !self.is_any_keyword(copy self.token)
+            && self.look_ahead(1) == token::COLON;
+
+        if is_loop_header || is_labeled_loop_header {
+            // This is a loop body
+            let opt_ident;
+            if is_labeled_loop_header {
+                opt_ident = Some(self.parse_ident());
+                self.expect(token::COLON);
+            } else {
+                opt_ident = None;
+            }
+
+            let lo = self.last_span.lo;
+            let body = self.parse_block_no_value();
+            let mut hi = body.span.hi;
+            return self.mk_expr(lo, hi, expr_loop(body, opt_ident));
         } else {
-            opt_ident = None;
+            // This is a 'continue' expression
+            let lo = self.span.lo;
+            let ex = if is_ident(self.token) {
+                expr_again(Some(self.parse_ident()))
+            } else {
+                expr_again(None)
+            };
+            let hi = self.span.hi;
+            return self.mk_expr(lo, hi, ex);
         }
-
-        let lo = self.last_span.lo;
-        let body = self.parse_block_no_value();
-        let mut hi = body.span.hi;
-        return self.mk_expr(lo, hi, expr_loop(body, opt_ident));
     }
 
     // For distingishing between record literals and blocks
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index 4e227bea5cc..dd5fc57f684 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -883,7 +883,9 @@ fn print_possibly_embedded_block_(s: ps, blk: ast::blk, embedded: embed_type,
 // alt, do, & while unambiguously without being parenthesized
 fn print_maybe_parens_discrim(s: ps, e: @ast::expr) {
     let disambig = match e.node {
-      ast::expr_ret(None) | ast::expr_fail(None) => true,
+      ast::expr_ret(None)
+      | ast::expr_fail(None)
+      | ast::expr_again(*) => true,
       _ => false
     };
     if disambig { popen(s); }
diff --git a/src/test/run-pass/loop-break-cont.rs b/src/test/run-pass/loop-break-cont.rs
index 7cdfddc5d7f..20276fff817 100644
--- a/src/test/run-pass/loop-break-cont.rs
+++ b/src/test/run-pass/loop-break-cont.rs
@@ -17,7 +17,7 @@ fn main() {
     is_even = false;
     i += 1u;
     if i % 2u != 0u {
-        again;
+        loop;
     }
     is_even = true;
   }
@@ -30,7 +30,7 @@ fn main() {
     is_even = false;
     i += 1u;
     if i % 2u != 0u {
-        again;
+        loop;
     }
     is_even = true;
   }
diff --git a/src/test/run-pass/weird-exprs.rs b/src/test/run-pass/weird-exprs.rs
index cd5d4594a41..9db274a7ec4 100644
--- a/src/test/run-pass/weird-exprs.rs
+++ b/src/test/run-pass/weird-exprs.rs
@@ -59,7 +59,7 @@ fn canttouchthis() -> uint {
 fn angrydome() {
     loop { if break { } }
     let mut i = 0;
-    loop { i += 1; if i == 1 { match again { 1 => { }, _ => fail ~"wat" } }
+    loop { i += 1; if i == 1 { match (again) { 1 => { }, _ => fail ~"wat" } }
       break; }
 }