about summary refs log tree commit diff
path: root/src/libsyntax/parse/parser.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/libsyntax/parse/parser.rs')
-rw-r--r--src/libsyntax/parse/parser.rs43
1 files changed, 25 insertions, 18 deletions
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 9e2829e6380..bd995d44fea 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -86,6 +86,7 @@ use std::collections::HashSet;
 use std::mem::replace;
 use std::rc::Rc;
 use std::gc::{Gc, GC};
+use std::iter;
 
 #[allow(non_camel_case_types)]
 #[deriving(PartialEq)]
@@ -762,20 +763,26 @@ impl<'a> Parser<'a> {
                                   sep: Option<token::Token>,
                                   f: |&mut Parser| -> T)
                                   -> OwnedSlice<T> {
-        let mut first = true;
         let mut v = Vec::new();
-        while self.token != token::GT
-            && self.token != token::BINOP(token::SHR)
-            && self.token != token::GE
-            && self.token != token::BINOPEQ(token::SHR) {
-            match sep {
-              Some(ref t) => {
-                if first { first = false; }
-                else { self.expect(t); }
-              }
-              _ => ()
+        // This loop works by alternating back and forth between parsing types
+        // and commas.  For example, given a string `A, B,>`, the parser would
+        // first parse `A`, then a comma, then `B`, then a comma. After that it
+        // would encounter a `>` and stop. This lets the parser handle trailing
+        // commas in generic parameters, because it can stop either after
+        // parsing a type or after parsing a comma.
+        for i in iter::count(0u, 1) {
+            if self.token == token::GT
+                || self.token == token::BINOP(token::SHR)
+                || self.token == token::GE
+                || self.token == token::BINOPEQ(token::SHR) {
+                break;
+            }
+
+            if i % 2 == 0 {
+                v.push(f(self));
+            } else {
+                sep.as_ref().map(|t| self.expect(t));
             }
-            v.push(f(self));
         }
         return OwnedSlice::from_vec(v);
     }
@@ -2266,7 +2273,7 @@ impl<'a> Parser<'a> {
                             let mut es = self.parse_unspanned_seq(
                                 &token::LPAREN,
                                 &token::RPAREN,
-                                seq_sep_trailing_disallowed(token::COMMA),
+                                seq_sep_trailing_allowed(token::COMMA),
                                 |p| p.parse_expr()
                             );
                             hi = self.last_span.hi;
@@ -3196,7 +3203,7 @@ impl<'a> Parser<'a> {
                                 args = self.parse_enum_variant_seq(
                                     &token::LPAREN,
                                     &token::RPAREN,
-                                    seq_sep_trailing_disallowed(token::COMMA),
+                                    seq_sep_trailing_allowed(token::COMMA),
                                     |p| p.parse_pat()
                                 );
                                 pat = PatEnum(enum_path, Some(args));
@@ -4068,7 +4075,7 @@ impl<'a> Parser<'a> {
             match self.token {
                 token::COMMA => {
                     self.bump();
-                    let sep = seq_sep_trailing_disallowed(token::COMMA);
+                    let sep = seq_sep_trailing_allowed(token::COMMA);
                     let mut fn_inputs = self.parse_seq_to_before_end(
                         &token::RPAREN,
                         sep,
@@ -4091,7 +4098,7 @@ impl<'a> Parser<'a> {
 
         let fn_inputs = match explicit_self {
             SelfStatic =>  {
-                let sep = seq_sep_trailing_disallowed(token::COMMA);
+                let sep = seq_sep_trailing_allowed(token::COMMA);
                 self.parse_seq_to_before_end(&token::RPAREN, sep, parse_arg_fn)
             }
             SelfValue(id) => parse_remaining_arguments!(id),
@@ -4128,7 +4135,7 @@ impl<'a> Parser<'a> {
                     self.parse_optional_unboxed_closure_kind();
                 let args = self.parse_seq_to_before_end(
                     &token::BINOP(token::OR),
-                    seq_sep_trailing_disallowed(token::COMMA),
+                    seq_sep_trailing_allowed(token::COMMA),
                     |p| p.parse_fn_block_arg()
                 );
                 self.bump();
@@ -4950,7 +4957,7 @@ impl<'a> Parser<'a> {
                 let arg_tys = self.parse_enum_variant_seq(
                     &token::LPAREN,
                     &token::RPAREN,
-                    seq_sep_trailing_disallowed(token::COMMA),
+                    seq_sep_trailing_allowed(token::COMMA),
                     |p| p.parse_ty(true)
                 );
                 for ty in arg_tys.move_iter() {