Skip to content

Commit 336b4d9

Browse files
committed
librustc: Change labels to use the lifetime notation '.
1 parent 7f2ce3d commit 336b4d9

File tree

6 files changed

+79
-40
lines changed

6 files changed

+79
-40
lines changed

doc/rust.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -2187,7 +2187,7 @@ A loop expression denotes an infinite loop;
21872187
see [Continue expressions](#continue-expressions) for continue expressions.
21882188

21892189
~~~~~~~~{.ebnf .gram}
2190-
loop_expr : "loop" [ ident ':' ] '{' block '}';
2190+
loop_expr : [ lifetime ':' ] "loop" '{' block '}';
21912191
~~~~~~~~
21922192

21932193
A `loop` expression may optionally have a _label_.
@@ -2198,7 +2198,7 @@ See [Break expressions](#break-expressions).
21982198
### Break expressions
21992199

22002200
~~~~~~~~{.ebnf .gram}
2201-
break_expr : "break" [ ident ];
2201+
break_expr : "break" [ lifetime ];
22022202
~~~~~~~~
22032203

22042204
A `break` expression has an optional `label`.
@@ -2211,7 +2211,7 @@ but must enclose it.
22112211
### Continue expressions
22122212

22132213
~~~~~~~~{.ebnf .gram}
2214-
continue_expr : "loop" [ ident ];
2214+
continue_expr : "loop" [ lifetime ];
22152215
~~~~~~~~
22162216

22172217
A continue expression, written `loop`, also has an optional `label`.

src/libsyntax/ext/asm.rs

+18-5
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,10 @@ pub fn expand_asm(cx: @ext_ctxt, sp: span, tts: &[ast::token_tree])
5656
let mut dialect = ast::asm_att;
5757

5858
let mut state = Asm;
59-
loop outer: {
59+
60+
// Not using labeled break to get us through one round of bootstrapping.
61+
let mut continue = true;
62+
while continue {
6063
match state {
6164
Asm => {
6265
asm = expr_to_str(cx, p.parse_expr(),
@@ -143,20 +146,30 @@ pub fn expand_asm(cx: @ext_ctxt, sp: span, tts: &[ast::token_tree])
143146
p.bump();
144147
match next_state(state) {
145148
Some(x) => x,
146-
None => break outer
149+
None => {
150+
continue = false;
151+
break
152+
}
147153
}
148154
} else if *p.token == token::MOD_SEP {
149155
p.bump();
150156
let s = match next_state(state) {
151157
Some(x) => x,
152-
None => break outer
158+
None => {
159+
continue = false;
160+
break
161+
}
153162
};
154163
match next_state(s) {
155164
Some(x) => x,
156-
None => break outer
165+
None => {
166+
continue = false;
167+
break
168+
}
157169
}
158170
} else if *p.token == token::EOF {
159-
break outer;
171+
continue = false;
172+
break;
160173
} else {
161174
state
162175
};

src/libsyntax/parse/parser.rs

+37-20
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,20 @@ pub impl Parser {
352352
self.token_is_keyword(&~"fn", tok)
353353
}
354354

355+
fn token_is_lifetime(&self, tok: &token::Token) -> bool {
356+
match *tok {
357+
token::LIFETIME(*) => true,
358+
_ => false,
359+
}
360+
}
361+
362+
fn get_lifetime(&self, tok: &token::Token) -> ast::ident {
363+
match *tok {
364+
token::LIFETIME(ref ident) => copy *ident,
365+
_ => self.bug(~"not a lifetime"),
366+
}
367+
}
368+
355369
// parse a ty_bare_fun type:
356370
fn parse_ty_bare_fn(&self) -> ty_
357371
{
@@ -1204,8 +1218,14 @@ pub impl Parser {
12041218
expr_do_body);
12051219
} else if self.eat_keyword(&~"while") {
12061220
return self.parse_while_expr();
1221+
} else if self.token_is_lifetime(&*self.token) {
1222+
let lifetime = self.get_lifetime(&*self.token);
1223+
self.bump();
1224+
self.expect(&token::COLON);
1225+
self.expect_keyword(&~"loop");
1226+
return self.parse_loop_expr(Some(lifetime));
12071227
} else if self.eat_keyword(&~"loop") {
1208-
return self.parse_loop_expr();
1228+
return self.parse_loop_expr(None);
12091229
} else if self.eat_keyword(&~"match") {
12101230
return self.parse_match_expr();
12111231
} else if self.eat_keyword(&~"unsafe") {
@@ -1263,8 +1283,10 @@ pub impl Parser {
12631283
ex = expr_ret(Some(e));
12641284
} else { ex = expr_ret(None); }
12651285
} else if self.eat_keyword(&~"break") {
1266-
if is_ident(&*self.token) {
1267-
ex = expr_break(Some(self.parse_ident()));
1286+
if self.token_is_lifetime(&*self.token) {
1287+
let lifetime = self.get_lifetime(&*self.token);
1288+
self.bump();
1289+
ex = expr_break(Some(lifetime));
12681290
} else {
12691291
ex = expr_break(None);
12701292
}
@@ -1961,37 +1983,32 @@ pub impl Parser {
19611983
return self.mk_expr(lo, hi, expr_while(cond, body));
19621984
}
19631985

1964-
fn parse_loop_expr(&self) -> @expr {
1986+
fn parse_loop_expr(&self, opt_ident: Option<ast::ident>) -> @expr {
19651987
// loop headers look like 'loop {' or 'loop unsafe {'
19661988
let is_loop_header =
19671989
*self.token == token::LBRACE
19681990
|| (is_ident(&*self.token)
19691991
&& self.look_ahead(1) == token::LBRACE);
1970-
// labeled loop headers look like 'loop foo: {'
1971-
let is_labeled_loop_header =
1972-
is_ident(&*self.token)
1973-
&& !self.is_any_keyword(&copy *self.token)
1974-
&& self.look_ahead(1) == token::COLON;
19751992

1976-
if is_loop_header || is_labeled_loop_header {
1993+
if is_loop_header {
19771994
// This is a loop body
1978-
let opt_ident;
1979-
if is_labeled_loop_header {
1980-
opt_ident = Some(self.parse_ident());
1981-
self.expect(&token::COLON);
1982-
} else {
1983-
opt_ident = None;
1984-
}
1985-
19861995
let lo = self.last_span.lo;
19871996
let body = self.parse_block_no_value();
19881997
let hi = body.span.hi;
19891998
return self.mk_expr(lo, hi, expr_loop(body, opt_ident));
19901999
} else {
19912000
// This is a 'continue' expression
2001+
if opt_ident.is_some() {
2002+
self.span_err(*self.last_span,
2003+
~"a label may not be used with a `loop` \
2004+
expression");
2005+
}
2006+
19922007
let lo = self.span.lo;
1993-
let ex = if is_ident(&*self.token) {
1994-
expr_again(Some(self.parse_ident()))
2008+
let ex = if self.token_is_lifetime(&*self.token) {
2009+
let lifetime = self.get_lifetime(&*self.token);
2010+
self.bump();
2011+
expr_again(Some(lifetime))
19952012
} else {
19962013
expr_again(None)
19972014
};

src/libsyntax/print/pprust.rs

+13-4
Original file line numberDiff line numberDiff line change
@@ -1217,12 +1217,13 @@ pub fn print_expr(s: @ps, expr: @ast::expr) {
12171217
print_block(s, blk);
12181218
}
12191219
ast::expr_loop(ref blk, opt_ident) => {
1220-
head(s, ~"loop");
1221-
space(s.s);
12221220
for opt_ident.each |ident| {
1221+
word(s.s, ~"'");
12231222
print_ident(s, *ident);
12241223
word_space(s, ~":");
12251224
}
1225+
head(s, ~"loop");
1226+
space(s.s);
12261227
print_block(s, blk);
12271228
}
12281229
ast::expr_match(expr, ref arms) => {
@@ -1370,12 +1371,20 @@ pub fn print_expr(s: @ps, expr: @ast::expr) {
13701371
ast::expr_break(opt_ident) => {
13711372
word(s.s, ~"break");
13721373
space(s.s);
1373-
for opt_ident.each |ident| { print_ident(s, *ident); space(s.s) }
1374+
for opt_ident.each |ident| {
1375+
word(s.s, ~"'");
1376+
print_ident(s, *ident);
1377+
space(s.s);
1378+
}
13741379
}
13751380
ast::expr_again(opt_ident) => {
13761381
word(s.s, ~"loop");
13771382
space(s.s);
1378-
for opt_ident.each |ident| { print_ident(s, *ident); space(s.s) }
1383+
for opt_ident.each |ident| {
1384+
word(s.s, ~"'");
1385+
print_ident(s, *ident);
1386+
space(s.s)
1387+
}
13791388
}
13801389
ast::expr_ret(result) => {
13811390
word(s.s, ~"return");

src/test/run-pass/issue-2216.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,17 @@
1111
pub fn main() {
1212
let mut x = 0;
1313

14-
loop foo: {
15-
loop bar: {
16-
loop quux: {
14+
'foo: loop {
15+
'bar: loop {
16+
'quux: loop {
1717
if 1 == 2 {
18-
break foo;
18+
break 'foo;
1919
}
2020
else {
21-
break bar;
21+
break 'bar;
2222
}
2323
}
24-
loop foo;
24+
loop 'foo;
2525
}
2626
x = 42;
2727
break;

src/test/run-pass/labeled-break.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@
1212
// xfail-test
1313

1414
pub fn main() {
15-
loop foo: {
15+
'foo: loop {
1616
loop {
17-
break foo;
17+
break 'foo;
1818
}
1919
}
2020
}

0 commit comments

Comments
 (0)