@@ -86,6 +86,7 @@ use std::collections::HashSet;
86
86
use std::mem::replace;
87
87
use std::rc::Rc;
88
88
use std::gc::{Gc, GC};
89
+ use std::iter;
89
90
90
91
#[allow(non_camel_case_types)]
91
92
#[deriving(PartialEq)]
@@ -762,20 +763,26 @@ impl<'a> Parser<'a> {
762
763
sep: Option<token::Token>,
763
764
f: |&mut Parser| -> T)
764
765
-> OwnedSlice<T> {
765
- let mut first = true;
766
766
let mut v = Vec::new();
767
- while self.token != token::GT
768
- && self.token != token::BINOP(token::SHR)
769
- && self.token != token::GE
770
- && self.token != token::BINOPEQ(token::SHR) {
771
- match sep {
772
- Some(ref t) => {
773
- if first { first = false; }
774
- else { self.expect(t); }
775
- }
776
- _ => ()
767
+ // This loop works by alternating back and forth between parsing types
768
+ // and commas. For example, given a string `A, B,>`, the parser would
769
+ // first parse `A`, then a comma, then `B`, then a comma. After that it
770
+ // would encounter a `>` and stop. This lets the parser handle trailing
771
+ // commas in generic parameters, because it can stop either after
772
+ // parsing a type or after parsing a comma.
773
+ for i in iter::count(0u, 1) {
774
+ if self.token == token::GT
775
+ || self.token == token::BINOP(token::SHR)
776
+ || self.token == token::GE
777
+ || self.token == token::BINOPEQ(token::SHR) {
778
+ break;
779
+ }
780
+
781
+ if i % 2 == 0 {
782
+ v.push(f(self));
783
+ } else {
784
+ sep.as_ref().map(|t| self.expect(t));
777
785
}
778
- v.push(f(self));
779
786
}
780
787
return OwnedSlice::from_vec(v);
781
788
}
@@ -2266,7 +2273,7 @@ impl<'a> Parser<'a> {
2266
2273
let mut es = self.parse_unspanned_seq(
2267
2274
&token::LPAREN,
2268
2275
&token::RPAREN,
2269
- seq_sep_trailing_disallowed (token::COMMA),
2276
+ seq_sep_trailing_allowed (token::COMMA),
2270
2277
|p| p.parse_expr()
2271
2278
);
2272
2279
hi = self.last_span.hi;
@@ -3196,7 +3203,7 @@ impl<'a> Parser<'a> {
3196
3203
args = self.parse_enum_variant_seq(
3197
3204
&token::LPAREN,
3198
3205
&token::RPAREN,
3199
- seq_sep_trailing_disallowed (token::COMMA),
3206
+ seq_sep_trailing_allowed (token::COMMA),
3200
3207
|p| p.parse_pat()
3201
3208
);
3202
3209
pat = PatEnum(enum_path, Some(args));
@@ -4068,7 +4075,7 @@ impl<'a> Parser<'a> {
4068
4075
match self.token {
4069
4076
token::COMMA => {
4070
4077
self.bump();
4071
- let sep = seq_sep_trailing_disallowed (token::COMMA);
4078
+ let sep = seq_sep_trailing_allowed (token::COMMA);
4072
4079
let mut fn_inputs = self.parse_seq_to_before_end(
4073
4080
&token::RPAREN,
4074
4081
sep,
@@ -4091,7 +4098,7 @@ impl<'a> Parser<'a> {
4091
4098
4092
4099
let fn_inputs = match explicit_self {
4093
4100
SelfStatic => {
4094
- let sep = seq_sep_trailing_disallowed (token::COMMA);
4101
+ let sep = seq_sep_trailing_allowed (token::COMMA);
4095
4102
self.parse_seq_to_before_end(&token::RPAREN, sep, parse_arg_fn)
4096
4103
}
4097
4104
SelfValue(id) => parse_remaining_arguments!(id),
@@ -4128,7 +4135,7 @@ impl<'a> Parser<'a> {
4128
4135
self.parse_optional_unboxed_closure_kind();
4129
4136
let args = self.parse_seq_to_before_end(
4130
4137
&token::BINOP(token::OR),
4131
- seq_sep_trailing_disallowed (token::COMMA),
4138
+ seq_sep_trailing_allowed (token::COMMA),
4132
4139
|p| p.parse_fn_block_arg()
4133
4140
);
4134
4141
self.bump();
@@ -4950,7 +4957,7 @@ impl<'a> Parser<'a> {
4950
4957
let arg_tys = self.parse_enum_variant_seq(
4951
4958
&token::LPAREN,
4952
4959
&token::RPAREN,
4953
- seq_sep_trailing_disallowed (token::COMMA),
4960
+ seq_sep_trailing_allowed (token::COMMA),
4954
4961
|p| p.parse_ty(true)
4955
4962
);
4956
4963
for ty in arg_tys.move_iter() {
0 commit comments