Remove parser restriction on varargs positioning

This commit is contained in:
Jonas Schievink 2022-03-31 16:03:27 +02:00
parent 9b000b544b
commit 42ecf406e8
5 changed files with 37 additions and 28 deletions

View file

@ -71,13 +71,10 @@ fn list_(p: &mut Parser, flavor: Flavor) {
m.abandon(p); m.abandon(p);
break; break;
} }
let param = param(p, m, flavor); param(p, m, flavor);
if !p.at(ket) { if !p.at(ket) {
p.expect(T![,]); p.expect(T![,]);
} }
if let Variadic(true) = param {
break;
}
} }
if let Some(m) = param_marker { if let Some(m) = param_marker {
@ -90,27 +87,24 @@ fn list_(p: &mut Parser, flavor: Flavor) {
const PARAM_FIRST: TokenSet = patterns::PATTERN_FIRST.union(types::TYPE_FIRST); const PARAM_FIRST: TokenSet = patterns::PATTERN_FIRST.union(types::TYPE_FIRST);
struct Variadic(bool); fn param(p: &mut Parser, m: Marker, flavor: Flavor) {
fn param(p: &mut Parser, m: Marker, flavor: Flavor) -> Variadic {
let mut res = Variadic(false);
match flavor { match flavor {
// test param_list_vararg // test param_list_vararg
// extern "C" { fn printf(format: *const i8, ...) -> i32; } // extern "C" { fn printf(format: *const i8, ..., _: u8) -> i32; }
Flavor::FnDef | Flavor::FnPointer if p.eat(T![...]) => res = Variadic(true), Flavor::FnDef | Flavor::FnPointer if p.eat(T![...]) => {}
// test fn_def_param // test fn_def_param
// fn foo((x, y): (i32, i32)) {} // fn foo(..., (x, y): (i32, i32)) {}
Flavor::FnDef => { Flavor::FnDef => {
patterns::pattern(p); patterns::pattern(p);
if variadic_param(p) { if !variadic_param(p) {
res = Variadic(true); if p.at(T![:]) {
} else if p.at(T![:]) { types::ascription(p);
types::ascription(p); } else {
} else { // test_err missing_fn_param_type
// test_err missing_fn_param_type // fn f(x y: i32, z, t: i32) {}
// fn f(x y: i32, z, t: i32) {} p.error("missing type for function parameter");
p.error("missing type for function parameter"); }
} }
} }
// test value_parameters_no_patterns // test value_parameters_no_patterns
@ -127,12 +121,12 @@ fn param(p: &mut Parser, m: Marker, flavor: Flavor) -> Variadic {
Flavor::FnPointer => { Flavor::FnPointer => {
if (p.at(IDENT) || p.at(UNDERSCORE)) && p.nth(1) == T![:] && !p.nth_at(1, T![::]) { if (p.at(IDENT) || p.at(UNDERSCORE)) && p.nth(1) == T![:] && !p.nth_at(1, T![::]) {
patterns::pattern_single(p); patterns::pattern_single(p);
if variadic_param(p) { if !variadic_param(p) {
res = Variadic(true); if p.at(T![:]) {
} else if p.at(T![:]) { types::ascription(p);
types::ascription(p); } else {
} else { p.error("missing type for function parameter");
p.error("missing type for function parameter"); }
} }
} else { } else {
types::type_(p); types::type_(p);
@ -150,7 +144,6 @@ fn param(p: &mut Parser, m: Marker, flavor: Flavor) -> Variadic {
} }
} }
m.complete(p, PARAM); m.complete(p, PARAM);
res
} }
fn variadic_param(p: &mut Parser) -> bool { fn variadic_param(p: &mut Parser) -> bool {

View file

@ -34,6 +34,18 @@ SOURCE_FILE
WHITESPACE " " WHITESPACE " "
PARAM PARAM
DOT3 "..." DOT3 "..."
COMMA ","
WHITESPACE " "
PARAM
WILDCARD_PAT
UNDERSCORE "_"
COLON ":"
WHITESPACE " "
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
IDENT "u8"
R_PAREN ")" R_PAREN ")"
WHITESPACE " " WHITESPACE " "
RET_TYPE RET_TYPE

View file

@ -1 +1 @@
extern "C" { fn printf(format: *const i8, ...) -> i32; } extern "C" { fn printf(format: *const i8, ..., _: u8) -> i32; }

View file

@ -6,6 +6,10 @@ SOURCE_FILE
IDENT "foo" IDENT "foo"
PARAM_LIST PARAM_LIST
L_PAREN "(" L_PAREN "("
PARAM
DOT3 "..."
COMMA ","
WHITESPACE " "
PARAM PARAM
TUPLE_PAT TUPLE_PAT
L_PAREN "(" L_PAREN "("

View file

@ -1 +1 @@
fn foo((x, y): (i32, i32)) {} fn foo(..., (x, y): (i32, i32)) {}