@@ -86,6 +86,7 @@ use std::collections::HashSet;
8686use std:: mem:: replace;
8787use std:: rc:: Rc ;
8888use std:: gc:: { Gc , GC } ;
89+ use std:: iter;
8990
9091#[ allow( non_camel_case_types) ]
9192#[ deriving( PartialEq ) ]
@@ -762,20 +763,26 @@ impl<'a> Parser<'a> {
762763 sep : Option < token:: Token > ,
763764 f: |& mut Parser | -> T )
764765 -> OwnedSlice < T > {
765- let mut first = true ;
766766 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) ) ;
777785 }
778- v. push ( f ( self ) ) ;
779786 }
780787 return OwnedSlice :: from_vec ( v) ;
781788 }
@@ -2266,7 +2273,7 @@ impl<'a> Parser<'a> {
22662273 let mut es = self . parse_unspanned_seq (
22672274 & token:: LPAREN ,
22682275 & token:: RPAREN ,
2269- seq_sep_trailing_disallowed ( token:: COMMA ) ,
2276+ seq_sep_trailing_allowed ( token:: COMMA ) ,
22702277 |p| p. parse_expr ( )
22712278 ) ;
22722279 hi = self . last_span . hi ;
@@ -3196,7 +3203,7 @@ impl<'a> Parser<'a> {
31963203 args = self . parse_enum_variant_seq (
31973204 & token:: LPAREN ,
31983205 & token:: RPAREN ,
3199- seq_sep_trailing_disallowed ( token:: COMMA ) ,
3206+ seq_sep_trailing_allowed ( token:: COMMA ) ,
32003207 |p| p. parse_pat ( )
32013208 ) ;
32023209 pat = PatEnum ( enum_path, Some ( args) ) ;
@@ -4068,7 +4075,7 @@ impl<'a> Parser<'a> {
40684075 match self . token {
40694076 token:: COMMA => {
40704077 self . bump( ) ;
4071- let sep = seq_sep_trailing_disallowed ( token:: COMMA ) ;
4078+ let sep = seq_sep_trailing_allowed ( token:: COMMA ) ;
40724079 let mut fn_inputs = self . parse_seq_to_before_end(
40734080 & token:: RPAREN ,
40744081 sep,
@@ -4091,7 +4098,7 @@ impl<'a> Parser<'a> {
40914098
40924099 let fn_inputs = match explicit_self {
40934100 SelfStatic => {
4094- let sep = seq_sep_trailing_disallowed ( token:: COMMA ) ;
4101+ let sep = seq_sep_trailing_allowed ( token:: COMMA ) ;
40954102 self . parse_seq_to_before_end ( & token:: RPAREN , sep, parse_arg_fn)
40964103 }
40974104 SelfValue ( id) => parse_remaining_arguments ! ( id) ,
@@ -4128,7 +4135,7 @@ impl<'a> Parser<'a> {
41284135 self . parse_optional_unboxed_closure_kind ( ) ;
41294136 let args = self . parse_seq_to_before_end (
41304137 & token:: BINOP ( token:: OR ) ,
4131- seq_sep_trailing_disallowed ( token:: COMMA ) ,
4138+ seq_sep_trailing_allowed ( token:: COMMA ) ,
41324139 |p| p. parse_fn_block_arg ( )
41334140 ) ;
41344141 self . bump ( ) ;
@@ -4950,7 +4957,7 @@ impl<'a> Parser<'a> {
49504957 let arg_tys = self . parse_enum_variant_seq (
49514958 & token:: LPAREN ,
49524959 & token:: RPAREN ,
4953- seq_sep_trailing_disallowed ( token:: COMMA ) ,
4960+ seq_sep_trailing_allowed ( token:: COMMA ) ,
49544961 |p| p. parse_ty ( true )
49554962 ) ;
49564963 for ty in arg_tys. move_iter ( ) {
0 commit comments