]> git.lizzy.rs Git - rust.git/blob - crates/parser/src/grammar/params.rs
Align parser names with grammar
[rust.git] / crates / parser / src / grammar / params.rs
1 //! FIXME: write short doc here
2
3 use 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: ()) {}
10 pub(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>)>(){}
16 pub(super) fn param_list_fn_trait(p: &mut Parser) {
17     list_(p, Flavor::FnTrait)
18 }
19
20 pub(super) fn param_list_fn_ptr(p: &mut Parser) {
21     list_(p, Flavor::FnPointer)
22 }
23
24 pub(super) fn param_list_closure(p: &mut Parser) {
25     list_(p, Flavor::Closure)
26 }
27
28 #[derive(Debug, Clone, Copy)]
29 enum 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
36 fn 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_attrs(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_attrs(p);
58
59         if !p.at_ts(PARAM_FIRST) {
60             p.error("expected value parameter");
61             break;
62         }
63         let param = param(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
76 const PARAM_FIRST: TokenSet = patterns::PATTERN_FIRST.union(types::TYPE_FIRST);
77
78 struct Variadic(bool);
79
80 fn param(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
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     }
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 // }
154 fn 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 }