Parse 'loop' and 'again' the same

This commit is contained in:
Brian Anderson 2012-09-04 13:36:54 -07:00
parent 443f79922d
commit d3e75ea375
4 changed files with 42 additions and 23 deletions

View File

@ -883,7 +883,7 @@ struct parser {
return pexpr(self.parse_sugary_call_expr(~"do", expr_do_body)); return pexpr(self.parse_sugary_call_expr(~"do", expr_do_body));
} else if self.eat_keyword(~"while") { } else if self.eat_keyword(~"while") {
return pexpr(self.parse_while_expr()); 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()); return pexpr(self.parse_loop_expr());
} else if self.eat_keyword(~"match") { } else if self.eat_keyword(~"match") {
return pexpr(self.parse_alt_expr()); return pexpr(self.parse_alt_expr());
@ -969,13 +969,6 @@ struct parser {
ex = expr_break(None); ex = expr_break(None);
} }
hi = self.span.hi; 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") { } else if self.eat_keyword(~"copy") {
let e = self.parse_expr(); let e = self.parse_expr();
ex = expr_copy(e); ex = expr_copy(e);
@ -1609,18 +1602,42 @@ struct parser {
} }
fn parse_loop_expr() -> @expr { fn parse_loop_expr() -> @expr {
let opt_ident; // loop headers look like 'loop {' or 'loop unsafe {'
if is_ident(self.token) && !self.is_any_keyword(copy self.token) { let is_loop_header =
opt_ident = Some(self.parse_ident()); self.token == token::LBRACE
self.expect(token::COLON); || (is_ident(copy self.token)
} else { && self.look_ahead(1) == token::LBRACE);
opt_ident = None; // 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; if is_loop_header || is_labeled_loop_header {
let body = self.parse_block_no_value(); // This is a loop body
let mut hi = body.span.hi; let opt_ident;
return self.mk_expr(lo, hi, expr_loop(body, 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 // For distingishing between record literals and blocks

View File

@ -883,7 +883,9 @@ fn print_possibly_embedded_block_(s: ps, blk: ast::blk, embedded: embed_type,
// alt, do, & while unambiguously without being parenthesized // alt, do, & while unambiguously without being parenthesized
fn print_maybe_parens_discrim(s: ps, e: @ast::expr) { fn print_maybe_parens_discrim(s: ps, e: @ast::expr) {
let disambig = match e.node { 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 _ => false
}; };
if disambig { popen(s); } if disambig { popen(s); }

View File

@ -17,7 +17,7 @@ fn main() {
is_even = false; is_even = false;
i += 1u; i += 1u;
if i % 2u != 0u { if i % 2u != 0u {
again; loop;
} }
is_even = true; is_even = true;
} }
@ -30,7 +30,7 @@ fn main() {
is_even = false; is_even = false;
i += 1u; i += 1u;
if i % 2u != 0u { if i % 2u != 0u {
again; loop;
} }
is_even = true; is_even = true;
} }

View File

@ -59,7 +59,7 @@ fn canttouchthis() -> uint {
fn angrydome() { fn angrydome() {
loop { if break { } } loop { if break { } }
let mut i = 0; 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; } break; }
} }