about summary refs log tree commit diff
path: root/src/libsyntax/parse
diff options
context:
space:
mode:
authorVadim Petrochenkov <vadim.petrochenkov@gmail.com>2016-03-06 15:54:44 +0300
committerVadim Petrochenkov <vadim.petrochenkov@gmail.com>2016-05-26 11:11:58 +0300
commitd69aeaf662c637b454e8c7a5ddbd69b4978ec211 (patch)
tree45d5b4b43bac7f04ea48136ffb02048278dcfb3a /src/libsyntax/parse
parentd5759a3417fa395d439f4283825504dd4f78dc87 (diff)
downloadrust-d69aeaf662c637b454e8c7a5ddbd69b4978ec211.tar.gz
rust-d69aeaf662c637b454e8c7a5ddbd69b4978ec211.zip
Implement `..` in tuple (struct) patterns
Diffstat (limited to 'src/libsyntax/parse')
-rw-r--r--src/libsyntax/parse/parser.rs65
1 files changed, 22 insertions, 43 deletions
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index fc62cee92fd..a4f12769b5c 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -954,25 +954,6 @@ impl<'a> Parser<'a> {
         Ok(result)
     }
 
-    /// Parse a sequence parameter of enum variant. For consistency purposes,
-    /// these should not be empty.
-    pub fn parse_enum_variant_seq<T, F>(&mut self,
-                                        bra: &token::Token,
-                                        ket: &token::Token,
-                                        sep: SeqSep,
-                                        f: F)
-                                        -> PResult<'a, Vec<T>> where
-        F: FnMut(&mut Parser<'a>) -> PResult<'a,  T>,
-    {
-        let result = self.parse_unspanned_seq(bra, ket, sep, f)?;
-        if result.is_empty() {
-            let last_span = self.last_span;
-            self.span_err(last_span,
-            "nullary enum variants are written with no trailing `( )`");
-        }
-        Ok(result)
-    }
-
     // NB: Do not use this function unless you actually plan to place the
     // spanned list in the AST.
     pub fn parse_seq<T, F>(&mut self,
@@ -3433,21 +3414,29 @@ impl<'a> Parser<'a> {
         };
     }
 
-    fn parse_pat_tuple_elements(&mut self) -> PResult<'a, Vec<P<Pat>>> {
+    fn parse_pat_tuple_elements(&mut self, unary_needs_comma: bool)
+                                -> PResult<'a, (Vec<P<Pat>>, Option<usize>)> {
         let mut fields = vec![];
-        if !self.check(&token::CloseDelim(token::Paren)) {
-            fields.push(self.parse_pat()?);
-            if self.look_ahead(1, |t| *t != token::CloseDelim(token::Paren)) {
-                while self.eat(&token::Comma) &&
-                      !self.check(&token::CloseDelim(token::Paren)) {
+        let mut ddpos = None;
+
+        while !self.check(&token::CloseDelim(token::Paren)) {
+            if ddpos.is_none() && self.eat(&token::DotDot) {
+                ddpos = Some(fields.len());
+                if self.eat(&token::Comma) {
+                    // `..` needs to be followed by `)` or `, pat`, `..,)` is disallowed.
                     fields.push(self.parse_pat()?);
                 }
+            } else {
+                fields.push(self.parse_pat()?);
             }
-            if fields.len() == 1 {
+
+            if !self.check(&token::CloseDelim(token::Paren)) ||
+                    (unary_needs_comma && fields.len() == 1 && ddpos.is_none()) {
                 self.expect(&token::Comma)?;
             }
         }
-        Ok(fields)
+
+        Ok((fields, ddpos))
     }
 
     fn parse_pat_vec_elements(
@@ -3626,9 +3615,9 @@ impl<'a> Parser<'a> {
           token::OpenDelim(token::Paren) => {
             // Parse (pat,pat,pat,...) as tuple pattern
             self.bump();
-            let fields = self.parse_pat_tuple_elements()?;
+            let (fields, ddpos) = self.parse_pat_tuple_elements(true)?;
             self.expect(&token::CloseDelim(token::Paren))?;
-            pat = PatKind::Tup(fields);
+            pat = PatKind::Tuple(fields, ddpos);
           }
           token::OpenDelim(token::Bracket) => {
             // Parse [pat,pat,...] as slice pattern
@@ -3713,20 +3702,10 @@ impl<'a> Parser<'a> {
                             return Err(self.fatal("unexpected `(` after qualified path"));
                         }
                         // Parse tuple struct or enum pattern
-                        if self.look_ahead(1, |t| *t == token::DotDot) {
-                            // This is a "top constructor only" pat
-                            self.bump();
-                            self.bump();
-                            self.expect(&token::CloseDelim(token::Paren))?;
-                            pat = PatKind::TupleStruct(path, None);
-                        } else {
-                            let args = self.parse_enum_variant_seq(
-                                &token::OpenDelim(token::Paren),
-                                &token::CloseDelim(token::Paren),
-                                SeqSep::trailing_allowed(token::Comma),
-                                |p| p.parse_pat())?;
-                            pat = PatKind::TupleStruct(path, Some(args));
-                        }
+                        self.bump();
+                        let (fields, ddpos) = self.parse_pat_tuple_elements(false)?;
+                        self.expect(&token::CloseDelim(token::Paren))?;
+                        pat = PatKind::TupleStruct(path, fields, ddpos)
                       }
                       _ => {
                         pat = match qself {