diff options
| author | Patrick Walton <pcwalton@mimiga.net> | 2013-04-26 16:19:26 -0700 |
|---|---|---|
| committer | Patrick Walton <pcwalton@mimiga.net> | 2013-04-29 14:30:57 -0700 |
| commit | 670ab8ac367cd8cfe8b86a1338667e7825d8d68d (patch) | |
| tree | babfc59051ffe36a8f4f45c2c8dba2a36dc679d5 | |
| parent | 876483dcf4bdcd0001cc25812060bc04cf367f60 (diff) | |
| download | rust-670ab8ac367cd8cfe8b86a1338667e7825d8d68d.tar.gz rust-670ab8ac367cd8cfe8b86a1338667e7825d8d68d.zip | |
librustc: Change labels to use the lifetime notation `'`.
| -rw-r--r-- | doc/rust.md | 6 | ||||
| -rw-r--r-- | src/libsyntax/ext/asm.rs | 23 | ||||
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 57 | ||||
| -rw-r--r-- | src/libsyntax/print/pprust.rs | 17 | ||||
| -rw-r--r-- | src/test/run-pass/issue-2216.rs | 12 | ||||
| -rw-r--r-- | src/test/run-pass/labeled-break.rs | 4 |
6 files changed, 79 insertions, 40 deletions
diff --git a/doc/rust.md b/doc/rust.md index 0173f61e730..9f81b38009f 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -2187,7 +2187,7 @@ A loop expression denotes an infinite loop; see [Continue expressions](#continue-expressions) for continue expressions. ~~~~~~~~{.ebnf .gram} -loop_expr : "loop" [ ident ':' ] '{' block '}'; +loop_expr : [ lifetime ':' ] "loop" '{' block '}'; ~~~~~~~~ A `loop` expression may optionally have a _label_. @@ -2198,7 +2198,7 @@ See [Break expressions](#break-expressions). ### Break expressions ~~~~~~~~{.ebnf .gram} -break_expr : "break" [ ident ]; +break_expr : "break" [ lifetime ]; ~~~~~~~~ A `break` expression has an optional `label`. @@ -2211,7 +2211,7 @@ but must enclose it. ### Continue expressions ~~~~~~~~{.ebnf .gram} -continue_expr : "loop" [ ident ]; +continue_expr : "loop" [ lifetime ]; ~~~~~~~~ A continue expression, written `loop`, also has an optional `label`. diff --git a/src/libsyntax/ext/asm.rs b/src/libsyntax/ext/asm.rs index 534027bd295..dfebf6f786a 100644 --- a/src/libsyntax/ext/asm.rs +++ b/src/libsyntax/ext/asm.rs @@ -52,7 +52,10 @@ pub fn expand_asm(cx: @ext_ctxt, sp: span, tts: &[ast::token_tree]) let mut dialect = ast::asm_att; let mut state = Asm; - loop outer: { + + // Not using labeled break to get us through one round of bootstrapping. + let mut continue = true; + while continue { match state { Asm => { asm = expr_to_str(cx, p.parse_expr(), @@ -139,20 +142,30 @@ pub fn expand_asm(cx: @ext_ctxt, sp: span, tts: &[ast::token_tree]) p.bump(); match next_state(state) { Some(x) => x, - None => break outer + None => { + continue = false; + break + } } } else if *p.token == token::MOD_SEP { p.bump(); let s = match next_state(state) { Some(x) => x, - None => break outer + None => { + continue = false; + break + } }; match next_state(s) { Some(x) => x, - None => break outer + None => { + continue = false; + break + } } } else if *p.token == token::EOF { - break outer; + continue = false; + break; } else { state }; diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index ae374808270..50bdfb2f557 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -348,6 +348,20 @@ pub impl Parser { self.token_is_keyword(&~"fn", tok) } + fn token_is_lifetime(&self, tok: &token::Token) -> bool { + match *tok { + token::LIFETIME(*) => true, + _ => false, + } + } + + fn get_lifetime(&self, tok: &token::Token) -> ast::ident { + match *tok { + token::LIFETIME(ref ident) => copy *ident, + _ => self.bug(~"not a lifetime"), + } + } + // parse a ty_bare_fun type: fn parse_ty_bare_fn(&self) -> ty_ { @@ -1228,8 +1242,14 @@ pub impl Parser { expr_do_body); } else if self.eat_keyword(&~"while") { return self.parse_while_expr(); + } else if self.token_is_lifetime(&*self.token) { + let lifetime = self.get_lifetime(&*self.token); + self.bump(); + self.expect(&token::COLON); + self.expect_keyword(&~"loop"); + return self.parse_loop_expr(Some(lifetime)); } else if self.eat_keyword(&~"loop") { - return self.parse_loop_expr(); + return self.parse_loop_expr(None); } else if self.eat_keyword(&~"match") { return self.parse_match_expr(); } else if self.eat_keyword(&~"unsafe") { @@ -1290,8 +1310,10 @@ pub impl Parser { } else { ex = expr_ret(None); } } else if self.eat_keyword(&~"break") { // BREAK expression - if is_ident(&*self.token) { - ex = expr_break(Some(self.parse_ident())); + if self.token_is_lifetime(&*self.token) { + let lifetime = self.get_lifetime(&*self.token); + self.bump(); + ex = expr_break(Some(lifetime)); } else { ex = expr_break(None); } @@ -1995,37 +2017,32 @@ pub impl Parser { return self.mk_expr(lo, hi, expr_while(cond, body)); } - fn parse_loop_expr(&self) -> @expr { + fn parse_loop_expr(&self, opt_ident: Option<ast::ident>) -> @expr { // loop headers look like 'loop {' or 'loop unsafe {' let is_loop_header = *self.token == token::LBRACE || (is_ident(&*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(© *self.token) - && self.look_ahead(1) == token::COLON; - if is_loop_header || is_labeled_loop_header { + if is_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(); let hi = body.span.hi; return self.mk_expr(lo, hi, expr_loop(body, opt_ident)); } else { // This is a 'continue' expression + if opt_ident.is_some() { + self.span_err(*self.last_span, + ~"a label may not be used with a `loop` \ + expression"); + } + let lo = self.span.lo; - let ex = if is_ident(&*self.token) { - expr_again(Some(self.parse_ident())) + let ex = if self.token_is_lifetime(&*self.token) { + let lifetime = self.get_lifetime(&*self.token); + self.bump(); + expr_again(Some(lifetime)) } else { expr_again(None) }; diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 337355304d4..d5645ada929 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -1210,12 +1210,13 @@ pub fn print_expr(s: @ps, expr: @ast::expr) { print_block(s, blk); } ast::expr_loop(ref blk, opt_ident) => { - head(s, ~"loop"); - space(s.s); for opt_ident.each |ident| { + word(s.s, ~"'"); print_ident(s, *ident); word_space(s, ~":"); } + head(s, ~"loop"); + space(s.s); print_block(s, blk); } ast::expr_match(expr, ref arms) => { @@ -1363,12 +1364,20 @@ pub fn print_expr(s: @ps, expr: @ast::expr) { ast::expr_break(opt_ident) => { word(s.s, ~"break"); space(s.s); - for opt_ident.each |ident| { print_ident(s, *ident); space(s.s) } + for opt_ident.each |ident| { + word(s.s, ~"'"); + print_ident(s, *ident); + space(s.s); + } } ast::expr_again(opt_ident) => { word(s.s, ~"loop"); space(s.s); - for opt_ident.each |ident| { print_ident(s, *ident); space(s.s) } + for opt_ident.each |ident| { + word(s.s, ~"'"); + print_ident(s, *ident); + space(s.s) + } } ast::expr_ret(result) => { word(s.s, ~"return"); diff --git a/src/test/run-pass/issue-2216.rs b/src/test/run-pass/issue-2216.rs index 0be4084b083..98965cb6d91 100644 --- a/src/test/run-pass/issue-2216.rs +++ b/src/test/run-pass/issue-2216.rs @@ -11,17 +11,17 @@ pub fn main() { let mut x = 0; - loop foo: { - loop bar: { - loop quux: { + 'foo: loop { + 'bar: loop { + 'quux: loop { if 1 == 2 { - break foo; + break 'foo; } else { - break bar; + break 'bar; } } - loop foo; + loop 'foo; } x = 42; break; diff --git a/src/test/run-pass/labeled-break.rs b/src/test/run-pass/labeled-break.rs index b26d8f78e64..06ca401a136 100644 --- a/src/test/run-pass/labeled-break.rs +++ b/src/test/run-pass/labeled-break.rs @@ -12,9 +12,9 @@ // xfail-test pub fn main() { - loop foo: { + 'foo: loop { loop { - break foo; + break 'foo; } } } |
