Skip to content

Commit 6d9b219

Browse files
committed
auto merge of #16646 : P1start/rust/trailing-commas, r=alexcrichton
This lets the parser understand trailing commas in method calls, method definitions, enum variants, and type parameters. Closes #14240. Closes #15887.
2 parents 9e8c30c + fde41a3 commit 6d9b219

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
}

0 commit comments

Comments
 (0)