Skip to content

Commit fde41a3

Browse files
committedAug 22, 2014
Add support for trailing commas in more places
This lets the parser understand trailing commas in method calls, method definitions, enum variants, and type parameters. Closes rust-lang#14240. Closes rust-lang#15887.
1 parent eaf810a commit fde41a3

File tree

2 files changed

+49
-20
lines changed

2 files changed

+49
-20
lines changed
 

‎src/libsyntax/parse/parser.rs

+25-18
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ use std::collections::HashSet;
8686
use std::mem::replace;
8787
use std::rc::Rc;
8888
use 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(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));
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() {

‎src/test/run-pass/trailing-comma.rs

+24-2
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,31 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
fn f(_: int,) {}
11+
fn f<T,>(_: T,) {}
12+
13+
struct Foo<T,>;
14+
15+
struct Bar;
16+
17+
impl Bar {
18+
fn f(_: int,) {}
19+
fn g(self, _: int,) {}
20+
fn h(self,) {}
21+
}
22+
23+
enum Baz {
24+
Qux(int,),
25+
}
1226

1327
pub fn main() {
14-
f(0i,);
28+
f::<int,>(0i,);
1529
let (_, _,) = (1i, 1i,);
30+
31+
let x: Foo<int,> = Foo::<int,>;
32+
33+
Bar::f(0i,);
34+
Bar.g(0i,);
35+
Bar.h();
36+
37+
let x = Qux(1,);
1638
}

1 commit comments

Comments
 (1)

alexcrichton commented on Aug 24, 2014

@alexcrichton

r+, thanks!

Please sign in to comment.