Skip to content

Commit bee5cdb

Browse files
committed
Parse variadics correctly
closes #3571
1 parent 93527b5 commit bee5cdb

File tree

7 files changed

+178
-14
lines changed

7 files changed

+178
-14
lines changed

crates/ra_parser/src/grammar/params.rs

+33-11
Original file line numberDiff line numberDiff line change
@@ -56,21 +56,17 @@ fn list_(p: &mut Parser, flavor: Flavor) {
5656
// fn f(#[attr1] pat: Type) {}
5757
attributes::outer_attributes(p);
5858

59-
// test param_list_vararg
60-
// extern "C" { fn printf(format: *const i8, ...) -> i32; }
61-
match flavor {
62-
FnDef | FnPointer if p.eat(T![...]) => break,
63-
_ => (),
64-
}
65-
6659
if !p.at_ts(VALUE_PARAMETER_FIRST) {
6760
p.error("expected value parameter");
6861
break;
6962
}
70-
value_parameter(p, flavor);
63+
let param = value_parameter(p, flavor);
7164
if !p.at(ket) {
7265
p.expect(T![,]);
7366
}
67+
if let Variadic(true) = param {
68+
break;
69+
}
7470
}
7571

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

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

82-
fn value_parameter(p: &mut Parser, flavor: Flavor) {
78+
struct Variadic(bool);
79+
80+
fn value_parameter(p: &mut Parser, flavor: Flavor) -> Variadic {
81+
let mut res = Variadic(false);
8382
let m = p.start();
8483
match flavor {
84+
// test param_list_vararg
85+
// extern "C" { fn printf(format: *const i8, ...) -> i32; }
86+
Flavor::FnDef | Flavor::FnPointer if p.eat(T![...]) => res = Variadic(true),
87+
8588
// test fn_def_param
8689
// fn foo((x, y): (i32, i32)) {}
8790
Flavor::FnDef => {
8891
patterns::pattern(p);
89-
types::ascription(p);
92+
if variadic_param(p) {
93+
res = Variadic(true)
94+
} else {
95+
types::ascription(p);
96+
}
9097
}
9198
// test value_parameters_no_patterns
9299
// type F = Box<Fn(i32, &i32, &i32, ())>;
@@ -102,7 +109,11 @@ fn value_parameter(p: &mut Parser, flavor: Flavor) {
102109
Flavor::FnPointer => {
103110
if (p.at(IDENT) || p.at(UNDERSCORE)) && p.nth(1) == T![:] && !p.nth_at(1, T![::]) {
104111
patterns::pattern_single(p);
105-
types::ascription(p);
112+
if variadic_param(p) {
113+
res = Variadic(true)
114+
} else {
115+
types::ascription(p);
116+
}
106117
} else {
107118
types::type_(p);
108119
}
@@ -119,6 +130,17 @@ fn value_parameter(p: &mut Parser, flavor: Flavor) {
119130
}
120131
}
121132
m.complete(p, PARAM);
133+
res
134+
}
135+
136+
fn variadic_param(p: &mut Parser) -> bool {
137+
if p.at(T![:]) && p.nth_at(1, T![...]) {
138+
p.bump(T![:]);
139+
p.bump(T![...]);
140+
true
141+
} else {
142+
false
143+
}
122144
}
123145

124146
// test self_param

crates/ra_syntax/src/tests.rs

+1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ fn main() {
3434
"##;
3535

3636
let parse = SourceFile::parse(code);
37+
// eprintln!("{:#?}", parse.syntax_node());
3738
assert!(parse.ok().is_ok());
3839
}
3940

crates/ra_syntax/test_data/parser/inline/ok/0032_fn_pointer_type.txt

+2-1
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,8 @@ SOURCE_FILE@[0; 113)
8181
WHITESPACE@[97; 98) " "
8282
COMMA@[98; 99) ","
8383
WHITESPACE@[99; 100) " "
84-
DOTDOTDOT@[100; 103) "..."
84+
PARAM@[100; 103)
85+
DOTDOTDOT@[100; 103) "..."
8586
WHITESPACE@[103; 104) " "
8687
R_PAREN@[104; 105) ")"
8788
WHITESPACE@[105; 106) " "

crates/ra_syntax/test_data/parser/inline/ok/0123_param_list_vararg.txt

+2-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@ SOURCE_FILE@[0; 57)
3232
IDENT@[38; 40) "i8"
3333
COMMA@[40; 41) ","
3434
WHITESPACE@[41; 42) " "
35-
DOTDOTDOT@[42; 45) "..."
35+
PARAM@[42; 45)
36+
DOTDOTDOT@[42; 45) "..."
3637
R_PAREN@[45; 46) ")"
3738
WHITESPACE@[46; 47) " "
3839
RET_TYPE@[47; 53)

crates/ra_syntax/test_data/parser/ok/0051_parameter_attrs.txt

+2-1
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,8 @@ SOURCE_FILE@[0; 519)
118118
IDENT@[108; 112) "attr"
119119
R_BRACK@[112; 113) "]"
120120
WHITESPACE@[113; 114) " "
121-
DOTDOTDOT@[114; 117) "..."
121+
PARAM@[114; 117)
122+
DOTDOTDOT@[114; 117) "..."
122123
R_PAREN@[117; 118) ")"
123124
WHITESPACE@[118; 119) " "
124125
RET_TYPE@[119; 125)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
extern "C" {
2+
fn a(_: *mut u8, ...,);
3+
fn b(_: *mut u8, _: ...);
4+
fn c(_: *mut u8, #[cfg(never)] [w, t, f]: ...,);
5+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
SOURCE_FILE@[0; 126)
2+
EXTERN_BLOCK@[0; 125)
3+
ABI@[0; 10)
4+
EXTERN_KW@[0; 6) "extern"
5+
WHITESPACE@[6; 7) " "
6+
STRING@[7; 10) "\"C\""
7+
WHITESPACE@[10; 11) " "
8+
EXTERN_ITEM_LIST@[11; 125)
9+
L_CURLY@[11; 12) "{"
10+
WHITESPACE@[12; 17) "\n "
11+
FN_DEF@[17; 40)
12+
FN_KW@[17; 19) "fn"
13+
WHITESPACE@[19; 20) " "
14+
NAME@[20; 21)
15+
IDENT@[20; 21) "a"
16+
PARAM_LIST@[21; 39)
17+
L_PAREN@[21; 22) "("
18+
PARAM@[22; 32)
19+
PLACEHOLDER_PAT@[22; 23)
20+
UNDERSCORE@[22; 23) "_"
21+
COLON@[23; 24) ":"
22+
WHITESPACE@[24; 25) " "
23+
POINTER_TYPE@[25; 32)
24+
STAR@[25; 26) "*"
25+
MUT_KW@[26; 29) "mut"
26+
WHITESPACE@[29; 30) " "
27+
PATH_TYPE@[30; 32)
28+
PATH@[30; 32)
29+
PATH_SEGMENT@[30; 32)
30+
NAME_REF@[30; 32)
31+
IDENT@[30; 32) "u8"
32+
COMMA@[32; 33) ","
33+
WHITESPACE@[33; 34) " "
34+
PARAM@[34; 37)
35+
DOTDOTDOT@[34; 37) "..."
36+
COMMA@[37; 38) ","
37+
R_PAREN@[38; 39) ")"
38+
SEMI@[39; 40) ";"
39+
WHITESPACE@[40; 45) "\n "
40+
FN_DEF@[45; 70)
41+
FN_KW@[45; 47) "fn"
42+
WHITESPACE@[47; 48) " "
43+
NAME@[48; 49)
44+
IDENT@[48; 49) "b"
45+
PARAM_LIST@[49; 69)
46+
L_PAREN@[49; 50) "("
47+
PARAM@[50; 60)
48+
PLACEHOLDER_PAT@[50; 51)
49+
UNDERSCORE@[50; 51) "_"
50+
COLON@[51; 52) ":"
51+
WHITESPACE@[52; 53) " "
52+
POINTER_TYPE@[53; 60)
53+
STAR@[53; 54) "*"
54+
MUT_KW@[54; 57) "mut"
55+
WHITESPACE@[57; 58) " "
56+
PATH_TYPE@[58; 60)
57+
PATH@[58; 60)
58+
PATH_SEGMENT@[58; 60)
59+
NAME_REF@[58; 60)
60+
IDENT@[58; 60) "u8"
61+
COMMA@[60; 61) ","
62+
WHITESPACE@[61; 62) " "
63+
PARAM@[62; 68)
64+
PLACEHOLDER_PAT@[62; 63)
65+
UNDERSCORE@[62; 63) "_"
66+
COLON@[63; 64) ":"
67+
WHITESPACE@[64; 65) " "
68+
DOTDOTDOT@[65; 68) "..."
69+
R_PAREN@[68; 69) ")"
70+
SEMI@[69; 70) ";"
71+
WHITESPACE@[70; 75) "\n "
72+
FN_DEF@[75; 123)
73+
FN_KW@[75; 77) "fn"
74+
WHITESPACE@[77; 78) " "
75+
NAME@[78; 79)
76+
IDENT@[78; 79) "c"
77+
PARAM_LIST@[79; 122)
78+
L_PAREN@[79; 80) "("
79+
PARAM@[80; 90)
80+
PLACEHOLDER_PAT@[80; 81)
81+
UNDERSCORE@[80; 81) "_"
82+
COLON@[81; 82) ":"
83+
WHITESPACE@[82; 83) " "
84+
POINTER_TYPE@[83; 90)
85+
STAR@[83; 84) "*"
86+
MUT_KW@[84; 87) "mut"
87+
WHITESPACE@[87; 88) " "
88+
PATH_TYPE@[88; 90)
89+
PATH@[88; 90)
90+
PATH_SEGMENT@[88; 90)
91+
NAME_REF@[88; 90)
92+
IDENT@[88; 90) "u8"
93+
COMMA@[90; 91) ","
94+
WHITESPACE@[91; 92) " "
95+
ATTR@[92; 105)
96+
POUND@[92; 93) "#"
97+
L_BRACK@[93; 94) "["
98+
PATH@[94; 97)
99+
PATH_SEGMENT@[94; 97)
100+
NAME_REF@[94; 97)
101+
IDENT@[94; 97) "cfg"
102+
TOKEN_TREE@[97; 104)
103+
L_PAREN@[97; 98) "("
104+
IDENT@[98; 103) "never"
105+
R_PAREN@[103; 104) ")"
106+
R_BRACK@[104; 105) "]"
107+
WHITESPACE@[105; 106) " "
108+
PARAM@[106; 120)
109+
SLICE_PAT@[106; 115)
110+
L_BRACK@[106; 107) "["
111+
BIND_PAT@[107; 108)
112+
NAME@[107; 108)
113+
IDENT@[107; 108) "w"
114+
COMMA@[108; 109) ","
115+
WHITESPACE@[109; 110) " "
116+
BIND_PAT@[110; 111)
117+
NAME@[110; 111)
118+
IDENT@[110; 111) "t"
119+
COMMA@[111; 112) ","
120+
WHITESPACE@[112; 113) " "
121+
BIND_PAT@[113; 114)
122+
NAME@[113; 114)
123+
IDENT@[113; 114) "f"
124+
R_BRACK@[114; 115) "]"
125+
COLON@[115; 116) ":"
126+
WHITESPACE@[116; 117) " "
127+
DOTDOTDOT@[117; 120) "..."
128+
COMMA@[120; 121) ","
129+
R_PAREN@[121; 122) ")"
130+
SEMI@[122; 123) ";"
131+
WHITESPACE@[123; 124) "\n"
132+
R_CURLY@[124; 125) "}"
133+
WHITESPACE@[125; 126) "\n"

0 commit comments

Comments
 (0)