Skip to content

Commit 670ab8a

Browse files
committed
librustc: Change labels to use the lifetime notation '.
1 parent 876483d commit 670ab8a

File tree

6 files changed

+79
-40
lines changed

6 files changed

+79
-40
lines changed

doc/rust.md

Lines changed: 3 additions & 3 deletions
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

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,10 @@ pub fn expand_asm(cx: @ext_ctxt, sp: span, tts: &[ast::token_tree])
5252
let mut dialect = ast::asm_att;
5353

5454
let mut state = Asm;
55-
loop outer: {
55+
56+
// Not using labeled break to get us through one round of bootstrapping.
57+
let mut continue = true;
58+
while continue {
5659
match state {
5760
Asm => {
5861
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])
139142
p.bump();
140143
match next_state(state) {
141144
Some(x) => x,
142-
None => break outer
145+
None => {
146+
continue = false;
147+
break
148+
}
143149
}
144150
} else if *p.token == token::MOD_SEP {
145151
p.bump();
146152
let s = match next_state(state) {
147153
Some(x) => x,
148-
None => break outer
154+
None => {
155+
continue = false;
156+
break
157+
}
149158
};
150159
match next_state(s) {
151160
Some(x) => x,
152-
None => break outer
161+
None => {
162+
continue = false;
163+
break
164+
}
153165
}
154166
} else if *p.token == token::EOF {
155-
break outer;
167+
continue = false;
168+
break;
156169
} else {
157170
state
158171
};

src/libsyntax/parse/parser.rs

Lines changed: 37 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,20 @@ pub impl Parser {
348348
self.token_is_keyword(&~"fn", tok)
349349
}
350350

351+
fn token_is_lifetime(&self, tok: &token::Token) -> bool {
352+
match *tok {
353+
token::LIFETIME(*) => true,
354+
_ => false,
355+
}
356+
}
357+
358+
fn get_lifetime(&self, tok: &token::Token) -> ast::ident {
359+
match *tok {
360+
token::LIFETIME(ref ident) => copy *ident,
361+
_ => self.bug(~"not a lifetime"),
362+
}
363+
}
364+
351365
// parse a ty_bare_fun type:
352366
fn parse_ty_bare_fn(&self) -> ty_
353367
{
@@ -1228,8 +1242,14 @@ pub impl Parser {
12281242
expr_do_body);
12291243
} else if self.eat_keyword(&~"while") {
12301244
return self.parse_while_expr();
1245+
} else if self.token_is_lifetime(&*self.token) {
1246+
let lifetime = self.get_lifetime(&*self.token);
1247+
self.bump();
1248+
self.expect(&token::COLON);
1249+
self.expect_keyword(&~"loop");
1250+
return self.parse_loop_expr(Some(lifetime));
12311251
} else if self.eat_keyword(&~"loop") {
1232-
return self.parse_loop_expr();
1252+
return self.parse_loop_expr(None);
12331253
} else if self.eat_keyword(&~"match") {
12341254
return self.parse_match_expr();
12351255
} else if self.eat_keyword(&~"unsafe") {
@@ -1290,8 +1310,10 @@ pub impl Parser {
12901310
} else { ex = expr_ret(None); }
12911311
} else if self.eat_keyword(&~"break") {
12921312
// BREAK expression
1293-
if is_ident(&*self.token) {
1294-
ex = expr_break(Some(self.parse_ident()));
1313+
if self.token_is_lifetime(&*self.token) {
1314+
let lifetime = self.get_lifetime(&*self.token);
1315+
self.bump();
1316+
ex = expr_break(Some(lifetime));
12951317
} else {
12961318
ex = expr_break(None);
12971319
}
@@ -1995,37 +2017,32 @@ pub impl Parser {
19952017
return self.mk_expr(lo, hi, expr_while(cond, body));
19962018
}
19972019

1998-
fn parse_loop_expr(&self) -> @expr {
2020+
fn parse_loop_expr(&self, opt_ident: Option<ast::ident>) -> @expr {
19992021
// loop headers look like 'loop {' or 'loop unsafe {'
20002022
let is_loop_header =
20012023
*self.token == token::LBRACE
20022024
|| (is_ident(&*self.token)
20032025
&& self.look_ahead(1) == token::LBRACE);
2004-
// labeled loop headers look like 'loop foo: {'
2005-
let is_labeled_loop_header =
2006-
is_ident(&*self.token)
2007-
&& !self.is_any_keyword(&copy *self.token)
2008-
&& self.look_ahead(1) == token::COLON;
20092026

2010-
if is_loop_header || is_labeled_loop_header {
2027+
if is_loop_header {
20112028
// This is a loop body
2012-
let opt_ident;
2013-
if is_labeled_loop_header {
2014-
opt_ident = Some(self.parse_ident());
2015-
self.expect(&token::COLON);
2016-
} else {
2017-
opt_ident = None;
2018-
}
2019-
20202029
let lo = self.last_span.lo;
20212030
let body = self.parse_block();
20222031
let hi = body.span.hi;
20232032
return self.mk_expr(lo, hi, expr_loop(body, opt_ident));
20242033
} else {
20252034
// This is a 'continue' expression
2035+
if opt_ident.is_some() {
2036+
self.span_err(*self.last_span,
2037+
~"a label may not be used with a `loop` \
2038+
expression");
2039+
}
2040+
20262041
let lo = self.span.lo;
2027-
let ex = if is_ident(&*self.token) {
2028-
expr_again(Some(self.parse_ident()))
2042+
let ex = if self.token_is_lifetime(&*self.token) {
2043+
let lifetime = self.get_lifetime(&*self.token);
2044+
self.bump();
2045+
expr_again(Some(lifetime))
20292046
} else {
20302047
expr_again(None)
20312048
};

src/libsyntax/print/pprust.rs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1210,12 +1210,13 @@ pub fn print_expr(s: @ps, expr: @ast::expr) {
12101210
print_block(s, blk);
12111211
}
12121212
ast::expr_loop(ref blk, opt_ident) => {
1213-
head(s, ~"loop");
1214-
space(s.s);
12151213
for opt_ident.each |ident| {
1214+
word(s.s, ~"'");
12161215
print_ident(s, *ident);
12171216
word_space(s, ~":");
12181217
}
1218+
head(s, ~"loop");
1219+
space(s.s);
12191220
print_block(s, blk);
12201221
}
12211222
ast::expr_match(expr, ref arms) => {
@@ -1363,12 +1364,20 @@ pub fn print_expr(s: @ps, expr: @ast::expr) {
13631364
ast::expr_break(opt_ident) => {
13641365
word(s.s, ~"break");
13651366
space(s.s);
1366-
for opt_ident.each |ident| { print_ident(s, *ident); space(s.s) }
1367+
for opt_ident.each |ident| {
1368+
word(s.s, ~"'");
1369+
print_ident(s, *ident);
1370+
space(s.s);
1371+
}
13671372
}
13681373
ast::expr_again(opt_ident) => {
13691374
word(s.s, ~"loop");
13701375
space(s.s);
1371-
for opt_ident.each |ident| { print_ident(s, *ident); space(s.s) }
1376+
for opt_ident.each |ident| {
1377+
word(s.s, ~"'");
1378+
print_ident(s, *ident);
1379+
space(s.s)
1380+
}
13721381
}
13731382
ast::expr_ret(result) => {
13741383
word(s.s, ~"return");

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

Lines changed: 6 additions & 6 deletions
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

Lines changed: 2 additions & 2 deletions
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)