about summary refs log tree commit diff
path: root/src/libsyntax
diff options
context:
space:
mode:
authorPatrick Walton <pcwalton@mimiga.net>2012-08-14 19:20:56 -0700
committerPatrick Walton <pcwalton@mimiga.net>2012-08-15 16:20:34 -0700
commitbdb206f2855cc6f7d3d79379633f7429b7327fec (patch)
tree05764770b6b2729780bb1289d3c2db55d1cc55c5 /src/libsyntax
parentd54db12155257787797cd9c7eaf06a215ff516e5 (diff)
downloadrust-bdb206f2855cc6f7d3d79379633f7429b7327fec.tar.gz
rust-bdb206f2855cc6f7d3d79379633f7429b7327fec.zip
rustc: Parse labeled loop, break, and again
Diffstat (limited to 'src/libsyntax')
-rw-r--r--src/libsyntax/ast.rs9
-rw-r--r--src/libsyntax/ast_util.rs2
-rw-r--r--src/libsyntax/fold.rs10
-rw-r--r--src/libsyntax/parse/classify.rs2
-rw-r--r--src/libsyntax/parse/parser.rs22
-rw-r--r--src/libsyntax/print/pprust.rs15
-rw-r--r--src/libsyntax/visit.rs6
7 files changed, 48 insertions, 18 deletions
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 39e116990dd..a09bd073c44 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -89,7 +89,8 @@ enum def {
               node_id /* expr node that creates the closure */),
     def_class(def_id, bool /* has constructor */),
     def_typaram_binder(node_id), /* class, impl or trait that has ty params */
-    def_region(node_id)
+    def_region(node_id),
+    def_label(node_id)
 }
 
 // The set of meta_items that define the compilation environment of the crate,
