diff options
Diffstat (limited to 'crates/ra_parser/src/grammar/items.rs')
-rw-r--r-- | crates/ra_parser/src/grammar/items.rs | 492 |
1 files changed, 0 insertions, 492 deletions
diff --git a/crates/ra_parser/src/grammar/items.rs b/crates/ra_parser/src/grammar/items.rs deleted file mode 100644 index cca524cea..000000000 --- a/crates/ra_parser/src/grammar/items.rs +++ /dev/null | |||
@@ -1,492 +0,0 @@ | |||
1 | //! FIXME: write short doc here | ||
2 | |||
3 | mod consts; | ||
4 | mod adt; | ||
5 | mod traits; | ||
6 | mod use_item; | ||
7 | |||
8 | pub(crate) use self::{ | ||
9 | adt::{enum_variant_list, record_field_def_list}, | ||
10 | expressions::{match_arm_list, record_field_list}, | ||
11 | traits::{impl_item_list, trait_item_list}, | ||
12 | use_item::use_tree_list, | ||
13 | }; | ||
14 | use super::*; | ||
15 | |||
16 | // test mod_contents | ||
17 | // fn foo() {} | ||
18 | // macro_rules! foo {} | ||
19 | // foo::bar!(); | ||
20 | // super::baz! {} | ||
21 | // struct S; | ||
22 | pub(super) fn mod_contents(p: &mut Parser, stop_on_r_curly: bool) { | ||
23 | attributes::inner_attributes(p); | ||
24 | while !(stop_on_r_curly && p.at(T!['}']) || p.at(EOF)) { | ||
25 | item_or_macro(p, stop_on_r_curly, ItemFlavor::Mod) | ||
26 | } | ||
27 | } | ||
28 | |||
29 | pub(super) enum ItemFlavor { | ||
30 | Mod, | ||
31 | Trait, | ||
32 | } | ||
33 | |||
34 | pub(super) const ITEM_RECOVERY_SET: TokenSet = token_set![ | ||
35 | FN_KW, STRUCT_KW, ENUM_KW, IMPL_KW, TRAIT_KW, CONST_KW, STATIC_KW, LET_KW, MOD_KW, PUB_KW, | ||
36 | CRATE_KW, USE_KW, MACRO_KW | ||
37 | ]; | ||
38 | |||
39 | pub(super) fn item_or_macro(p: &mut Parser, stop_on_r_curly: bool, flavor: ItemFlavor) { | ||
40 | let m = p.start(); | ||
41 | attributes::outer_attributes(p); | ||
42 | let m = match maybe_item(p, m, flavor) { | ||
43 | Ok(()) => { | ||
44 | if p.at(T![;]) { | ||
45 | p.err_and_bump( | ||
46 | "expected item, found `;`\n\ | ||
47 | consider removing this semicolon", | ||
48 | ); | ||
49 | } | ||
50 | return; | ||
51 | } | ||
52 | Err(m) => m, | ||
53 | }; | ||
54 | if paths::is_use_path_start(p) { | ||
55 | match macro_call(p) { | ||
56 | BlockLike::Block => (), | ||
57 | BlockLike::NotBlock => { | ||
58 | p.expect(T![;]); | ||
59 | } | ||
60 | } | ||
61 | m.complete(p, MACRO_CALL); | ||
62 | } else { | ||
63 | m.abandon(p); | ||
64 | if p.at(T!['{']) { | ||
65 | error_block(p, "expected an item"); | ||
66 | } else if p.at(T!['}']) && !stop_on_r_curly { | ||
67 | let e = p.start(); | ||
68 | p.error("unmatched `}`"); | ||
69 | p.bump(T!['}']); | ||
70 | e.complete(p, ERROR); | ||
71 | } else if !p.at(EOF) && !p.at(T!['}']) { | ||
72 | p.err_and_bump("expected an item"); | ||
73 | } else { | ||
74 | p.error("expected an item"); | ||
75 | } | ||
76 | } | ||
77 | } | ||
78 | |||
79 | pub(super) fn maybe_item(p: &mut Parser, m: Marker, flavor: ItemFlavor) -> Result<(), Marker> { | ||
80 | // test_err pub_expr | ||
81 | // fn foo() { pub 92; } | ||
82 | let has_visibility = opt_visibility(p); | ||
83 | |||
84 | let m = match items_without_modifiers(p, m) { | ||
85 | Ok(()) => return Ok(()), | ||
86 | Err(m) => m, | ||
87 | }; | ||
88 | |||
89 | let mut has_mods = false; | ||
90 | |||
91 | // modifiers | ||
92 | has_mods |= p.eat(T![const]); | ||
93 | |||
94 | // test_err async_without_semicolon | ||
95 | // fn foo() { let _ = async {} } | ||
96 | if p.at(T![async]) && p.nth(1) != T!['{'] && p.nth(1) != T![move] && p.nth(1) != T![|] { | ||
97 | p.eat(T![async]); | ||
98 | has_mods = true; | ||
99 | } | ||
100 | |||
101 | // test_err unsafe_block_in_mod | ||
102 | // fn foo(){} unsafe { } fn bar(){} | ||
103 | if p.at(T![unsafe]) && p.nth(1) != T!['{'] { | ||
104 | p.eat(T![unsafe]); | ||
105 | has_mods = true; | ||
106 | } | ||
107 | |||
108 | if p.at(T![extern]) { | ||
109 | has_mods = true; | ||
110 | abi(p); | ||
111 | } | ||
112 | if p.at(IDENT) && p.at_contextual_kw("auto") && p.nth(1) == T![trait] { | ||
113 | p.bump_remap(T![auto]); | ||
114 | has_mods = true; | ||
115 | } | ||
116 | |||
117 | if p.at(IDENT) | ||
118 | && p.at_contextual_kw("default") | ||
119 | && (match p.nth(1) { | ||
120 | T![impl] => true, | ||
121 | T![unsafe] => { | ||
122 | // test default_unsafe_impl | ||
123 | // default unsafe impl Foo {} | ||
124 | |||
125 | // test default_unsafe_fn | ||
126 | // impl T for Foo { | ||
127 | // default unsafe fn foo() {} | ||
128 | // } | ||
129 | if p.nth(2) == T![impl] || p.nth(2) == T![fn] { | ||
130 | p.bump_remap(T![default]); | ||
131 | p.bump(T![unsafe]); | ||
132 | has_mods = true; | ||
133 | } | ||
134 | false | ||
135 | } | ||
136 | T![fn] | T![type] | T![const] => { | ||
137 | if let ItemFlavor::Mod = flavor { | ||
138 | true | ||
139 | } else { | ||
140 | false | ||
141 | } | ||
142 | } | ||
143 | _ => false, | ||
144 | }) | ||
145 | { | ||
146 | p.bump_remap(T![default]); | ||
147 | has_mods = true; | ||
148 | } | ||
149 | if p.at(IDENT) && p.at_contextual_kw("existential") && p.nth(1) == T![type] { | ||
150 | p.bump_remap(T![existential]); | ||
151 | has_mods = true; | ||
152 | } | ||
153 | |||
154 | // items | ||
155 | match p.current() { | ||
156 | // test async_fn | ||
157 | // async fn foo() {} | ||
158 | |||
159 | // test extern_fn | ||
160 | // extern fn foo() {} | ||
161 | |||
162 | // test const_fn | ||
163 | // const fn foo() {} | ||
164 | |||
165 | // test const_unsafe_fn | ||
166 | // const unsafe fn foo() {} | ||
167 | |||
168 | // test unsafe_extern_fn | ||
169 | // unsafe extern "C" fn foo() {} | ||
170 | |||
171 | // test unsafe_fn | ||
172 | // unsafe fn foo() {} | ||
173 | |||
174 | // test combined_fns | ||
175 | // async unsafe fn foo() {} | ||
176 | // const unsafe fn bar() {} | ||
177 | |||
178 | // test_err wrong_order_fns | ||
179 | // unsafe async fn foo() {} | ||
180 | // unsafe const fn bar() {} | ||
181 | T![fn] => { | ||
182 | fn_def(p); | ||
183 | m.complete(p, FN); | ||
184 | } | ||
185 | |||
186 | // test unsafe_trait | ||
187 | // unsafe trait T {} | ||
188 | |||
189 | // test auto_trait | ||
190 | // auto trait T {} | ||
191 | |||
192 | // test unsafe_auto_trait | ||
193 | // unsafe auto trait T {} | ||
194 | T![trait] => { | ||
195 | traits::trait_def(p); | ||
196 | m.complete(p, TRAIT); | ||
197 | } | ||
198 | |||
199 | // test unsafe_impl | ||
200 | // unsafe impl Foo {} | ||
201 | |||
202 | // test default_impl | ||
203 | // default impl Foo {} | ||
204 | |||
205 | // test_err default_fn_type | ||
206 | // trait T { | ||
207 | // default type T = Bar; | ||
208 | // default fn foo() {} | ||
209 | // } | ||
210 | |||
211 | // test default_fn_type | ||
212 | // impl T for Foo { | ||
213 | // default type T = Bar; | ||
214 | // default fn foo() {} | ||
215 | // } | ||
216 | T![const] => { | ||
217 | consts::const_def(p, m); | ||
218 | } | ||
219 | |||
220 | // test unsafe_default_impl | ||
221 | // unsafe default impl Foo {} | ||
222 | T![impl] => { | ||
223 | traits::impl_def(p); | ||
224 | m.complete(p, IMPL); | ||
225 | } | ||
226 | |||
227 | // test existential_type | ||
228 | // existential type Foo: Fn() -> usize; | ||
229 | T![type] => { | ||
230 | type_def(p, m); | ||
231 | } | ||
232 | _ => { | ||
233 | if !has_visibility && !has_mods { | ||
234 | return Err(m); | ||
235 | } else { | ||
236 | if has_mods { | ||
237 | p.error("expected existential, fn, trait or impl"); | ||
238 | } else { | ||
239 | p.error("expected an item"); | ||
240 | } | ||
241 | m.complete(p, ERROR); | ||
242 | } | ||
243 | } | ||
244 | } | ||
245 | Ok(()) | ||
246 | } | ||
247 | |||
248 | fn items_without_modifiers(p: &mut Parser, m: Marker) -> Result<(), Marker> { | ||
249 | let la = p.nth(1); | ||
250 | match p.current() { | ||
251 | // test extern_crate | ||
252 | // extern crate foo; | ||
253 | T![extern] if la == T![crate] => extern_crate_item(p, m), | ||
254 | T![type] => { | ||
255 | type_def(p, m); | ||
256 | } | ||
257 | T![mod] => mod_item(p, m), | ||
258 | T![struct] => { | ||
259 | // test struct_items | ||
260 | // struct Foo; | ||
261 | // struct Foo {} | ||
262 | // struct Foo(); | ||
263 | // struct Foo(String, usize); | ||
264 | // struct Foo { | ||
265 | // a: i32, | ||
266 | // b: f32, | ||
267 | // } | ||
268 | adt::struct_def(p, m); | ||
269 | } | ||
270 | // test pub_macro_def | ||
271 | // pub macro m($:ident) {} | ||
272 | T![macro] => { | ||
273 | macro_def(p, m); | ||
274 | } | ||
275 | IDENT if p.at_contextual_kw("union") && p.nth(1) == IDENT => { | ||
276 | // test union_items | ||
277 | // union Foo {} | ||
278 | // union Foo { | ||
279 | // a: i32, | ||
280 | // b: f32, | ||
281 | // } | ||
282 | adt::union_def(p, m); | ||
283 | } | ||
284 | T![enum] => adt::enum_def(p, m), | ||
285 | T![use] => use_item::use_item(p, m), | ||
286 | T![const] if (la == IDENT || la == T![_] || la == T![mut]) => consts::const_def(p, m), | ||
287 | T![static] => consts::static_def(p, m), | ||
288 | // test extern_block | ||
289 | // extern {} | ||
290 | T![extern] | ||
291 | if la == T!['{'] || ((la == STRING || la == RAW_STRING) && p.nth(2) == T!['{']) => | ||
292 | { | ||
293 | abi(p); | ||
294 | extern_item_list(p); | ||
295 | m.complete(p, EXTERN_BLOCK); | ||
296 | } | ||
297 | _ => return Err(m), | ||
298 | }; | ||
299 | Ok(()) | ||
300 | } | ||
301 | |||
302 | fn extern_crate_item(p: &mut Parser, m: Marker) { | ||
303 | assert!(p.at(T![extern])); | ||
304 | p.bump(T![extern]); | ||
305 | assert!(p.at(T![crate])); | ||
306 | p.bump(T![crate]); | ||
307 | |||
308 | if p.at(T![self]) { | ||
309 | p.bump(T![self]); | ||
310 | } else { | ||
311 | name_ref(p); | ||
312 | } | ||
313 | |||
314 | opt_alias(p); | ||
315 | p.expect(T![;]); | ||
316 | m.complete(p, EXTERN_CRATE); | ||
317 | } | ||
318 | |||
319 | pub(crate) fn extern_item_list(p: &mut Parser) { | ||
320 | assert!(p.at(T!['{'])); | ||
321 | let m = p.start(); | ||
322 | p.bump(T!['{']); | ||
323 | mod_contents(p, true); | ||
324 | p.expect(T!['}']); | ||
325 | m.complete(p, EXTERN_ITEM_LIST); | ||
326 | } | ||
327 | |||
328 | fn fn_def(p: &mut Parser) { | ||
329 | assert!(p.at(T![fn])); | ||
330 | p.bump(T![fn]); | ||
331 | |||
332 | name_r(p, ITEM_RECOVERY_SET); | ||
333 | // test function_type_params | ||
334 | // fn foo<T: Clone + Copy>(){} | ||
335 | type_params::opt_type_param_list(p); | ||
336 | |||
337 | if p.at(T!['(']) { | ||
338 | params::param_list_fn_def(p); | ||
339 | } else { | ||
340 | p.error("expected function arguments"); | ||
341 | } | ||
342 | // test function_ret_type | ||
343 | // fn foo() {} | ||
344 | // fn bar() -> () {} | ||
345 | opt_fn_ret_type(p); | ||
346 | |||
347 | // test function_where_clause | ||
348 | // fn foo<T>() where T: Copy {} | ||
349 | type_params::opt_where_clause(p); | ||
350 | |||
351 | // test fn_decl | ||
352 | // trait T { fn foo(); } | ||
353 | if p.at(T![;]) { | ||
354 | p.bump(T![;]); | ||
355 | } else { | ||
356 | expressions::block_expr(p) | ||
357 | } | ||
358 | } | ||
359 | |||
360 | // test type_item | ||
361 | // type Foo = Bar; | ||
362 | fn type_def(p: &mut Parser, m: Marker) { | ||
363 | assert!(p.at(T![type])); | ||
364 | p.bump(T![type]); | ||
365 | |||
366 | name(p); | ||
367 | |||
368 | // test type_item_type_params | ||
369 | // type Result<T> = (); | ||
370 | type_params::opt_type_param_list(p); | ||
371 | |||
372 | if p.at(T![:]) { | ||
373 | type_params::bounds(p); | ||
374 | } | ||
375 | |||
376 | // test type_item_where_clause | ||
377 | // type Foo where Foo: Copy = (); | ||
378 | type_params::opt_where_clause(p); | ||
379 | if p.eat(T![=]) { | ||
380 | types::type_(p); | ||
381 | } | ||
382 | p.expect(T![;]); | ||
383 | m.complete(p, TYPE_ALIAS); | ||
384 | } | ||
385 | |||
386 | pub(crate) fn mod_item(p: &mut Parser, m: Marker) { | ||
387 | assert!(p.at(T![mod])); | ||
388 | p.bump(T![mod]); | ||
389 | |||
390 | name(p); | ||
391 | if p.at(T!['{']) { | ||
392 | mod_item_list(p); | ||
393 | } else if !p.eat(T![;]) { | ||
394 | p.error("expected `;` or `{`"); | ||
395 | } | ||
396 | m.complete(p, MODULE); | ||
397 | } | ||
398 | |||
399 | pub(crate) fn mod_item_list(p: &mut Parser) { | ||
400 | assert!(p.at(T!['{'])); | ||
401 | let m = p.start(); | ||
402 | p.bump(T!['{']); | ||
403 | mod_contents(p, true); | ||
404 | p.expect(T!['}']); | ||
405 | m.complete(p, ITEM_LIST); | ||
406 | } | ||
407 | |||
408 | // test macro_def | ||
409 | // macro m { ($i:ident) => {} } | ||
410 | // macro m($i:ident) {} | ||
411 | fn macro_def(p: &mut Parser, m: Marker) { | ||
412 | p.expect(T![macro]); | ||
413 | name_r(p, ITEM_RECOVERY_SET); | ||
414 | if p.at(T!['{']) { | ||
415 | token_tree(p); | ||
416 | } else if !p.at(T!['(']) { | ||
417 | p.error("unmatched `(`"); | ||
418 | } else { | ||
419 | let m = p.start(); | ||
420 | token_tree(p); | ||
421 | match p.current() { | ||
422 | T!['{'] | T!['['] | T!['('] => token_tree(p), | ||
423 | _ => p.error("expected `{`, `[`, `(`"), | ||
424 | } | ||
425 | m.complete(p, TOKEN_TREE); | ||
426 | } | ||
427 | |||
428 | m.complete(p, MACRO_DEF); | ||
429 | } | ||
430 | |||
431 | fn macro_call(p: &mut Parser) -> BlockLike { | ||
432 | assert!(paths::is_use_path_start(p)); | ||
433 | paths::use_path(p); | ||
434 | macro_call_after_excl(p) | ||
435 | } | ||
436 | |||
437 | pub(super) fn macro_call_after_excl(p: &mut Parser) -> BlockLike { | ||
438 | p.expect(T![!]); | ||
439 | if p.at(IDENT) { | ||
440 | name(p); | ||
441 | } | ||
442 | // Special-case `macro_rules! try`. | ||
443 | // This is a hack until we do proper edition support | ||
444 | |||
445 | // test try_macro_rules | ||
446 | // macro_rules! try { () => {} } | ||
447 | if p.at(T![try]) { | ||
448 | let m = p.start(); | ||
449 | p.bump_remap(IDENT); | ||
450 | m.complete(p, NAME); | ||
451 | } | ||
452 | |||
453 | match p.current() { | ||
454 | T!['{'] => { | ||
455 | token_tree(p); | ||
456 | BlockLike::Block | ||
457 | } | ||
458 | T!['('] | T!['['] => { | ||
459 | token_tree(p); | ||
460 | BlockLike::NotBlock | ||
461 | } | ||
462 | _ => { | ||
463 | p.error("expected `{`, `[`, `(`"); | ||
464 | BlockLike::NotBlock | ||
465 | } | ||
466 | } | ||
467 | } | ||
468 | |||
469 | pub(crate) fn token_tree(p: &mut Parser) { | ||
470 | let closing_paren_kind = match p.current() { | ||
471 | T!['{'] => T!['}'], | ||
472 | T!['('] => T![')'], | ||
473 | T!['['] => T![']'], | ||
474 | _ => unreachable!(), | ||
475 | }; | ||
476 | let m = p.start(); | ||
477 | p.bump_any(); | ||
478 | while !p.at(EOF) && !p.at(closing_paren_kind) { | ||
479 | match p.current() { | ||
480 | T!['{'] | T!['('] | T!['['] => token_tree(p), | ||
481 | T!['}'] => { | ||
482 | p.error("unmatched `}`"); | ||
483 | m.complete(p, TOKEN_TREE); | ||
484 | return; | ||
485 | } | ||
486 | T![')'] | T![']'] => p.err_and_bump("unmatched brace"), | ||
487 | _ => p.bump_any(), | ||
488 | } | ||
489 | } | ||
490 | p.expect(closing_paren_kind); | ||
491 | m.complete(p, TOKEN_TREE); | ||
492 | } | ||