@@ -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 ( 0 u, 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 ( ) {
1 commit comments
alexcrichton commentedon Aug 24, 2014
r+, thanks!