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.
This commit is contained in:
bors 2014-08-24 22:16:00 +00:00
commit 6d9b219e6f
2 changed files with 49 additions and 20 deletions

View File

@ -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)]
@ -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);
}
@ -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;
@ -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));
@ -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,
@ -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),
@ -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();
@ -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() {

View File

@ -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,);
}