Skip to content

Commit

Permalink
Add support for trailing commas in more places
Browse files Browse the repository at this point in the history
This lets the parser understand trailing commas in method calls, method
definitions, enum variants, and type parameters.

Closes #14240.
Closes #15887.
  • Loading branch information
ftxqxd committed Aug 22, 2014
1 parent eaf810a commit fde41a3
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 20 deletions.
43 changes: 25 additions & 18 deletions src/libsyntax/parse/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ use std::collections::HashSet;
use std::mem::replace;
use std::rc::Rc;
use std::gc::{Gc, GC};
use std::iter;

#[allow(non_camel_case_types)]
#[deriving(PartialEq)]
Expand Down Expand Up @@ -762,20 +763,26 @@ impl<'a> Parser<'a> {
sep: Option<token::Token>,
f: |&mut Parser| -> T)
-> OwnedSlice<T> {
let mut first = true;
let mut v = Vec::new();
while self.token != token::GT
&& self.token != token::BINOP(token::SHR)
&& self.token != token::GE
&& self.token != token::BINOPEQ(token::SHR) {
match sep {
Some(ref t) => {
if first { first = false; }
else { self.expect(t); }
}
_ => ()
// This loop works by alternating back and forth between parsing types
// and commas. For example, given a string `A, B,>`, the parser would
// first parse `A`, then a comma, then `B`, then a comma. After that it
// would encounter a `>` and stop. This lets the parser handle trailing
// commas in generic parameters, because it can stop either after
// parsing a type or after parsing a comma.
for i in iter::count(0u, 1) {
if self.token == token::GT
|| self.token == token::BINOP(token::SHR)
|| self.token == token::GE
|| self.token == token::BINOPEQ(token::SHR) {
break;
}

if i % 2 == 0 {
v.push(f(self));
} else {
sep.as_ref().map(|t| self.expect(t));
}
v.push(f(self));
}
return OwnedSlice::from_vec(v);
}
Expand Down Expand Up @@ -2266,7 +2273,7 @@ impl<'a> Parser<'a> {
let mut es = self.parse_unspanned_seq(
&token::LPAREN,
&token::RPAREN,
seq_sep_trailing_disallowed(token::COMMA),
seq_sep_trailing_allowed(token::COMMA),
|p| p.parse_expr()
);
hi = self.last_span.hi;
Expand Down Expand Up @@ -3196,7 +3203,7 @@ impl<'a> Parser<'a> {
args = self.parse_enum_variant_seq(
&token::LPAREN,
&token::RPAREN,
seq_sep_trailing_disallowed(token::COMMA),
seq_sep_trailing_allowed(token::COMMA),
|p| p.parse_pat()
);
pat = PatEnum(enum_path, Some(args));
Expand Down Expand Up @@ -4068,7 +4075,7 @@ impl<'a> Parser<'a> {
match self.token {
token::COMMA => {
self.bump();
let sep = seq_sep_trailing_disallowed(token::COMMA);
let sep = seq_sep_trailing_allowed(token::COMMA);
let mut fn_inputs = self.parse_seq_to_before_end(
&token::RPAREN,
sep,
Expand All @@ -4091,7 +4098,7 @@ impl<'a> Parser<'a> {

let fn_inputs = match explicit_self {
SelfStatic => {
let sep = seq_sep_trailing_disallowed(token::COMMA);
let sep = seq_sep_trailing_allowed(token::COMMA);
self.parse_seq_to_before_end(&token::RPAREN, sep, parse_arg_fn)
}
SelfValue(id) => parse_remaining_arguments!(id),
Expand Down Expand Up @@ -4128,7 +4135,7 @@ impl<'a> Parser<'a> {
self.parse_optional_unboxed_closure_kind();
let args = self.parse_seq_to_before_end(
&token::BINOP(token::OR),
seq_sep_trailing_disallowed(token::COMMA),
seq_sep_trailing_allowed(token::COMMA),
|p| p.parse_fn_block_arg()
);
self.bump();
Expand Down Expand Up @@ -4950,7 +4957,7 @@ impl<'a> Parser<'a> {
let arg_tys = self.parse_enum_variant_seq(
&token::LPAREN,
&token::RPAREN,
seq_sep_trailing_disallowed(token::COMMA),
seq_sep_trailing_allowed(token::COMMA),
|p| p.parse_ty(true)
);
for ty in arg_tys.move_iter() {
Expand Down
26 changes: 24 additions & 2 deletions src/test/run-pass/trailing-comma.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,31 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

fn f(_: int,) {}
fn f<T,>(_: T,) {}

struct Foo<T,>;

struct Bar;

impl Bar {
fn f(_: int,) {}
fn g(self, _: int,) {}
fn h(self,) {}
}

enum Baz {
Qux(int,),
}

pub fn main() {
f(0i,);
f::<int,>(0i,);
let (_, _,) = (1i, 1i,);

let x: Foo<int,> = Foo::<int,>;

Bar::f(0i,);
Bar.g(0i,);
Bar.h();

let x = Qux(1,);
}

5 comments on commit fde41a3

@bors
Copy link
Contributor

@bors bors commented on fde41a3 Aug 24, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

saw approval from alexcrichton
at ftxqxd@fde41a3

@bors
Copy link
Contributor

@bors bors commented on fde41a3 Aug 24, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

merging P1start/rust/trailing-commas = fde41a3 into auto

@bors
Copy link
Contributor

@bors bors commented on fde41a3 Aug 24, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1start/rust/trailing-commas = fde41a3 merged ok, testing candidate = 6d9b219

@bors
Copy link
Contributor

@bors bors commented on fde41a3 Aug 24, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fast-forwarding master to auto = 6d9b219

Please sign in to comment.