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); - } else { - opt_ident = None; - } + // 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; - 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)); + 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 { + // 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); + } } // 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; } }