aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_parser/src/grammar/items.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_parser/src/grammar/items.rs')
-rw-r--r--crates/ra_parser/src/grammar/items.rs492
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
3mod consts;
4mod adt;
5mod traits;
6mod use_item;
7
8pub(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};
14use super::*;
15
16// test mod_contents
17// fn foo() {}
18// macro_rules! foo {}
19// foo::bar!();
20// super::baz! {}
21// struct S;
22pub(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
29pub(super) enum ItemFlavor {
30 Mod,
31 Trait,
32}
33
34pub(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
39pub(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
79pub(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
248fn 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
302fn 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
319pub(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
328fn 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;
362fn 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
386pub(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
399pub(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) {}
411fn 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
431fn 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
437pub(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
469pub(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}