1use crate::grammar::attributes::ATTRIBUTE_FIRST;
2
3use super::*;
4
5pub(super) fn param_list_fn_def(p: &mut Parser<'_>) {
14 list_(p, Flavor::FnDef);
15}
16
17pub(super) fn param_list_fn_ptr(p: &mut Parser<'_>) {
18 list_(p, Flavor::FnPointer);
19}
20
21pub(super) fn param_list_closure(p: &mut Parser<'_>) {
22 list_(p, Flavor::Closure);
23}
24
25#[derive(Debug, Clone, Copy, PartialEq, Eq)]
26enum Flavor {
27 FnDef, FnPointer,
29 Closure,
30}
31
32fn list_(p: &mut Parser<'_>, flavor: Flavor) {
33 use Flavor::*;
34
35 let (bra, ket) = match flavor {
36 Closure => (T![|], T![|]),
37 FnDef | FnPointer => (T!['('], T![')']),
38 };
39
40 let list_marker = p.start();
41 p.bump(bra);
42
43 let mut param_marker = None;
44 if let FnDef = flavor {
45 let m = p.start();
48 attributes::outer_attrs(p);
49 match opt_self_param(p, m) {
50 Ok(()) => {}
51 Err(m) => param_marker = Some(m),
52 }
53 }
54
55 while !p.at(EOF) && !p.at(ket) {
56 let m = match param_marker.take() {
59 Some(m) => m,
60 None => {
61 let m = p.start();
62 attributes::outer_attrs(p);
63 m
64 }
65 };
66
67 if !p.at_ts(PARAM_FIRST.union(ATTRIBUTE_FIRST)) {
68 p.error("expected value parameter");
69 m.abandon(p);
70 if p.eat(T![,]) {
71 continue;
72 }
73 break;
74 }
75 param(p, m, flavor);
76 if !p.eat(T![,]) {
77 if p.at_ts(PARAM_FIRST.union(ATTRIBUTE_FIRST)) {
78 p.error("expected `,`");
79 } else {
80 break;
81 }
82 }
83 }
84
85 if let Some(m) = param_marker {
86 m.abandon(p);
87 }
88
89 p.expect(ket);
90 list_marker.complete(p, PARAM_LIST);
91}
92
93const PARAM_FIRST: TokenSet = patterns::PATTERN_FIRST.union(types::TYPE_FIRST);
94
95fn param(p: &mut Parser<'_>, m: Marker, flavor: Flavor) {
96 match flavor {
97 Flavor::FnDef | Flavor::FnPointer if p.eat(T![...]) => {}
100
101 Flavor::FnDef => {
104 patterns::pattern(p);
105 if !variadic_param(p) {
106 if p.at(T![:]) {
107 types::ascription(p);
108 } else {
109 p.error("missing type for function parameter");
112 }
113 }
114 }
115 Flavor::FnPointer => {
122 if (p.at(IDENT) || p.at(UNDERSCORE)) && p.nth(1) == T![:] && !p.nth_at(1, T![::]) {
123 patterns::pattern_single(p);
124 if !variadic_param(p) {
125 if p.at(T![:]) {
126 types::ascription(p);
127 } else {
128 p.error("missing type for function parameter");
129 }
130 }
131 } else {
132 types::type_(p);
133 }
134 }
135 Flavor::Closure => {
140 patterns::pattern_single(p);
141 if p.at(T![:]) && !p.at(T![::]) {
142 types::ascription(p);
143 }
144 }
145 }
146 m.complete(p, PARAM);
147}
148
149fn variadic_param(p: &mut Parser<'_>) -> bool {
150 if p.at(T![:]) && p.nth_at(1, T![...]) {
151 p.bump(T![:]);
152 p.bump(T![...]);
153 true
154 } else {
155 false
156 }
157}
158
159fn opt_self_param(p: &mut Parser<'_>, m: Marker) -> Result<(), Marker> {
168 if p.at(T![self]) || p.at(T![mut]) && p.nth(1) == T![self] {
169 p.eat(T![mut]);
170 self_as_name(p);
171 if p.at(T![:]) {
177 types::ascription(p);
178 }
179 } else {
180 let la1 = p.nth(1);
181 let la2 = p.nth(2);
182 let la3 = p.nth(3);
183 if !matches!(
184 (p.current(), la1, la2, la3),
185 (T![&], T![self], _, _)
186 | (T![&], T![mut] | LIFETIME_IDENT, T![self], _)
187 | (T![&], LIFETIME_IDENT, T![mut], T![self])
188 ) {
189 return Err(m);
190 }
191 p.bump(T![&]);
192 if p.at(LIFETIME_IDENT) {
193 lifetime(p);
194 }
195 p.eat(T![mut]);
196 self_as_name(p);
197 }
198 m.complete(p, SELF_PARAM);
199 if !p.at(T![')']) {
200 p.expect(T![,]);
201 }
202 Ok(())
203}
204
205fn self_as_name(p: &mut Parser<'_>) {
206 let m = p.start();
207 p.bump(T![self]);
208 m.complete(p, NAME);
209}