diff options
author | Aleksey Kladov <[email protected]> | 2019-02-20 12:47:32 +0000 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2019-02-20 12:47:32 +0000 |
commit | 5222b8aba3b1c2c68706aacf6869423a8e4fe6d5 (patch) | |
tree | c8a6e999b8ac5f1f29bde86a2e0b3a53466bb369 /crates/ra_syntax/src/parsing/grammar/types.rs | |
parent | 9d0cda4bc84350961f3884e75a1c20e62c449ede (diff) |
move all parsing related bits to a separate module
Diffstat (limited to 'crates/ra_syntax/src/parsing/grammar/types.rs')
-rw-r--r-- | crates/ra_syntax/src/parsing/grammar/types.rs | 278 |
1 files changed, 278 insertions, 0 deletions
diff --git a/crates/ra_syntax/src/parsing/grammar/types.rs b/crates/ra_syntax/src/parsing/grammar/types.rs new file mode 100644 index 000000000..adc189a29 --- /dev/null +++ b/crates/ra_syntax/src/parsing/grammar/types.rs | |||
@@ -0,0 +1,278 @@ | |||
1 | use super::*; | ||
2 | |||
3 | pub(super) const TYPE_FIRST: TokenSet = paths::PATH_FIRST.union(token_set![ | ||
4 | L_PAREN, EXCL, STAR, L_BRACK, AMP, UNDERSCORE, FN_KW, UNSAFE_KW, EXTERN_KW, FOR_KW, IMPL_KW, | ||
5 | DYN_KW, L_ANGLE, | ||
6 | ]); | ||
7 | |||
8 | const TYPE_RECOVERY_SET: TokenSet = token_set![R_PAREN, COMMA]; | ||
9 | |||
10 | pub(super) fn type_(p: &mut Parser) { | ||
11 | type_with_bounds_cond(p, true); | ||
12 | } | ||
13 | |||
14 | pub(super) fn type_no_bounds(p: &mut Parser) { | ||
15 | type_with_bounds_cond(p, false); | ||
16 | } | ||
17 | |||
18 | fn type_with_bounds_cond(p: &mut Parser, allow_bounds: bool) { | ||
19 | match p.current() { | ||
20 | L_PAREN => paren_or_tuple_type(p), | ||
21 | EXCL => never_type(p), | ||
22 | STAR => pointer_type(p), | ||
23 | L_BRACK => array_or_slice_type(p), | ||
24 | AMP => reference_type(p), | ||
25 | UNDERSCORE => placeholder_type(p), | ||
26 | FN_KW | UNSAFE_KW | EXTERN_KW => fn_pointer_type(p), | ||
27 | FOR_KW => for_type(p), | ||
28 | IMPL_KW => impl_trait_type(p), | ||
29 | DYN_KW => dyn_trait_type(p), | ||
30 | // Some path types are not allowed to have bounds (no plus) | ||
31 | L_ANGLE => path_type_(p, allow_bounds), | ||
32 | _ if paths::is_path_start(p) => path_or_macro_type_(p, allow_bounds), | ||
33 | _ => { | ||
34 | p.err_recover("expected type", TYPE_RECOVERY_SET); | ||
35 | } | ||
36 | } | ||
37 | } | ||
38 | |||
39 | pub(super) fn ascription(p: &mut Parser) { | ||
40 | p.expect(COLON); | ||
41 | type_(p) | ||
42 | } | ||
43 | |||
44 | fn paren_or_tuple_type(p: &mut Parser) { | ||
45 | assert!(p.at(L_PAREN)); | ||
46 | let m = p.start(); | ||
47 | p.bump(); | ||
48 | let mut n_types: u32 = 0; | ||
49 | let mut trailing_comma: bool = false; | ||
50 | while !p.at(EOF) && !p.at(R_PAREN) { | ||
51 | n_types += 1; | ||
52 | type_(p); | ||
53 | if p.eat(COMMA) { | ||
54 | trailing_comma = true; | ||
55 | } else { | ||
56 | trailing_comma = false; | ||
57 | break; | ||
58 | } | ||
59 | } | ||
60 | p.expect(R_PAREN); | ||
61 | |||
62 | let kind = if n_types == 1 && !trailing_comma { | ||
63 | // test paren_type | ||
64 | // type T = (i32); | ||
65 | PAREN_TYPE | ||
66 | } else { | ||
67 | // test unit_type | ||
68 | // type T = (); | ||
69 | |||
70 | // test singleton_tuple_type | ||
71 | // type T = (i32,); | ||
72 | TUPLE_TYPE | ||
73 | }; | ||
74 | m.complete(p, kind); | ||
75 | } | ||
76 | |||
77 | // test never_type | ||
78 | // type Never = !; | ||
79 | fn never_type(p: &mut Parser) { | ||
80 | assert!(p.at(EXCL)); | ||
81 | let m = p.start(); | ||
82 | p.bump(); | ||
83 | m.complete(p, NEVER_TYPE); | ||
84 | } | ||
85 | |||
86 | fn pointer_type(p: &mut Parser) { | ||
87 | assert!(p.at(STAR)); | ||
88 | let m = p.start(); | ||
89 | p.bump(); | ||
90 | |||
91 | match p.current() { | ||
92 | // test pointer_type_mut | ||
93 | // type M = *mut (); | ||
94 | // type C = *mut (); | ||
95 | MUT_KW | CONST_KW => p.bump(), | ||
96 | _ => { | ||
97 | // test_err pointer_type_no_mutability | ||
98 | // type T = *(); | ||
99 | p.error( | ||
100 | "expected mut or const in raw pointer type \ | ||
101 | (use `*mut T` or `*const T` as appropriate)", | ||
102 | ); | ||
103 | } | ||
104 | }; | ||
105 | |||
106 | type_no_bounds(p); | ||
107 | m.complete(p, POINTER_TYPE); | ||
108 | } | ||
109 | |||
110 | fn array_or_slice_type(p: &mut Parser) { | ||
111 | assert!(p.at(L_BRACK)); | ||
112 | let m = p.start(); | ||
113 | p.bump(); | ||
114 | |||
115 | type_(p); | ||
116 | let kind = match p.current() { | ||
117 | // test slice_type | ||
118 | // type T = [()]; | ||
119 | R_BRACK => { | ||
120 | p.bump(); | ||
121 | SLICE_TYPE | ||
122 | } | ||
123 | |||
124 | // test array_type | ||
125 | // type T = [(); 92]; | ||
126 | SEMI => { | ||
127 | p.bump(); | ||
128 | expressions::expr(p); | ||
129 | p.expect(R_BRACK); | ||
130 | ARRAY_TYPE | ||
131 | } | ||
132 | // test_err array_type_missing_semi | ||
133 | // type T = [() 92]; | ||
134 | _ => { | ||
135 | p.error("expected `;` or `]`"); | ||
136 | SLICE_TYPE | ||
137 | } | ||
138 | }; | ||
139 | m.complete(p, kind); | ||
140 | } | ||
141 | |||
142 | // test reference_type; | ||
143 | // type A = &(); | ||
144 | // type B = &'static (); | ||
145 | // type C = &mut (); | ||
146 | fn reference_type(p: &mut Parser) { | ||
147 | assert!(p.at(AMP)); | ||
148 | let m = p.start(); | ||
149 | p.bump(); | ||
150 | p.eat(LIFETIME); | ||
151 | p.eat(MUT_KW); | ||
152 | type_no_bounds(p); | ||
153 | m.complete(p, REFERENCE_TYPE); | ||
154 | } | ||
155 | |||
156 | // test placeholder_type | ||
157 | // type Placeholder = _; | ||
158 | fn placeholder_type(p: &mut Parser) { | ||
159 | assert!(p.at(UNDERSCORE)); | ||
160 | let m = p.start(); | ||
161 | p.bump(); | ||
162 | m.complete(p, PLACEHOLDER_TYPE); | ||
163 | } | ||
164 | |||
165 | // test fn_pointer_type | ||
166 | // type A = fn(); | ||
167 | // type B = unsafe fn(); | ||
168 | // type C = unsafe extern "C" fn(); | ||
169 | fn fn_pointer_type(p: &mut Parser) { | ||
170 | let m = p.start(); | ||
171 | p.eat(UNSAFE_KW); | ||
172 | if p.at(EXTERN_KW) { | ||
173 | abi(p); | ||
174 | } | ||
175 | // test_err fn_pointer_type_missing_fn | ||
176 | // type F = unsafe (); | ||
177 | if !p.eat(FN_KW) { | ||
178 | m.abandon(p); | ||
179 | p.error("expected `fn`"); | ||
180 | return; | ||
181 | } | ||
182 | if p.at(L_PAREN) { | ||
183 | params::param_list_opt_patterns(p); | ||
184 | } else { | ||
185 | p.error("expected parameters") | ||
186 | } | ||
187 | // test fn_pointer_type_with_ret | ||
188 | // type F = fn() -> (); | ||
189 | opt_fn_ret_type(p); | ||
190 | m.complete(p, FN_POINTER_TYPE); | ||
191 | } | ||
192 | |||
193 | pub(super) fn for_binder(p: &mut Parser) { | ||
194 | assert!(p.at(FOR_KW)); | ||
195 | p.bump(); | ||
196 | if p.at(L_ANGLE) { | ||
197 | type_params::opt_type_param_list(p); | ||
198 | } else { | ||
199 | p.error("expected `<`"); | ||
200 | } | ||
201 | } | ||
202 | |||
203 | // test for_type | ||
204 | // type A = for<'a> fn() -> (); | ||
205 | pub(super) fn for_type(p: &mut Parser) { | ||
206 | assert!(p.at(FOR_KW)); | ||
207 | let m = p.start(); | ||
208 | for_binder(p); | ||
209 | match p.current() { | ||
210 | FN_KW | UNSAFE_KW | EXTERN_KW => fn_pointer_type(p), | ||
211 | _ if paths::is_path_start(p) => path_type_(p, false), | ||
212 | _ => p.error("expected a path"), | ||
213 | } | ||
214 | m.complete(p, FOR_TYPE); | ||
215 | } | ||
216 | |||
217 | // test impl_trait_type | ||
218 | // type A = impl Iterator<Item=Foo<'a>> + 'a; | ||
219 | fn impl_trait_type(p: &mut Parser) { | ||
220 | assert!(p.at(IMPL_KW)); | ||
221 | let m = p.start(); | ||
222 | p.bump(); | ||
223 | type_params::bounds_without_colon(p); | ||
224 | m.complete(p, IMPL_TRAIT_TYPE); | ||
225 | } | ||
226 | |||
227 | // test dyn_trait_type | ||
228 | // type A = dyn Iterator<Item=Foo<'a>> + 'a; | ||
229 | fn dyn_trait_type(p: &mut Parser) { | ||
230 | assert!(p.at(DYN_KW)); | ||
231 | let m = p.start(); | ||
232 | p.bump(); | ||
233 | type_params::bounds_without_colon(p); | ||
234 | m.complete(p, DYN_TRAIT_TYPE); | ||
235 | } | ||
236 | |||
237 | // test path_type | ||
238 | // type A = Foo; | ||
239 | // type B = ::Foo; | ||
240 | // type C = self::Foo; | ||
241 | // type D = super::Foo; | ||
242 | pub(super) fn path_type(p: &mut Parser) { | ||
243 | path_type_(p, true) | ||
244 | } | ||
245 | |||
246 | // test macro_call_type | ||
247 | // type A = foo!(); | ||
248 | // type B = crate::foo!(); | ||
249 | fn path_or_macro_type_(p: &mut Parser, allow_bounds: bool) { | ||
250 | assert!(paths::is_path_start(p) || p.at(L_ANGLE)); | ||
251 | let m = p.start(); | ||
252 | paths::type_path(p); | ||
253 | |||
254 | let kind = if p.at(EXCL) { | ||
255 | items::macro_call_after_excl(p); | ||
256 | MACRO_CALL | ||
257 | } else { | ||
258 | PATH_TYPE | ||
259 | }; | ||
260 | |||
261 | if allow_bounds && p.eat(PLUS) { | ||
262 | type_params::bounds_without_colon(p); | ||
263 | } | ||
264 | |||
265 | m.complete(p, kind); | ||
266 | } | ||
267 | |||
268 | pub(super) fn path_type_(p: &mut Parser, allow_bounds: bool) { | ||
269 | assert!(paths::is_path_start(p) || p.at(L_ANGLE)); | ||
270 | let m = p.start(); | ||
271 | paths::type_path(p); | ||
272 | // test path_type_with_bounds | ||
273 | // fn foo() -> Box<T + 'f> {} | ||
274 | if allow_bounds && p.eat(PLUS) { | ||
275 | type_params::bounds_without_colon(p); | ||
276 | } | ||
277 | m.complete(p, PATH_TYPE); | ||
278 | } | ||