1 mod consts;
2 mod adt;
3 mod traits;
4 mod use_item;
5
6 pub(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 };
12 use super::*;
13
14 // test mod_contents
15 // fn foo() {}
16 // macro_rules! foo {}
17 // foo::bar!();
18 // super::baz! {}
19 // struct S;
mod_contents(p: &mut Parser<'_>, stop_on_r_curly: bool)20 pub(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);
24 }
25 }
26
27 pub(super) const ITEM_RECOVERY_SET: TokenSet = TokenSet::new(&[
28 T![fn],
29 T![struct],
30 T![enum],
31 T![impl],
32 T![trait],
33 T![const],
34 T![static],
35 T![let],
36 T![mod],
37 T![pub],
38 T![crate],
39 T![use],
40 T![macro],
41 T![;],
42 ]);
43
item_or_macro(p: &mut Parser<'_>, stop_on_r_curly: bool)44 pub(super) fn item_or_macro(p: &mut Parser<'_>, stop_on_r_curly: bool) {
45 let m = p.start();
46 attributes::outer_attrs(p);
47
48 let m = match opt_item(p, m) {
49 Ok(()) => {
50 if p.at(T![;]) {
51 p.err_and_bump(
52 "expected item, found `;`\n\
53 consider removing this semicolon",
54 );
55 }
56 return;
57 }
58 Err(m) => m,
59 };
60
61 if paths::is_use_path_start(p) {
62 match macro_call(p) {
63 BlockLike::Block => (),
64 BlockLike::NotBlock => {
65 p.expect(T![;]);
66 }
67 }
68 m.complete(p, MACRO_CALL);
69 return;
70 }
71
72 m.abandon(p);
73 match p.current() {
74 T!['{'] => error_block(p, "expected an item"),
75 T!['}'] if !stop_on_r_curly => {
76 let e = p.start();
77 p.error("unmatched `}`");
78 p.bump(T!['}']);
79 e.complete(p, ERROR);
80 }
81 EOF | T!['}'] => p.error("expected an item"),
82 _ => p.err_and_bump("expected an item"),
83 }
84 }
85
86 /// Try to parse an item, completing `m` in case of success.
opt_item(p: &mut Parser<'_>, m: Marker) -> Result<(), Marker>87 pub(super) fn opt_item(p: &mut Parser<'_>, m: Marker) -> Result<(), Marker> {
88 // test_err pub_expr
89 // fn foo() { pub 92; }
90 let has_visibility = opt_visibility(p, false);
91
92 let m = match opt_item_without_modifiers(p, m) {
93 Ok(()) => return Ok(()),
94 Err(m) => m,
95 };
96
97 let mut has_mods = false;
98 let mut has_extern = false;
99
100 // modifiers
101 if p.at(T![const]) && p.nth(1) != T!['{'] {
102 p.eat(T![const]);
103 has_mods = true;
104 }
105
106 // test_err async_without_semicolon
107 // fn foo() { let _ = async {} }
108 if p.at(T![async]) && !matches!(p.nth(1), T!['{'] | T![move] | T![|]) {
109 p.eat(T![async]);
110 has_mods = true;
111 }
112
113 // test_err unsafe_block_in_mod
114 // fn foo(){} unsafe { } fn bar(){}
115 if p.at(T![unsafe]) && p.nth(1) != T!['{'] {
116 p.eat(T![unsafe]);
117 has_mods = true;
118 }
119
120 if p.at(T![extern]) {
121 has_extern = true;
122 has_mods = true;
123 abi(p);
124 }
125 if p.at_contextual_kw(T![auto]) && p.nth(1) == T![trait] {
126 p.bump_remap(T![auto]);
127 has_mods = true;
128 }
129
130 // test default_item
131 // default impl T for Foo {}
132 if p.at_contextual_kw(T![default]) {
133 match p.nth(1) {
134 T![fn] | T![type] | T![const] | T![impl] => {
135 p.bump_remap(T![default]);
136 has_mods = true;
137 }
138 // test default_unsafe_item
139 // default unsafe impl T for Foo {
140 // default unsafe fn foo() {}
141 // }
142 T![unsafe] if matches!(p.nth(2), T![impl] | T![fn]) => {
143 p.bump_remap(T![default]);
144 p.bump(T![unsafe]);
145 has_mods = true;
146 }
147 // test default_async_fn
148 // impl T for Foo {
149 // default async fn foo() {}
150 // }
151 T![async] => {
152 let mut maybe_fn = p.nth(2);
153 let is_unsafe = if matches!(maybe_fn, T![unsafe]) {
154 // test default_async_unsafe_fn
155 // impl T for Foo {
156 // default async unsafe fn foo() {}
157 // }
158 maybe_fn = p.nth(3);
159 true
160 } else {
161 false
162 };
163
164 if matches!(maybe_fn, T![fn]) {
165 p.bump_remap(T![default]);
166 p.bump(T![async]);
167 if is_unsafe {
168 p.bump(T![unsafe]);
169 }
170 has_mods = true;
171 }
172 }
173 _ => (),
174 }
175 }
176
177 // test existential_type
178 // existential type Foo: Fn() -> usize;
179 if p.at_contextual_kw(T![existential]) && p.nth(1) == T![type] {
180 p.bump_remap(T![existential]);
181 has_mods = true;
182 }
183
184 // items
185 match p.current() {
186 T![fn] => fn_(p, m),
187
188 T![const] if p.nth(1) != T!['{'] => consts::konst(p, m),
189
190 T![trait] => traits::trait_(p, m),
191 T![impl] => traits::impl_(p, m),
192
193 T![type] => type_alias(p, m),
194
195 // test extern_block
196 // unsafe extern "C" {}
197 // extern {}
198 T!['{'] if has_extern => {
199 extern_item_list(p);
200 m.complete(p, EXTERN_BLOCK);
201 }
202
203 _ if has_visibility || has_mods => {
204 if has_mods {
205 p.error("expected existential, fn, trait or impl");
206 } else {
207 p.error("expected an item");
208 }
209 m.complete(p, ERROR);
210 }
211
212 _ => return Err(m),
213 }
214 Ok(())
215 }
216
opt_item_without_modifiers(p: &mut Parser<'_>, m: Marker) -> Result<(), Marker>217 fn opt_item_without_modifiers(p: &mut Parser<'_>, m: Marker) -> Result<(), Marker> {
218 let la = p.nth(1);
219 match p.current() {
220 T![extern] if la == T![crate] => extern_crate(p, m),
221 T![use] => use_item::use_(p, m),
222 T![mod] => mod_item(p, m),
223
224 T![type] => type_alias(p, m),
225 T![struct] => adt::strukt(p, m),
226 T![enum] => adt::enum_(p, m),
227 IDENT if p.at_contextual_kw(T![union]) && p.nth(1) == IDENT => adt::union(p, m),
228
229 T![macro] => macro_def(p, m),
230 IDENT if p.at_contextual_kw(T![macro_rules]) && p.nth(1) == BANG => macro_rules(p, m),
231
232 T![const] if (la == IDENT || la == T![_] || la == T![mut]) => consts::konst(p, m),
233 T![static] if (la == IDENT || la == T![_] || la == T![mut]) => consts::static_(p, m),
234
235 _ => return Err(m),
236 };
237 Ok(())
238 }
239
240 // test extern_crate
241 // extern crate foo;
extern_crate(p: &mut Parser<'_>, m: Marker)242 fn extern_crate(p: &mut Parser<'_>, m: Marker) {
243 p.bump(T![extern]);
244 p.bump(T![crate]);
245
246 if p.at(T![self]) {
247 // test extern_crate_self
248 // extern crate self;
249 let m = p.start();
250 p.bump(T![self]);
251 m.complete(p, NAME_REF);
252 } else {
253 name_ref(p);
254 }
255
256 // test extern_crate_rename
257 // extern crate foo as bar;
258 opt_rename(p);
259 p.expect(T![;]);
260 m.complete(p, EXTERN_CRATE);
261 }
262
263 // test mod_item
264 // mod a;
mod_item(p: &mut Parser<'_>, m: Marker)265 pub(crate) fn mod_item(p: &mut Parser<'_>, m: Marker) {
266 p.bump(T![mod]);
267 name(p);
268 if p.at(T!['{']) {
269 // test mod_item_curly
270 // mod b { }
271 item_list(p);
272 } else if !p.eat(T![;]) {
273 p.error("expected `;` or `{`");
274 }
275 m.complete(p, MODULE);
276 }
277
278 // test type_alias
279 // type Foo = Bar;
type_alias(p: &mut Parser<'_>, m: Marker)280 fn type_alias(p: &mut Parser<'_>, m: Marker) {
281 p.bump(T![type]);
282
283 name(p);
284
285 // test type_item_type_params
286 // type Result<T> = ();
287 generic_params::opt_generic_param_list(p);
288
289 if p.at(T![:]) {
290 generic_params::bounds(p);
291 }
292
293 // test type_item_where_clause_deprecated
294 // type Foo where Foo: Copy = ();
295 generic_params::opt_where_clause(p);
296 if p.eat(T![=]) {
297 types::type_(p);
298 }
299
300 // test type_item_where_clause
301 // type Foo = () where Foo: Copy;
302 generic_params::opt_where_clause(p);
303
304 p.expect(T![;]);
305 m.complete(p, TYPE_ALIAS);
306 }
307
item_list(p: &mut Parser<'_>)308 pub(crate) fn item_list(p: &mut Parser<'_>) {
309 assert!(p.at(T!['{']));
310 let m = p.start();
311 p.bump(T!['{']);
312 mod_contents(p, true);
313 p.expect(T!['}']);
314 m.complete(p, ITEM_LIST);
315 }
316
extern_item_list(p: &mut Parser<'_>)317 pub(crate) fn extern_item_list(p: &mut Parser<'_>) {
318 assert!(p.at(T!['{']));
319 let m = p.start();
320 p.bump(T!['{']);
321 mod_contents(p, true);
322 p.expect(T!['}']);
323 m.complete(p, EXTERN_ITEM_LIST);
324 }
325
macro_rules(p: &mut Parser<'_>, m: Marker)326 fn macro_rules(p: &mut Parser<'_>, m: Marker) {
327 assert!(p.at_contextual_kw(T![macro_rules]));
328 p.bump_remap(T![macro_rules]);
329 p.expect(T![!]);
330
331 if p.at(IDENT) {
332 name(p);
333 }
334 // Special-case `macro_rules! try`.
335 // This is a hack until we do proper edition support
336
337 // test try_macro_rules
338 // macro_rules! try { () => {} }
339 if p.at(T![try]) {
340 let m = p.start();
341 p.bump_remap(IDENT);
342 m.complete(p, NAME);
343 }
344
345 match p.current() {
346 // test macro_rules_non_brace
347 // macro_rules! m ( ($i:ident) => {} );
348 // macro_rules! m [ ($i:ident) => {} ];
349 T!['['] | T!['('] => {
350 token_tree(p);
351 p.expect(T![;]);
352 }
353 T!['{'] => token_tree(p),
354 _ => p.error("expected `{`, `[`, `(`"),
355 }
356 m.complete(p, MACRO_RULES);
357 }
358
359 // test macro_def
360 // macro m($i:ident) {}
macro_def(p: &mut Parser<'_>, m: Marker)361 fn macro_def(p: &mut Parser<'_>, m: Marker) {
362 p.expect(T![macro]);
363 name_r(p, ITEM_RECOVERY_SET);
364 if p.at(T!['{']) {
365 // test macro_def_curly
366 // macro m { ($i:ident) => {} }
367 token_tree(p);
368 } else if p.at(T!['(']) {
369 let m = p.start();
370 token_tree(p);
371 match p.current() {
372 T!['{'] | T!['['] | T!['('] => token_tree(p),
373 _ => p.error("expected `{`, `[`, `(`"),
374 }
375 m.complete(p, TOKEN_TREE);
376 } else {
377 p.error("unmatched `(`");
378 }
379
380 m.complete(p, MACRO_DEF);
381 }
382
383 // test fn
384 // fn foo() {}
fn_(p: &mut Parser<'_>, m: Marker)385 fn fn_(p: &mut Parser<'_>, m: Marker) {
386 p.bump(T![fn]);
387
388 name_r(p, ITEM_RECOVERY_SET);
389 // test function_type_params
390 // fn foo<T: Clone + Copy>(){}
391 generic_params::opt_generic_param_list(p);
392
393 if p.at(T!['(']) {
394 params::param_list_fn_def(p);
395 } else {
396 p.error("expected function arguments");
397 }
398 // test function_ret_type
399 // fn foo() {}
400 // fn bar() -> () {}
401 opt_ret_type(p);
402
403 // test function_where_clause
404 // fn foo<T>() where T: Copy {}
405 generic_params::opt_where_clause(p);
406
407 if p.at(T![;]) {
408 // test fn_decl
409 // trait T { fn foo(); }
410 p.bump(T![;]);
411 } else {
412 expressions::block_expr(p);
413 }
414 m.complete(p, FN);
415 }
416
macro_call(p: &mut Parser<'_>) -> BlockLike417 fn macro_call(p: &mut Parser<'_>) -> BlockLike {
418 assert!(paths::is_use_path_start(p));
419 paths::use_path(p);
420 macro_call_after_excl(p)
421 }
422
macro_call_after_excl(p: &mut Parser<'_>) -> BlockLike423 pub(super) fn macro_call_after_excl(p: &mut Parser<'_>) -> BlockLike {
424 p.expect(T![!]);
425
426 match p.current() {
427 T!['{'] => {
428 token_tree(p);
429 BlockLike::Block
430 }
431 T!['('] | T!['['] => {
432 token_tree(p);
433 BlockLike::NotBlock
434 }
435 _ => {
436 p.error("expected `{`, `[`, `(`");
437 BlockLike::NotBlock
438 }
439 }
440 }
441
token_tree(p: &mut Parser<'_>)442 pub(crate) fn token_tree(p: &mut Parser<'_>) {
443 let closing_paren_kind = match p.current() {
444 T!['{'] => T!['}'],
445 T!['('] => T![')'],
446 T!['['] => T![']'],
447 _ => unreachable!(),
448 };
449 let m = p.start();
450 p.bump_any();
451 while !p.at(EOF) && !p.at(closing_paren_kind) {
452 match p.current() {
453 T!['{'] | T!['('] | T!['['] => token_tree(p),
454 T!['}'] => {
455 p.error("unmatched `}`");
456 m.complete(p, TOKEN_TREE);
457 return;
458 }
459 T![')'] | T![']'] => p.err_and_bump("unmatched brace"),
460 _ => p.bump_any(),
461 }
462 }
463 p.expect(closing_paren_kind);
464 m.complete(p, TOKEN_TREE);
465 }
466