aboutsummaryrefslogtreecommitdiff
path: root/crates/parser/src/grammar/params.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/parser/src/grammar/params.rs')
-rw-r--r--crates/parser/src/grammar/params.rs188
1 files changed, 188 insertions, 0 deletions
diff --git a/crates/parser/src/grammar/params.rs b/crates/parser/src/grammar/params.rs
new file mode 100644
index 000000000..f0da173cc
--- /dev/null
+++ b/crates/parser/src/grammar/params.rs
@@ -0,0 +1,188 @@
1//! FIXME: write short doc here
2
3use super::*;
4
5// test param_list
6// fn a() {}
7// fn b(x: i32) {}
8// fn c(x: i32, ) {}
9// fn d(x: i32, y: ()) {}
10pub(super) fn param_list_fn_def(p: &mut Parser) {
11 list_(p, Flavor::FnDef)
12}
13
14// test param_list_opt_patterns
15// fn foo<F: FnMut(&mut Foo<'a>)>(){}
16pub(super) fn param_list_fn_trait(p: &mut Parser) {
17 list_(p, Flavor::FnTrait)
18}
19
20pub(super) fn param_list_fn_ptr(p: &mut Parser) {
21 list_(p, Flavor::FnPointer)
22}
23
24pub(super) fn param_list_closure(p: &mut Parser) {
25 list_(p, Flavor::Closure)
26}
27
28#[derive(Debug, Clone, Copy)]
29enum Flavor {
30 FnDef, // Includes trait fn params; omitted param idents are not supported
31 FnTrait, // Params for `Fn(...)`/`FnMut(...)`/`FnOnce(...)` annotations
32 FnPointer,
33 Closure,
34}
35
36fn list_(p: &mut Parser, flavor: Flavor) {
37 use Flavor::*;
38
39 let (bra, ket) = match flavor {
40 Closure => (T![|], T![|]),
41 FnDef | FnTrait | FnPointer => (T!['('], T![')']),
42 };
43
44 let m = p.start();
45 p.bump(bra);
46
47 if let FnDef = flavor {
48 // test self_param_outer_attr
49 // fn f(#[must_use] self) {}
50 attributes::outer_attributes(p);
51 opt_self_param(p);
52 }
53
54 while !p.at(EOF) && !p.at(ket) {
55 // test param_outer_arg
56 // fn f(#[attr1] pat: Type) {}
57 attributes::outer_attributes(p);
58
59 if !p.at_ts(VALUE_PARAMETER_FIRST) {
60 p.error("expected value parameter");
61 break;
62 }
63 let param = value_parameter(p, flavor);
64 if !p.at(ket) {
65 p.expect(T![,]);
66 }
67 if let Variadic(true) = param {
68 break;
69 }
70 }
71
72 p.expect(ket);
73 m.complete(p, PARAM_LIST);
74}
75
76const VALUE_PARAMETER_FIRST: TokenSet = patterns::PATTERN_FIRST.union(types::TYPE_FIRST);
77
78struct Variadic(bool);
79
80fn value_parameter(p: &mut Parser, flavor: Flavor) -> Variadic {
81 let mut res = Variadic(false);
82 let m = p.start();
83 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
88 // test fn_def_param
89 // fn foo((x, y): (i32, i32)) {}
90 Flavor::FnDef => {
91 patterns::pattern(p);
92 if variadic_param(p) {
93 res = Variadic(true)
94 } else {
95 types::ascription(p);
96 }
97 }
98 // test value_parameters_no_patterns
99 // type F = Box<Fn(i32, &i32, &i32, ())>;
100 Flavor::FnTrait => {
101 types::type_(p);
102 }
103 // test fn_pointer_param_ident_path
104 // type Foo = fn(Bar::Baz);
105 // type Qux = fn(baz: Bar::Baz);
106
107 // test fn_pointer_unnamed_arg
108 // type Foo = fn(_: bar);
109 Flavor::FnPointer => {
110 if (p.at(IDENT) || p.at(UNDERSCORE)) && p.nth(1) == T![:] && !p.nth_at(1, T![::]) {
111 patterns::pattern_single(p);
112 if variadic_param(p) {
113 res = Variadic(true)
114 } else {
115 types::ascription(p);
116 }
117 } else {
118 types::type_(p);
119 }
120 }
121 // test closure_params
122 // fn main() {
123 // let foo = |bar, baz: Baz, qux: Qux::Quux| ();
124 // }
125 Flavor::Closure => {
126 patterns::pattern_single(p);
127 if p.at(T![:]) && !p.at(T![::]) {
128 types::ascription(p);
129 }
130 }
131 }
132 m.complete(p, PARAM);
133 res
134}
135
136fn 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 }
144}
145
146// test self_param
147// impl S {
148// fn a(self) {}
149// fn b(&self,) {}
150// fn c(&'a self,) {}
151// fn d(&'a mut self, x: i32) {}
152// fn e(mut self) {}
153// }
154fn opt_self_param(p: &mut Parser) {
155 let m;
156 if p.at(T![self]) || p.at(T![mut]) && p.nth(1) == T![self] {
157 m = p.start();
158 p.eat(T![mut]);
159 p.eat(T![self]);
160 // test arb_self_types
161 // impl S {
162 // fn a(self: &Self) {}
163 // fn b(mut self: Box<Self>) {}
164 // }
165 if p.at(T![:]) {
166 types::ascription(p);
167 }
168 } else {
169 let la1 = p.nth(1);
170 let la2 = p.nth(2);
171 let la3 = p.nth(3);
172 let n_toks = match (p.current(), la1, la2, la3) {
173 (T![&], T![self], _, _) => 2,
174 (T![&], T![mut], T![self], _) => 3,
175 (T![&], LIFETIME, T![self], _) => 3,
176 (T![&], LIFETIME, T![mut], T![self]) => 4,
177 _ => return,
178 };
179 m = p.start();
180 for _ in 0..n_toks {
181 p.bump_any();
182 }
183 }
184 m.complete(p, SELF_PARAM);
185 if !p.at(T![')']) {
186 p.expect(T![,]);
187 }
188}