about summary refs log tree commit diff
path: root/src/comp/syntax
diff options
context:
space:
mode:
authorMarijn Haverbeke <marijnh@gmail.com>2011-08-22 14:38:48 +0200
committerMarijn Haverbeke <marijnh@gmail.com>2011-08-22 17:49:31 +0200
commit7d08678b740d779d9f0e1e6d15d7cf6ad4e1b57a (patch)
tree71a73aa6e74449cab2048957f79a5ca05138e22b /src/comp/syntax
parenta2466233b4217cc8da4d2ebcd5f7c0b11db5b861 (diff)
downloadrust-7d08678b740d779d9f0e1e6d15d7cf6ad4e1b57a.tar.gz
rust-7d08678b740d779d9f0e1e6d15d7cf6ad4e1b57a.zip
Implement pattern guards
The syntax is

    alt x {
        mypat where mycond { ... }
    }

The condition may refer to any of the variables bound by the pattern.
When a guard fails, pattern-matching continues with the next pattern.

Closes #857
Diffstat (limited to 'src/comp/syntax')
-rw-r--r--src/comp/syntax/ast.rs2
-rw-r--r--src/comp/syntax/fold.rs4
-rw-r--r--src/comp/syntax/parse/parser.rs6
-rw-r--r--src/comp/syntax/print/pprust.rs8
-rw-r--r--src/comp/syntax/visit.rs1
5 files changed, 18 insertions, 3 deletions
diff --git a/src/comp/syntax/ast.rs b/src/comp/syntax/ast.rs
index 80d327b119b..2537aa95f36 100644
--- a/src/comp/syntax/ast.rs
+++ b/src/comp/syntax/ast.rs
@@ -267,7 +267,7 @@ type decl = spanned<decl_>;
 
 tag decl_ { decl_local([@local]); decl_item(@item); }
 
-type arm = {pats: [@pat], body: blk};
+type arm = {pats: [@pat], guard: option::t<@expr>, body: blk};
 
 type field_ = {mut: mutability, ident: ident, expr: @expr};
 
diff --git a/src/comp/syntax/fold.rs b/src/comp/syntax/fold.rs
index ef04e66d756..a91b2f31814 100644
--- a/src/comp/syntax/fold.rs
+++ b/src/comp/syntax/fold.rs
@@ -269,7 +269,9 @@ fn noop_fold_stmt(s: &stmt_, fld: ast_fold) -> stmt_ {
 }
 
 fn noop_fold_arm(a: &arm, fld: ast_fold) -> arm {
-    ret {pats: vec::map(fld.fold_pat, a.pats), body: fld.fold_block(a.body)};
+    ret {pats: vec::map(fld.fold_pat, a.pats),
+         guard: option::map(fld.fold_expr, a.guard),
+         body: fld.fold_block(a.body)};
 }
 
 fn noop_fold_pat(p: &pat_, fld: ast_fold) -> pat_ {
diff --git a/src/comp/syntax/parse/parser.rs b/src/comp/syntax/parse/parser.rs
index d20f345b3af..b20c7905013 100644
--- a/src/comp/syntax/parse/parser.rs
+++ b/src/comp/syntax/parse/parser.rs
@@ -1360,8 +1360,12 @@ fn parse_alt_expr(p: &parser) -> @ast::expr {
     let arms: [ast::arm] = [];
     while p.peek() != token::RBRACE {
         let pats = parse_pats(p);
+        let guard = none;
+        if eat_word(p, "when") {
+            guard = some(parse_expr(p));
+        }
         let blk = parse_block(p);
-        arms += [{pats: pats, body: blk}];
+        arms += [{pats: pats, guard: guard, body: blk}];
     }
     let hi = p.get_hi_pos();
     p.bump();
diff --git a/src/comp/syntax/print/pprust.rs b/src/comp/syntax/print/pprust.rs
index c0e38a3b40e..8ecbfd58405 100644
--- a/src/comp/syntax/print/pprust.rs
+++ b/src/comp/syntax/print/pprust.rs
@@ -905,6 +905,14 @@ fn print_expr(s: &ps, expr: &@ast::expr) {
                 print_pat(s, p);
             }
             space(s.s);
+            alt arm.guard {
+              some(e) {
+                word_space(s, "when");
+                print_expr(s, e);
+                space(s.s);
+              }
+              none. {}
+            }
             print_possibly_embedded_block(s, arm.body, block_normal,
                                           alt_indent_unit);
         }
diff --git a/src/comp/syntax/visit.rs b/src/comp/syntax/visit.rs
index 350dfc3dd44..d69104a7010 100644
--- a/src/comp/syntax/visit.rs
+++ b/src/comp/syntax/visit.rs
@@ -332,6 +332,7 @@ fn visit_expr<E>(ex: &@expr, e: &E, v: &vt<E>) {
 
 fn visit_arm<E>(a: &arm, e: &E, v: &vt<E>) {
     for p: @pat in a.pats { v.visit_pat(p, e, v); }
+    visit_expr_opt(a.guard, e, v);
     v.visit_block(a.body, e, v);
 }