1mod adt;
2mod consts;
3mod traits;
4mod use_item;
5
6pub(crate) use self::{
7 adt::{record_field_list, variant_list},
8 expressions::{match_arm_list, record_expr_field_list},
9 traits::assoc_item_list,
10 use_item::use_tree_list,
11};
12use super::*;
13
14pub(super) fn mod_contents(p: &mut Parser<'_>, stop_on_r_curly: bool) {
21 attributes::inner_attrs(p);
22 while !(p.at(EOF) || (p.at(T!['}']) && stop_on_r_curly)) {
23 item_or_macro(p, stop_on_r_curly, true);
25 }
26}
27
28pub(super) const ITEM_RECOVERY_SET: TokenSet = TokenSet::new(&[
29 T![fn],
30 T![struct],
31 T![enum],
32 T![impl],
33 T![trait],
34 T![const],
35 T![async],
36 T![unsafe],
37 T![extern],
38 T![static],
39 T![let],
40 T![mod],
41 T![pub],
42 T![crate],
43 T![use],
44 T![macro],
45 T![;],
46]);
47
48pub(super) fn item_or_macro(p: &mut Parser<'_>, stop_on_r_curly: bool, is_in_extern: bool) {
49 let m = p.start();
50 attributes::outer_attrs(p);
51
52 let m = match opt_item(p, m, is_in_extern) {
53 Ok(()) => {
54 if p.at(T![;]) {
55 p.err_and_bump(
56 "expected item, found `;`\n\
57 consider removing this semicolon",
58 );
59 }
60 return;
61 }
62 Err(m) => m,
63 };
64
65 if paths::is_use_path_start(p) {
78 paths::use_path(p);
79 if p.at(T![!]) {
84 macro_call(p, m);
85 return;
86 } else {
87 m.complete(p, ERROR);
88 p.error("expected an item");
89 return;
90 }
91 }
92
93 m.abandon(p);
94 match p.current() {
95 T!['{'] => error_block(p, "expected an item"),
96 T!['}'] if !stop_on_r_curly => {
97 let e = p.start();
98 p.error("unmatched `}`");
99 p.bump(T!['}']);
100 e.complete(p, ERROR);
101 }
102 EOF | T!['}'] => p.error("expected an item"),
103 T![let] => error_let_stmt(p, "expected an item"),
104 _ => p.err_and_bump("expected an item"),
105 }
106}
107
108pub(super) fn opt_item(p: &mut Parser<'_>, m: Marker, is_in_extern: bool) -> Result<(), Marker> {
110 let has_visibility = opt_visibility(p, false);
113
114 let m = match opt_item_without_modifiers(p, m) {
115 Ok(()) => return Ok(()),
116 Err(m) => m,
117 };
118
119 let mut has_mods = false;
120 let mut has_extern = false;
121
122 if p.at(T![const]) && p.nth(1) != T!['{'] {
124 p.eat(T![const]);
125 has_mods = true;
126 }
127
128 if p.at(T![async])
131 && (!matches!(p.nth(1), T!['{'] | T![gen] | T![move] | T![|])
132 || matches!((p.nth(1), p.nth(2)), (T![gen], T![fn])))
133 {
134 p.eat(T![async]);
135 has_mods = true;
136 }
137
138 if p.at(T![gen]) && p.nth(1) == T![fn] {
142 p.eat(T![gen]);
143 has_mods = true;
144 }
145
146 if p.at(T![unsafe]) && p.nth(1) != T!['{'] {
149 p.eat(T![unsafe]);
150 has_mods = true;
151 }
152
153 if is_in_extern && p.at_contextual_kw(T![safe]) {
156 p.eat_contextual_kw(T![safe]);
157 has_mods = true;
158 }
159
160 if p.at(T![extern]) {
161 has_extern = true;
162 has_mods = true;
163 abi(p);
164 }
165 if p.at_contextual_kw(T![auto]) && p.nth(1) == T![trait] {
166 p.bump_remap(T![auto]);
167 has_mods = true;
168 }
169
170 if p.at_contextual_kw(T![default]) {
173 match p.nth(1) {
174 T![fn] | T![type] | T![const] | T![impl] => {
175 p.bump_remap(T![default]);
176 has_mods = true;
177 }
178 T![unsafe] if matches!(p.nth(2), T![impl] | T![fn]) => {
183 p.bump_remap(T![default]);
184 p.bump(T![unsafe]);
185 has_mods = true;
186 }
187 T![async]
192 if p.nth_at(2, T![fn]) || (p.nth_at(2, T![unsafe]) && p.nth_at(3, T![fn])) =>
193 {
194 p.bump_remap(T![default]);
195 p.bump(T![async]);
196
197 p.eat(T![unsafe]);
202
203 has_mods = true;
204 }
205 _ => (),
206 }
207 }
208
209 match p.current() {
211 T![fn] => fn_(p, m),
212
213 T![const] if p.nth(1) != T!['{'] => consts::konst(p, m),
214 T![static] if matches!(p.nth(1), IDENT | T![_] | T![mut]) => consts::static_(p, m),
215
216 T![trait] => traits::trait_(p, m),
217 T![impl] => traits::impl_(p, m),
218
219 T![type] => type_alias(p, m),
220
221 T!['{'] if has_extern => {
225 extern_item_list(p);
226 m.complete(p, EXTERN_BLOCK);
227 }
228
229 _ if has_visibility || has_mods => {
230 if has_mods {
231 p.error("expected fn, trait or impl");
232 } else {
233 p.error("expected an item");
234 }
235 m.complete(p, ERROR);
236 }
237
238 _ => return Err(m),
239 }
240 Ok(())
241}
242
243fn opt_item_without_modifiers(p: &mut Parser<'_>, m: Marker) -> Result<(), Marker> {
244 let la = p.nth(1);
245 match p.current() {
246 T![extern] if la == T![crate] => extern_crate(p, m),
247 T![use] => use_item::use_(p, m),
248 T![mod] => mod_item(p, m),
249
250 T![type] => type_alias(p, m),
251 T![struct] => adt::strukt(p, m),
252 T![enum] => adt::enum_(p, m),
253 IDENT if p.at_contextual_kw(T![union]) && p.nth(1) == IDENT => adt::union(p, m),
254
255 T![macro] => macro_def(p, m),
256 IDENT if p.at_contextual_kw(T![macro_rules]) && p.nth_at(1, BANG) && p.nth_at(2, IDENT) => {
258 macro_rules(p, m)
259 }
260
261 T![const] if (la == IDENT || la == T![_] || la == T![mut]) => consts::konst(p, m),
262 T![static] if (la == IDENT || la == T![_] || la == T![mut]) => consts::static_(p, m),
263
264 IDENT
265 if p.at_contextual_kw(T![builtin])
266 && p.nth_at(1, T![#])
267 && p.nth_at_contextual_kw(2, T![global_asm]) =>
268 {
269 p.bump_remap(T![builtin]);
270 p.bump(T![#]);
271 p.bump_remap(T![global_asm]);
272 expressions::parse_asm_expr(p, m);
275 }
276
277 _ => return Err(m),
278 };
279 Ok(())
280}
281
282fn extern_crate(p: &mut Parser<'_>, m: Marker) {
286 p.bump(T![extern]);
287 p.bump(T![crate]);
288
289 name_ref_or_self(p);
290
291 opt_rename(p);
295 p.expect(T![;]);
296 m.complete(p, EXTERN_CRATE);
297}
298
299pub(crate) fn mod_item(p: &mut Parser<'_>, m: Marker) {
302 p.bump(T![mod]);
303 name(p);
304 if p.at(T!['{']) {
305 item_list(p);
308 } else if !p.eat(T![;]) {
309 p.error("expected `;` or `{`");
310 }
311 m.complete(p, MODULE);
312}
313
314fn type_alias(p: &mut Parser<'_>, m: Marker) {
317 p.bump(T![type]);
318
319 name(p);
320
321 generic_params::opt_generic_param_list(p);
324
325 if p.at(T![:]) {
326 generic_params::bounds(p);
327 }
328
329 generic_params::opt_where_clause(p);
332 if p.eat(T![=]) {
333 types::type_(p);
334 }
335
336 generic_params::opt_where_clause(p);
339
340 p.expect(T![;]);
341 m.complete(p, TYPE_ALIAS);
342}
343
344pub(crate) fn item_list(p: &mut Parser<'_>) {
345 assert!(p.at(T!['{']));
346 let m = p.start();
347 p.bump(T!['{']);
348 mod_contents(p, true);
349 p.expect(T!['}']);
350 m.complete(p, ITEM_LIST);
351}
352
353pub(crate) fn extern_item_list(p: &mut Parser<'_>) {
354 assert!(p.at(T!['{']));
355 let m = p.start();
356 p.bump(T!['{']);
357 mod_contents(p, true);
358 p.expect(T!['}']);
359 m.complete(p, EXTERN_ITEM_LIST);
360}
361
362fn macro_rules(p: &mut Parser<'_>, m: Marker) {
365 assert!(p.at_contextual_kw(T![macro_rules]));
366 p.bump_remap(T![macro_rules]);
367 p.expect(T![!]);
368
369 name(p);
370
371 match p.current() {
372 T!['['] | T!['('] => {
376 token_tree(p);
377 p.expect(T![;]);
378 }
379 T!['{'] => token_tree(p),
380 _ => p.error("expected `{`, `[`, `(`"),
381 }
382 m.complete(p, MACRO_RULES);
383}
384
385fn macro_def(p: &mut Parser<'_>, m: Marker) {
388 p.expect(T![macro]);
389 name_r(p, ITEM_RECOVERY_SET);
390 if p.at(T!['{']) {
391 token_tree(p);
394 } else if p.at(T!['(']) {
395 token_tree(p);
396 match p.current() {
397 T!['{'] | T!['['] | T!['('] => token_tree(p),
398 _ => p.error("expected `{`, `[`, `(`"),
399 }
400 } else {
401 p.error("unmatched `(`");
402 }
403
404 m.complete(p, MACRO_DEF);
405}
406
407fn fn_(p: &mut Parser<'_>, m: Marker) {
410 p.bump(T![fn]);
411
412 name_r(p, ITEM_RECOVERY_SET);
413 generic_params::opt_generic_param_list(p);
416
417 if p.at(T!['(']) {
418 params::param_list_fn_def(p);
419 } else {
420 p.error("expected function arguments");
421 }
422 opt_ret_type(p);
426
427 while p.at(T![')']) | p.at(T![']']) | p.at(T![>]) {
431 p.err_and_bump("expected a curly brace");
433 }
434
435 generic_params::opt_where_clause(p);
438
439 if !p.eat(T![;]) {
442 expressions::block_expr(p);
443 }
444 m.complete(p, FN);
445}
446
447fn macro_call(p: &mut Parser<'_>, m: Marker) {
448 assert!(p.at(T![!]));
449 match macro_call_after_excl(p) {
450 BlockLike::Block => (),
451 BlockLike::NotBlock => {
452 p.expect(T![;]);
453 }
454 }
455 m.complete(p, MACRO_CALL);
456}
457
458pub(super) fn macro_call_after_excl(p: &mut Parser<'_>) -> BlockLike {
459 p.expect(T![!]);
460
461 match p.current() {
462 T!['{'] => {
463 token_tree(p);
464 BlockLike::Block
465 }
466 T!['('] | T!['['] => {
467 token_tree(p);
468 BlockLike::NotBlock
469 }
470 _ => {
471 p.error("expected `{`, `[`, `(`");
472 BlockLike::NotBlock
473 }
474 }
475}
476
477pub(crate) fn token_tree(p: &mut Parser<'_>) {
478 let closing_paren_kind = match p.current() {
479 T!['{'] => T!['}'],
480 T!['('] => T![')'],
481 T!['['] => T![']'],
482 _ => unreachable!(),
483 };
484 let m = p.start();
485 p.bump_any();
486 while !p.at(EOF) && !p.at(closing_paren_kind) {
487 match p.current() {
488 T!['{'] | T!['('] | T!['['] => token_tree(p),
489 T!['}'] => {
490 p.error("unmatched `}`");
491 m.complete(p, TOKEN_TREE);
492 return;
493 }
494 T![')'] | T![']'] => p.err_and_bump("unmatched brace"),
495 _ => p.bump_any(),
496 }
497 }
498 p.expect(closing_paren_kind);
499 m.complete(p, TOKEN_TREE);
500}