Skip to content

Commit

Permalink
Parse variadics correctly
Browse files Browse the repository at this point in the history
  • Loading branch information
matklad authored and JoshMcguigan committed Apr 1, 2020
1 parent 0b21783 commit ef6eb9f
Show file tree
Hide file tree
Showing 7 changed files with 178 additions and 14 deletions.
44 changes: 33 additions & 11 deletions crates/ra_parser/src/grammar/params.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,21 +56,17 @@ fn list_(p: &mut Parser, flavor: Flavor) {
// fn f(#[attr1] pat: Type) {}
attributes::outer_attributes(p);

// test param_list_vararg
// extern "C" { fn printf(format: *const i8, ...) -> i32; }
match flavor {
FnDef | FnPointer if p.eat(T![...]) => break,
_ => (),
}

if !p.at_ts(VALUE_PARAMETER_FIRST) {
p.error("expected value parameter");
break;
}
value_parameter(p, flavor);
let param = value_parameter(p, flavor);
if !p.at(ket) {
p.expect(T![,]);
}
if let Variadic(true) = param {
break;
}
}

p.expect(ket);
Expand All @@ -79,14 +75,25 @@ fn list_(p: &mut Parser, flavor: Flavor) {

const VALUE_PARAMETER_FIRST: TokenSet = patterns::PATTERN_FIRST.union(types::TYPE_FIRST);

fn value_parameter(p: &mut Parser, flavor: Flavor) {
struct Variadic(bool);

fn value_parameter(p: &mut Parser, flavor: Flavor) -> Variadic {
let mut res = Variadic(false);
let m = p.start();
match flavor {
// test param_list_vararg
// extern "C" { fn printf(format: *const i8, ...) -> i32; }
Flavor::FnDef | Flavor::FnPointer if p.eat(T![...]) => res = Variadic(true),

// test fn_def_param
// fn foo((x, y): (i32, i32)) {}
Flavor::FnDef => {
patterns::pattern(p);
types::ascription(p);
if variadic_param(p) {
res = Variadic(true)
} else {
types::ascription(p);
}
}
// test value_parameters_no_patterns
// type F = Box<Fn(i32, &i32, &i32, ())>;
Expand All @@ -102,7 +109,11 @@ fn value_parameter(p: &mut Parser, flavor: Flavor) {
Flavor::FnPointer => {
if (p.at(IDENT) || p.at(UNDERSCORE)) && p.nth(1) == T![:] && !p.nth_at(1, T![::]) {
patterns::pattern_single(p);
types::ascription(p);
if variadic_param(p) {
res = Variadic(true)
} else {
types::ascription(p);
}
} else {
types::type_(p);
}
Expand All @@ -119,6 +130,17 @@ fn value_parameter(p: &mut Parser, flavor: Flavor) {
}
}
m.complete(p, PARAM);
res
}

fn variadic_param(p: &mut Parser) -> bool {
if p.at(T![:]) && p.nth_at(1, T![...]) {
p.bump(T![:]);
p.bump(T![...]);
true
} else {
false
}
}

// test self_param
Expand Down
1 change: 1 addition & 0 deletions crates/ra_syntax/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ fn main() {
"##;

let parse = SourceFile::parse(code);
// eprintln!("{:#?}", parse.syntax_node());
assert!(parse.ok().is_ok());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,8 @@ SOURCE_FILE@[0; 113)
WHITESPACE@[97; 98) " "
COMMA@[98; 99) ","
WHITESPACE@[99; 100) " "
DOTDOTDOT@[100; 103) "..."
PARAM@[100; 103)
DOTDOTDOT@[100; 103) "..."
WHITESPACE@[103; 104) " "
R_PAREN@[104; 105) ")"
WHITESPACE@[105; 106) " "
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ SOURCE_FILE@[0; 57)
IDENT@[38; 40) "i8"
COMMA@[40; 41) ","
WHITESPACE@[41; 42) " "
DOTDOTDOT@[42; 45) "..."
PARAM@[42; 45)
DOTDOTDOT@[42; 45) "..."
R_PAREN@[45; 46) ")"
WHITESPACE@[46; 47) " "
RET_TYPE@[47; 53)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,8 @@ SOURCE_FILE@[0; 519)
IDENT@[108; 112) "attr"
R_BRACK@[112; 113) "]"
WHITESPACE@[113; 114) " "
DOTDOTDOT@[114; 117) "..."
PARAM@[114; 117)
DOTDOTDOT@[114; 117) "..."
R_PAREN@[117; 118) ")"
WHITESPACE@[118; 119) " "
RET_TYPE@[119; 125)
Expand Down
5 changes: 5 additions & 0 deletions crates/ra_syntax/test_data/parser/ok/0063_variadic_fun.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
extern "C" {
fn a(_: *mut u8, ...,);
fn b(_: *mut u8, _: ...);
fn c(_: *mut u8, #[cfg(never)] [w, t, f]: ...,);
}
133 changes: 133 additions & 0 deletions crates/ra_syntax/test_data/parser/ok/0063_variadic_fun.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
SOURCE_FILE@[0; 126)
EXTERN_BLOCK@[0; 125)
ABI@[0; 10)
EXTERN_KW@[0; 6) "extern"
WHITESPACE@[6; 7) " "
STRING@[7; 10) "\"C\""
WHITESPACE@[10; 11) " "
EXTERN_ITEM_LIST@[11; 125)
L_CURLY@[11; 12) "{"
WHITESPACE@[12; 17) "\n "
FN_DEF@[17; 40)
FN_KW@[17; 19) "fn"
WHITESPACE@[19; 20) " "
NAME@[20; 21)
IDENT@[20; 21) "a"
PARAM_LIST@[21; 39)
L_PAREN@[21; 22) "("
PARAM@[22; 32)
PLACEHOLDER_PAT@[22; 23)
UNDERSCORE@[22; 23) "_"
COLON@[23; 24) ":"
WHITESPACE@[24; 25) " "
POINTER_TYPE@[25; 32)
STAR@[25; 26) "*"
MUT_KW@[26; 29) "mut"
WHITESPACE@[29; 30) " "
PATH_TYPE@[30; 32)
PATH@[30; 32)
PATH_SEGMENT@[30; 32)
NAME_REF@[30; 32)
IDENT@[30; 32) "u8"
COMMA@[32; 33) ","
WHITESPACE@[33; 34) " "
PARAM@[34; 37)
DOTDOTDOT@[34; 37) "..."
COMMA@[37; 38) ","
R_PAREN@[38; 39) ")"
SEMI@[39; 40) ";"
WHITESPACE@[40; 45) "\n "
FN_DEF@[45; 70)
FN_KW@[45; 47) "fn"
WHITESPACE@[47; 48) " "
NAME@[48; 49)
IDENT@[48; 49) "b"
PARAM_LIST@[49; 69)
L_PAREN@[49; 50) "("
PARAM@[50; 60)
PLACEHOLDER_PAT@[50; 51)
UNDERSCORE@[50; 51) "_"
COLON@[51; 52) ":"
WHITESPACE@[52; 53) " "
POINTER_TYPE@[53; 60)
STAR@[53; 54) "*"
MUT_KW@[54; 57) "mut"
WHITESPACE@[57; 58) " "
PATH_TYPE@[58; 60)
PATH@[58; 60)
PATH_SEGMENT@[58; 60)
NAME_REF@[58; 60)
IDENT@[58; 60) "u8"
COMMA@[60; 61) ","
WHITESPACE@[61; 62) " "
PARAM@[62; 68)
PLACEHOLDER_PAT@[62; 63)
UNDERSCORE@[62; 63) "_"
COLON@[63; 64) ":"
WHITESPACE@[64; 65) " "
DOTDOTDOT@[65; 68) "..."
R_PAREN@[68; 69) ")"
SEMI@[69; 70) ";"
WHITESPACE@[70; 75) "\n "
FN_DEF@[75; 123)
FN_KW@[75; 77) "fn"
WHITESPACE@[77; 78) " "
NAME@[78; 79)
IDENT@[78; 79) "c"
PARAM_LIST@[79; 122)
L_PAREN@[79; 80) "("
PARAM@[80; 90)
PLACEHOLDER_PAT@[80; 81)
UNDERSCORE@[80; 81) "_"
COLON@[81; 82) ":"
WHITESPACE@[82; 83) " "
POINTER_TYPE@[83; 90)
STAR@[83; 84) "*"
MUT_KW@[84; 87) "mut"
WHITESPACE@[87; 88) " "
PATH_TYPE@[88; 90)
PATH@[88; 90)
PATH_SEGMENT@[88; 90)
NAME_REF@[88; 90)
IDENT@[88; 90) "u8"
COMMA@[90; 91) ","
WHITESPACE@[91; 92) " "
ATTR@[92; 105)
POUND@[92; 93) "#"
L_BRACK@[93; 94) "["
PATH@[94; 97)
PATH_SEGMENT@[94; 97)
NAME_REF@[94; 97)
IDENT@[94; 97) "cfg"
TOKEN_TREE@[97; 104)
L_PAREN@[97; 98) "("
IDENT@[98; 103) "never"
R_PAREN@[103; 104) ")"
R_BRACK@[104; 105) "]"
WHITESPACE@[105; 106) " "
PARAM@[106; 120)
SLICE_PAT@[106; 115)
L_BRACK@[106; 107) "["
BIND_PAT@[107; 108)
NAME@[107; 108)
IDENT@[107; 108) "w"
COMMA@[108; 109) ","
WHITESPACE@[109; 110) " "
BIND_PAT@[110; 111)
NAME@[110; 111)
IDENT@[110; 111) "t"
COMMA@[111; 112) ","
WHITESPACE@[112; 113) " "
BIND_PAT@[113; 114)
NAME@[113; 114)
IDENT@[113; 114) "f"
R_BRACK@[114; 115) "]"
COLON@[115; 116) ":"
WHITESPACE@[116; 117) " "
DOTDOTDOT@[117; 120) "..."
COMMA@[120; 121) ","
R_PAREN@[121; 122) ")"
SEMI@[122; 123) ";"
WHITESPACE@[123; 124) "\n"
R_CURLY@[124; 125) "}"
WHITESPACE@[125; 126) "\n"

0 comments on commit ef6eb9f

Please sign in to comment.