@@ -316,7 +317,7 @@ enum expr_ {
     /* Conditionless loop (can be exited with break, cont, ret, or fail)
        Same semantics as while(true) { body }, but typestate knows that the
        (implicit) condition is always true. */
-    expr_loop(blk),
+    expr_loop(blk, option<ident>),
     expr_match(@expr, ~[arm], alt_mode),
     expr_fn(proto, fn_decl, blk, capture_clause),
     expr_fn_block(fn_decl, blk, capture_clause),
@@ -339,8 +340,8 @@ enum expr_ {
     expr_path(@path),
     expr_addr_of(mutability, @expr),
     expr_fail(option<@expr>),
-    expr_break,
-    expr_again,
+    expr_break(option<ident>),
+    expr_again(option<ident>),
     expr_ret(option<@expr>),
     expr_log(int, @expr, @expr),
 
diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs
index 6ea6ecb1ba3..4a6f8b1e77a 100644
--- a/src/libsyntax/ast_util.rs
+++ b/src/libsyntax/ast_util.rs
@@ -61,7 +61,7 @@ pure fn def_id_of_def(d: def) -> def_id {
       }
       def_arg(id, _) | def_local(id, _) | def_self(id) |
       def_upvar(id, _, _) | def_binding(id, _) | def_region(id)
-      | def_typaram_binder(id) => {
+      | def_typaram_binder(id) | def_label(id) => {
         local_def(id)
       }
 
diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs
index 5cce86fd458..5bd35490f0e 100644
--- a/src/libsyntax/fold.rs
+++ b/src/libsyntax/fold.rs
@@ -448,8 +448,9 @@ fn noop_fold_expr(e: expr_, fld: ast_fold) -> expr_ {
           expr_while(cond, body) => {
             expr_while(fld.fold_expr(cond), fld.fold_block(body))
           }
-          expr_loop(body) => {
-              expr_loop(fld.fold_block(body))
+          expr_loop(body, opt_ident) => {
+              expr_loop(fld.fold_block(body),
+                        option::map(opt_ident, |x| fld.fold_ident(x)))
           }
           expr_match(expr, arms, mode) => {
             expr_match(fld.fold_expr(expr),
@@ -492,7 +493,10 @@ fn noop_fold_expr(e: expr_, fld: ast_fold) -> expr_ {
           }
           expr_path(pth) => expr_path(fld.fold_path(pth)),
           expr_fail(e) => expr_fail(option::map(e, |x| fld.fold_expr(x))),
-          expr_break | expr_again => copy e,
+          expr_break(opt_ident) =>
+            expr_break(option::map(opt_ident, |x| fld.fold_ident(x))),
+          expr_again(opt_ident) =>
+            expr_again(option::map(opt_ident, |x| fld.fold_ident(x))),
           expr_ret(e) => expr_ret(option::map(e, |x| fld.fold_expr(x))),
           expr_log(i, lv, e) => expr_log(i, fld.fold_expr(lv),
                                          fld.fold_expr(e)),
diff --git a/src/libsyntax/parse/classify.rs b/src/libsyntax/parse/classify.rs
index d8ae8044370..1fd9dc2c23c 100644
--- a/src/libsyntax/parse/classify.rs
+++ b/src/libsyntax/parse/classify.rs
@@ -7,7 +7,7 @@ import ast_util::operator_prec;
 fn expr_requires_semi_to_be_stmt(e: @ast::expr) -> bool {
     match e.node {
       ast::expr_if(_, _, _) | ast::expr_match(_, _, _) | ast::expr_block(_)
-      | ast::expr_while(_, _) | ast::expr_loop(_)
+      | ast::expr_while(_, _) | ast::expr_loop(_, _)
       | ast::expr_call(_, _, true) => false,
       _ => true
     }
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 642cdaa8fab..977e75362f8 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -939,10 +939,18 @@ class parser {
                 ex = expr_ret(some(e));
             } else { ex = expr_ret(none); }
         } else if self.eat_keyword(~"break") {
-            ex = expr_break;
+            if is_ident(self.token) {
+                ex = expr_break(some(self.parse_ident()));
+            } else {
+                ex = expr_break(none);
+            }
             hi = self.span.hi;
         } else if self.eat_keyword(~"again") {
-            ex = expr_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();
@@ -1585,10 +1593,18 @@ class parser {
     }
 
     fn parse_loop_expr() -> @expr {
+        let opt_ident;
+        if is_ident(self.token) {
+            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));
+        return self.mk_expr(lo, hi, expr_loop(body, opt_ident));
     }
 
     // For distingishing between record literals and blocks
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index 39bc18529c9..49ded036e04 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -1142,9 +1142,10 @@ fn print_expr(s: ps, &&expr: @ast::expr) {
         space(s.s);
         print_block(s, blk);
       }
-      ast::expr_loop(blk) => {
+      ast::expr_loop(blk, opt_ident) => {
         head(s, ~"loop");
         space(s.s);
+        option::iter(opt_ident, |ident| word_space(s, *ident));
         print_block(s, blk);
       }
       ast::expr_match(expr, arms, mode) => {
@@ -1310,8 +1311,16 @@ fn print_expr(s: ps, &&expr: @ast::expr) {
           _ => ()
         }
       }
-      ast::expr_break => word(s.s, ~"break"),
-      ast::expr_again => word(s.s, ~"again"),
+      ast::expr_break(opt_ident) => {
+        word(s.s, ~"break");
+        space(s.s);
+        option::iter(opt_ident, |ident| word_space(s, *ident));
+      }
+      ast::expr_again(opt_ident) => {
+        word(s.s, ~"again");
+        space(s.s);
+        option::iter(opt_ident, |ident| word_space(s, *ident));
+      }
       ast::expr_ret(result) => {
         word(s.s, ~"return");
         match result {
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index 1903a688aea..93d253d2163 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -422,7 +422,7 @@ fn visit_expr<E>(ex: @expr, e: E, v: vt<E>) {
         visit_expr_opt(eo, e, v);
       }
       expr_while(x, b) => { v.visit_expr(x, e, v); v.visit_block(b, e, v); }
-      expr_loop(b) => v.visit_block(b, e, v),
+      expr_loop(b, _) => v.visit_block(b, e, v),
       expr_match(x, arms, _) => {
         v.visit_expr(x, e, v);
         for arms.each |a| { v.visit_arm(a, e, v); }
@@ -452,8 +452,8 @@ fn visit_expr<E>(ex: @expr, e: E, v: vt<E>) {
       expr_index(a, b) => { v.visit_expr(a, e, v); v.visit_expr(b, e, v); }
       expr_path(p) => visit_path(p, e, v),
       expr_fail(eo) => visit_expr_opt(eo, e, v),
-      expr_break => (),
-      expr_again => (),
+      expr_break(_) => (),
+      expr_again(_) => (),
       expr_ret(eo) => visit_expr_opt(eo, e, v),
       expr_log(_, lv, x) => {
         v.visit_expr(lv, e, v);