aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_syntax/src/grammar/items.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_syntax/src/grammar/items.rs')
-rw-r--r--crates/ra_syntax/src/grammar/items.rs392
1 files changed, 0 insertions, 392 deletions
diff --git a/crates/ra_syntax/src/grammar/items.rs b/crates/ra_syntax/src/grammar/items.rs
deleted file mode 100644
index 4b962c1f3..000000000
--- a/crates/ra_syntax/src/grammar/items.rs
+++ /dev/null
@@ -1,392 +0,0 @@
1mod consts;
2mod nominal;
3mod traits;
4mod use_item;
5
6pub(crate) use self::{
7 expressions::{match_arm_list, named_field_list},
8 nominal::{enum_variant_list, named_field_def_list},
9 traits::{impl_item_list, trait_item_list},
10 use_item::use_tree_list,
11};
12use super::*;
13
14// test mod_contents
15// fn foo() {}
16// macro_rules! foo {}
17// foo::bar!();
18// super::baz! {}
19// struct S;
20pub(super) fn mod_contents(p: &mut Parser, stop_on_r_curly: bool) {
21 attributes::inner_attributes(p);
22 while !p.at(EOF) && !(stop_on_r_curly && p.at(R_CURLY)) {
23 item_or_macro(p, stop_on_r_curly, ItemFlavor::Mod)
24 }
25}
26
27pub(super) enum ItemFlavor {
28 Mod,
29 Trait,
30}
31
32pub(super) const ITEM_RECOVERY_SET: TokenSet = token_set![
33 FN_KW, STRUCT_KW, ENUM_KW, IMPL_KW, TRAIT_KW, CONST_KW, STATIC_KW, LET_KW, MOD_KW, PUB_KW,
34 CRATE_KW
35];
36
37pub(super) fn item_or_macro(p: &mut Parser, stop_on_r_curly: bool, flavor: ItemFlavor) {
38 let m = p.start();
39 attributes::outer_attributes(p);
40 match maybe_item(p, flavor) {
41 MaybeItem::Item(kind) => {
42 m.complete(p, kind);
43 }
44 MaybeItem::None => {
45 if paths::is_path_start(p) {
46 match macro_call(p) {
47 BlockLike::Block => (),
48 BlockLike::NotBlock => {
49 p.expect(SEMI);
50 }
51 }
52 m.complete(p, MACRO_CALL);
53 } else {
54 m.abandon(p);
55 if p.at(L_CURLY) {
56 error_block(p, "expected an item");
57 } else if p.at(R_CURLY) && !stop_on_r_curly {
58 let e = p.start();
59 p.error("unmatched `}`");
60 p.bump();
61 e.complete(p, ERROR);
62 } else if !p.at(EOF) && !p.at(R_CURLY) {
63 p.err_and_bump("expected an item");
64 } else {
65 p.error("expected an item");
66 }
67 }
68 }
69 MaybeItem::Modifiers => {
70 p.error("expected fn, trait or impl");
71 m.complete(p, ERROR);
72 }
73 }
74}
75
76pub(super) enum MaybeItem {
77 None,
78 Item(SyntaxKind),
79 Modifiers,
80}
81
82pub(super) fn maybe_item(p: &mut Parser, flavor: ItemFlavor) -> MaybeItem {
83 opt_visibility(p);
84 if let Some(kind) = items_without_modifiers(p) {
85 return MaybeItem::Item(kind);
86 }
87
88 let mut has_mods = false;
89 // modifiers
90 has_mods |= p.eat(CONST_KW);
91
92 // test_err unsafe_block_in_mod
93 // fn foo(){} unsafe { } fn bar(){}
94 if p.at(UNSAFE_KW) && p.nth(1) != L_CURLY {
95 p.eat(UNSAFE_KW);
96 has_mods = true;
97 }
98 if p.at(EXTERN_KW) {
99 has_mods = true;
100 abi(p);
101 }
102 if p.at(IDENT) && p.at_contextual_kw("auto") && p.nth(1) == TRAIT_KW {
103 p.bump_remap(AUTO_KW);
104 has_mods = true;
105 }
106 if p.at(IDENT) && p.at_contextual_kw("default") && p.nth(1) == IMPL_KW {
107 p.bump_remap(DEFAULT_KW);
108 has_mods = true;
109 }
110
111 // items
112 let kind = match p.current() {
113 // test extern_fn
114 // extern fn foo() {}
115
116 // test const_fn
117 // const fn foo() {}
118
119 // test const_unsafe_fn
120 // const unsafe fn foo() {}
121
122 // test unsafe_extern_fn
123 // unsafe extern "C" fn foo() {}
124
125 // test unsafe_fn
126 // unsafe fn foo() {}
127 FN_KW => {
128 fn_def(p, flavor);
129 FN_DEF
130 }
131
132 // test unsafe_trait
133 // unsafe trait T {}
134
135 // test auto_trait
136 // auto trait T {}
137
138 // test unsafe_auto_trait
139 // unsafe auto trait T {}
140 TRAIT_KW => {
141 traits::trait_def(p);
142 TRAIT_DEF
143 }
144
145 // test unsafe_impl
146 // unsafe impl Foo {}
147
148 // test default_impl
149 // default impl Foo {}
150
151 // test unsafe_default_impl
152 // unsafe default impl Foo {}
153 IMPL_KW => {
154 traits::impl_block(p);
155 IMPL_BLOCK
156 }
157 _ => {
158 return if has_mods { MaybeItem::Modifiers } else { MaybeItem::None };
159 }
160 };
161
162 MaybeItem::Item(kind)
163}
164
165fn items_without_modifiers(p: &mut Parser) -> Option<SyntaxKind> {
166 let la = p.nth(1);
167 let kind = match p.current() {
168 // test extern_crate
169 // extern crate foo;
170 EXTERN_KW if la == CRATE_KW => {
171 extern_crate_item(p);
172 EXTERN_CRATE_ITEM
173 }
174 TYPE_KW => {
175 type_def(p);
176 TYPE_DEF
177 }
178 MOD_KW => {
179 mod_item(p);
180 MODULE
181 }
182 STRUCT_KW => {
183 // test struct_items
184 // struct Foo;
185 // struct Foo {}
186 // struct Foo();
187 // struct Foo(String, usize);
188 // struct Foo {
189 // a: i32,
190 // b: f32,
191 // }
192 nominal::struct_def(p, STRUCT_KW);
193 if p.at(SEMI) {
194 p.err_and_bump(
195 "expected item, found `;`\n\
196 consider removing this semicolon",
197 );
198 }
199 STRUCT_DEF
200 }
201 IDENT if p.at_contextual_kw("union") && p.nth(1) == IDENT => {
202 // test union_items
203 // union Foo {}
204 // union Foo {
205 // a: i32,
206 // b: f32,
207 // }
208 nominal::struct_def(p, UNION_KW);
209 STRUCT_DEF
210 }
211 ENUM_KW => {
212 nominal::enum_def(p);
213 ENUM_DEF
214 }
215 USE_KW => {
216 use_item::use_item(p);
217 USE_ITEM
218 }
219 CONST_KW if (la == IDENT || la == MUT_KW) => {
220 consts::const_def(p);
221 CONST_DEF
222 }
223 STATIC_KW => {
224 consts::static_def(p);
225 STATIC_DEF
226 }
227 // test extern_block
228 // extern {}
229 EXTERN_KW
230 if la == L_CURLY || ((la == STRING || la == RAW_STRING) && p.nth(2) == L_CURLY) =>
231 {
232 abi(p);
233 extern_item_list(p);
234 EXTERN_BLOCK
235 }
236 _ => return None,
237 };
238 Some(kind)
239}
240
241fn extern_crate_item(p: &mut Parser) {
242 assert!(p.at(EXTERN_KW));
243 p.bump();
244 assert!(p.at(CRATE_KW));
245 p.bump();
246 name_ref(p);
247 opt_alias(p);
248 p.expect(SEMI);
249}
250
251pub(crate) fn extern_item_list(p: &mut Parser) {
252 assert!(p.at(L_CURLY));
253 let m = p.start();
254 p.bump();
255 mod_contents(p, true);
256 p.expect(R_CURLY);
257 m.complete(p, EXTERN_ITEM_LIST);
258}
259
260fn fn_def(p: &mut Parser, flavor: ItemFlavor) {
261 assert!(p.at(FN_KW));
262 p.bump();
263
264 name_r(p, ITEM_RECOVERY_SET);
265 // test function_type_params
266 // fn foo<T: Clone + Copy>(){}
267 type_params::opt_type_param_list(p);
268
269 if p.at(L_PAREN) {
270 match flavor {
271 ItemFlavor::Mod => params::param_list(p),
272 ItemFlavor::Trait => params::param_list_opt_patterns(p),
273 }
274 } else {
275 p.error("expected function arguments");
276 }
277 // test function_ret_type
278 // fn foo() {}
279 // fn bar() -> () {}
280 opt_fn_ret_type(p);
281
282 // test function_where_clause
283 // fn foo<T>() where T: Copy {}
284 type_params::opt_where_clause(p);
285
286 // test fn_decl
287 // trait T { fn foo(); }
288 if p.at(SEMI) {
289 p.bump();
290 } else {
291 expressions::block(p)
292 }
293}
294
295// test type_item
296// type Foo = Bar;
297fn type_def(p: &mut Parser) {
298 assert!(p.at(TYPE_KW));
299 p.bump();
300
301 name(p);
302
303 // test type_item_type_params
304 // type Result<T> = ();
305 type_params::opt_type_param_list(p);
306
307 if p.at(COLON) {
308 type_params::bounds(p);
309 }
310
311 // test type_item_where_clause
312 // type Foo where Foo: Copy = ();
313 type_params::opt_where_clause(p);
314
315 if p.eat(EQ) {
316 types::type_(p);
317 }
318 p.expect(SEMI);
319}
320
321pub(crate) fn mod_item(p: &mut Parser) {
322 assert!(p.at(MOD_KW));
323 p.bump();
324
325 name(p);
326 if p.at(L_CURLY) {
327 mod_item_list(p);
328 } else if !p.eat(SEMI) {
329 p.error("expected `;` or `{`");
330 }
331}
332
333pub(crate) fn mod_item_list(p: &mut Parser) {
334 assert!(p.at(L_CURLY));
335 let m = p.start();
336 p.bump();
337 mod_contents(p, true);
338 p.expect(R_CURLY);
339 m.complete(p, ITEM_LIST);
340}
341
342fn macro_call(p: &mut Parser) -> BlockLike {
343 assert!(paths::is_path_start(p));
344 paths::use_path(p);
345 macro_call_after_excl(p)
346}
347
348pub(super) fn macro_call_after_excl(p: &mut Parser) -> BlockLike {
349 p.expect(EXCL);
350 if p.at(IDENT) {
351 name(p);
352 }
353 match p.current() {
354 L_CURLY => {
355 token_tree(p);
356 BlockLike::Block
357 }
358 L_PAREN | L_BRACK => {
359 token_tree(p);
360 BlockLike::NotBlock
361 }
362 _ => {
363 p.error("expected `{`, `[`, `(`");
364 BlockLike::NotBlock
365 }
366 }
367}
368
369pub(crate) fn token_tree(p: &mut Parser) {
370 let closing_paren_kind = match p.current() {
371 L_CURLY => R_CURLY,
372 L_PAREN => R_PAREN,
373 L_BRACK => R_BRACK,
374 _ => unreachable!(),
375 };
376 let m = p.start();
377 p.bump();
378 while !p.at(EOF) && !p.at(closing_paren_kind) {
379 match p.current() {
380 L_CURLY | L_PAREN | L_BRACK => token_tree(p),
381 R_CURLY => {
382 p.error("unmatched `}`");
383 m.complete(p, TOKEN_TREE);
384 return;
385 }
386 R_PAREN | R_BRACK => p.err_and_bump("unmatched brace"),
387 _ => p.bump(),
388 }
389 }
390 p.expect(closing_paren_kind);
391 m.complete(p, TOKEN_TREE);
392}