about summary refs log tree commit diff
path: root/src/rustc/syntax/parse
diff options
context:
space:
mode:
authorMarijn Haverbeke <marijnh@gmail.com>2012-03-26 16:09:27 +0200
committerMarijn Haverbeke <marijnh@gmail.com>2012-03-27 09:27:31 +0200
commitf6e3738b9c824e56f561e75f0ff11cf3a0d2dd09 (patch)
treeab6624224bc83dc5edc4561b6d3d81860ecf6cef /src/rustc/syntax/parse
parent9638e7fece158fd084a1d1f70970d716e9979f96 (diff)
downloadrust-f6e3738b9c824e56f561e75f0ff11cf3a0d2dd09.tar.gz
rust-f6e3738b9c824e56f561e75f0ff11cf3a0d2dd09.zip
Support an alternate for syntax that calls a higher-order function
The last argument of the call must be a block, and the type of this
argument must a function returning bool. `break` and `cont` are
supported in the body of the block, and return `false` or `true` from
the function. When the end of the function is reached, `true` is
implicitly returned.

    for vec::all([1, 2, 3]) {|elt|
        if elt == 2 { break; }
        log(error, elt);
    }

Issue #1619
Diffstat (limited to 'src/rustc/syntax/parse')
-rw-r--r--src/rustc/syntax/parse/parser.rs38
1 files changed, 31 insertions, 7 deletions
diff --git a/src/rustc/syntax/parse/parser.rs b/src/rustc/syntax/parse/parser.rs
index 78d8d2b6133..a898ee840be 100644
--- a/src/rustc/syntax/parse/parser.rs
+++ b/src/rustc/syntax/parse/parser.rs
@@ -1403,13 +1403,37 @@ fn parse_else_expr(p: parser) -> @ast::expr {
 }
 
 fn parse_for_expr(p: parser) -> @ast::expr {
-    let lo = p.last_span.lo;
-    let decl = parse_local(p, false, false);
-    expect_word(p, "in");
-    let seq = parse_expr(p);
-    let body = parse_block_no_value(p);
-    let mut hi = body.span.hi;
-    ret mk_expr(p, lo, hi, ast::expr_for(decl, seq, body));
+    let lo = p.last_span;
+    // FIXME remove this kludge after migration and snapshotting (#1619)
+    let new_style = alt p.token {
+      token::IDENT(_, false) { alt p.look_ahead(1u) {
+        token::DOT | token::LPAREN { true }
+        _ { false }
+      } }
+      token::IDENT(_, true) { true }
+      _ { false }
+    };
+    if new_style {
+        let call = parse_expr(p);
+        alt call.node {
+          ast::expr_call(f, args, true) {
+            let b_arg = vec::last(args);
+            let last = mk_expr(p, b_arg.span.lo, b_arg.span.hi,
+                               ast::expr_loop_body(b_arg));
+            @{node: ast::expr_call(f, vec::init(args) + [last], true)
+              with *call}
+          }
+          _ {
+            p.span_fatal(lo, "`for` must be followed by a block call");
+          }
+        }
+    } else {
+        let decl = parse_local(p, false, false);
+        expect_word(p, "in");
+        let seq = parse_expr(p);
+        let body = parse_block_no_value(p);
+        mk_expr(p, lo.lo, body.span.hi, ast::expr_for(decl, seq, body))
+    }
 }
 
 fn parse_while_expr(p: parser) -> @ast::expr {