about summary refs log tree commit diff
path: root/src/libsyntax
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2013-03-11 04:27:48 -0700
committerbors <bors@rust-lang.org>2013-03-11 04:27:48 -0700
commit51cdca0bf0d3efc554c1815df9306ea10e881a14 (patch)
tree250354cf3cd8fe9af0de4e0d8434c99a50742c75 /src/libsyntax
parent58618fb8cfd791a930261ff68ae6bc77e0bc4412 (diff)
parent070137ce905d0177e8d112385f1d8dc7b2407006 (diff)
downloadrust-51cdca0bf0d3efc554c1815df9306ea10e881a14.tar.gz
rust-51cdca0bf0d3efc554c1815df9306ea10e881a14.zip
auto merge of #5122 : sanxiyn/rust/vec-match-tail-2, r=nikomatsakis
Incorporated @nikomatsakis's comments from #4748.

Fix #4635.
Diffstat (limited to 'src/libsyntax')
-rw-r--r--src/libsyntax/ast.rs4
-rw-r--r--src/libsyntax/ast_util.rs11
-rw-r--r--src/libsyntax/fold.rs7
-rw-r--r--src/libsyntax/parse/parser.rs40
-rw-r--r--src/libsyntax/print/pprust.rs16
-rw-r--r--src/libsyntax/visit.rs9
6 files changed, 56 insertions, 31 deletions
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 3782208eb85..f3e73823f69 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -309,7 +309,9 @@ pub enum pat_ {
     pat_region(@pat), // borrowed pointer pattern
     pat_lit(@expr),
     pat_range(@expr, @expr),
-    pat_vec(~[@pat], Option<@pat>)
+    // [a, b, ..i, y, z] is represented as
+    // pat_vec(~[a, b], Some(i), ~[y, z])
+    pat_vec(~[@pat], Option<@pat>, ~[@pat])
 }
 
 #[auto_encode]
diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs
index 686ae3900ff..7b0e72e6e95 100644
--- a/src/libsyntax/ast_util.rs
+++ b/src/libsyntax/ast_util.rs
@@ -533,12 +533,15 @@ pub fn walk_pat(pat: @pat, it: fn(@pat)) {
         pat_box(s) | pat_uniq(s) | pat_region(s) => {
             walk_pat(s, it)
         }
-        pat_vec(ref elts, ref tail) => {
-            for elts.each |p| {
+        pat_vec(ref before, ref slice, ref after) => {
+            for before.each |p| {
                 walk_pat(*p, it)
             }
-            for tail.each |tail| {
-                walk_pat(*tail, it)
+            for slice.each |p| {
+                walk_pat(*p, it)
+            }
+            for after.each |p| {
+                walk_pat(*p, it)
             }
         }
         pat_wild | pat_lit(_) | pat_range(_, _) | pat_ident(_, _, _) |
diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs
index b8371c9e8d9..2a5fe788770 100644
--- a/src/libsyntax/fold.rs
+++ b/src/libsyntax/fold.rs
@@ -416,10 +416,11 @@ pub fn noop_fold_pat(p: &pat_, fld: @ast_fold) -> pat_ {
         pat_range(e1, e2) => {
             pat_range(fld.fold_expr(e1), fld.fold_expr(e2))
         },
-        pat_vec(ref elts, ref tail) => {
+        pat_vec(ref before, ref slice, ref after) => {
             pat_vec(
-                elts.map(|x| fld.fold_pat(*x)),
-                tail.map(|tail| fld.fold_pat(*tail))
+                before.map(|x| fld.fold_pat(*x)),
+                slice.map(|x| fld.fold_pat(*x)),
+                after.map(|x| fld.fold_pat(*x))
             )
         }
     }
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index adcaa006247..38cd09abad4 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -2024,23 +2024,28 @@ pub impl Parser {
     fn parse_pat_vec_elements(
         &self,
         refutable: bool
-    ) -> (~[@pat], Option<@pat>) {
-        let mut elements = ~[];
-        let mut tail = None;
+    ) -> (~[@pat], Option<@pat>, ~[@pat]) {
+        let mut before = ~[];
+        let mut slice = None;
+        let mut after = ~[];
         let mut first = true;
+        let mut before_slice = true;
 
         while *self.token != token::RBRACKET {
             if first { first = false; }
             else { self.expect(&token::COMMA); }
 
-            let mut is_tail = false;
-            if *self.token == token::DOTDOT {
-                self.bump();
-                is_tail = true;
+            let mut is_slice = false;
+            if before_slice {
+                if *self.token == token::DOTDOT {
+                    self.bump();
+                    is_slice = true;
+                    before_slice = false;
+                }
             }
 
             let subpat = self.parse_pat(refutable);
-            if is_tail {
+            if is_slice {
                 match subpat {
                     @ast::pat { node: pat_wild, _ } => (),
                     @ast::pat { node: pat_ident(_, _, _), _ } => (),
@@ -2048,13 +2053,17 @@ pub impl Parser {
                         span, ~"expected an identifier or `_`"
                     )
                 }
-                tail = Some(subpat);
-                break;
+                slice = Some(subpat);
+            } else {
+                if before_slice {
+                    before.push(subpat);
+                } else {
+                    after.push(subpat);
+                }
             }
-
-            elements.push(subpat);
         }
-        return (elements, tail);
+
+        (before, slice, after)
     }
 
     fn parse_pat_fields(&self, refutable: bool) -> (~[ast::field_pat], bool) {
@@ -2208,10 +2217,11 @@ pub impl Parser {
           }
           token::LBRACKET => {
             self.bump();
-            let (elements, tail) = self.parse_pat_vec_elements(refutable);
+            let (before, slice, after) =
+                self.parse_pat_vec_elements(refutable);
             hi = self.span.hi;
             self.expect(&token::RBRACKET);
-            pat = ast::pat_vec(elements, tail);
+            pat = ast::pat_vec(before, slice, after);
           }
           copy tok => {
             if !is_ident_or_path(&tok)
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index 3744b7a8f6c..c81c1c8bd0e 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -1609,13 +1609,19 @@ pub fn print_pat(s: @ps, &&pat: @ast::pat, refutable: bool) {
         word(s.s, ~"..");
         print_expr(s, end);
       }
-      ast::pat_vec(elts, tail) => {
+      ast::pat_vec(before, slice, after) => {
         word(s.s, ~"[");
-        commasep(s, inconsistent, elts, |s, p| print_pat(s, p, refutable));
-        for tail.each |tail| {
-            if vec::len(elts) != 0u { word_space(s, ~","); }
+        do commasep(s, inconsistent, before) |s, p| {
+            print_pat(s, p, refutable);
+        }
+        for slice.each |&p| {
+            if !before.is_empty() { word_space(s, ~","); }
             word(s.s, ~"..");
-            print_pat(s, *tail, refutable);
+            print_pat(s, p, refutable);
+            if !after.is_empty() { word_space(s, ~","); }
+        }
+        do commasep(s, inconsistent, after) |s, p| {
+            print_pat(s, p, refutable);
         }
         word(s.s, ~"]");
       }
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index 6048256b90b..f04894729bd 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -287,11 +287,14 @@ pub fn visit_pat<E>(p: @pat, e: E, v: vt<E>) {
             (v.visit_expr)(e2, e, v);
         }
         pat_wild => (),
-        pat_vec(ref elts, ref tail) => {
-            for elts.each |elt| {
+        pat_vec(ref before, ref slice, ref after) => {
+            for before.each |elt| {
+                (v.visit_pat)(*elt, e, v);
+            }
+            for slice.each |elt| {
                 (v.visit_pat)(*elt, e, v);
             }
-            for tail.each |tail| {
+            for after.each |tail| {
                 (v.visit_pat)(*tail, e, v);
             }
         }