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 #14240. Closes #15887.
This commit is contained in:
parent
eaf810a219
commit
fde41a3f70
@ -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() {
|
||||
|
@ -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,);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user