1 //! FIXME: write short doc here
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,
18 // macro_rules! foo {}
22 pub(super) fn mod_contents(p: &mut Parser, stop_on_r_curly: bool) {
23 attributes::inner_attributes(p);
24 while !p.at(EOF) && !(stop_on_r_curly && p.at(T!['}'])) {
25 item_or_macro(p, stop_on_r_curly, ItemFlavor::Mod)
29 pub(super) enum ItemFlavor {
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
39 pub(super) fn item_or_macro(p: &mut Parser, stop_on_r_curly: bool, flavor: ItemFlavor) {
41 attributes::outer_attributes(p);
42 let m = match maybe_item(p, m, flavor) {
46 "expected item, found `;`\n\
47 consider removing this semicolon",
54 if paths::is_use_path_start(p) {
56 BlockLike::Block => (),
57 BlockLike::NotBlock => {
61 m.complete(p, MACRO_CALL);
65 error_block(p, "expected an item");
66 } else if p.at(T!['}']) && !stop_on_r_curly {
68 p.error("unmatched `}`");
71 } else if !p.at(EOF) && !p.at(T!['}']) {
72 p.err_and_bump("expected an item");
74 p.error("expected an item");
79 pub(super) fn maybe_item(p: &mut Parser, m: Marker, flavor: ItemFlavor) -> Result<(), Marker> {
81 // fn foo() { pub 92; }
82 let has_visibility = opt_visibility(p);
84 let m = match items_without_modifiers(p, m) {
85 Ok(()) => return Ok(()),
89 let mut has_mods = false;
92 has_mods |= p.eat(T![const]);
94 // test_err unsafe_block_in_mod
95 // fn foo(){} unsafe { } fn bar(){}
96 if p.at(T![unsafe]) && p.nth(1) != T!['{'] {
101 // test_err async_without_semicolon
102 // fn foo() { let _ = async {} }
103 if p.at(T![async]) && p.nth(1) != T!['{'] && p.nth(1) != T![move] && p.nth(1) != T![|] {
108 if p.at(T![extern]) {
112 if p.at(IDENT) && p.at_contextual_kw("auto") && p.nth(1) == T![trait] {
113 p.bump_remap(T![auto]);
118 && p.at_contextual_kw("default")
121 T![fn] | T![type] => {
122 if let ItemFlavor::Mod = flavor {
131 p.bump_remap(T![default]);
134 if p.at(IDENT) && p.at_contextual_kw("existential") && p.nth(1) == T![type] {
135 p.bump_remap(T![existential]);
145 // extern fn foo() {}
150 // test const_unsafe_fn
151 // const unsafe fn foo() {}
153 // test unsafe_extern_fn
154 // unsafe extern "C" fn foo() {}
157 // unsafe fn foo() {}
160 // unsafe async fn foo() {}
161 // const unsafe fn bar() {}
163 // test_err wrong_order_fns
164 // async unsafe fn foo() {}
165 // unsafe const fn bar() {}
168 m.complete(p, FN_DEF);
177 // test unsafe_auto_trait
178 // unsafe auto trait T {}
180 traits::trait_def(p);
181 m.complete(p, TRAIT_DEF);
185 // unsafe impl Foo {}
188 // default impl Foo {}
190 // test_err default_fn_type
192 // default type T = Bar;
193 // default fn foo() {}
196 // test default_fn_type
198 // default type T = Bar;
199 // default fn foo() {}
202 // test unsafe_default_impl
203 // unsafe default impl Foo {}
205 traits::impl_block(p);
206 m.complete(p, IMPL_BLOCK);
209 // test existential_type
210 // existential type Foo: Fn() -> usize;
215 if !has_visibility && !has_mods {
219 p.error("expected existential, fn, trait or impl");
221 p.error("expected an item");
223 m.complete(p, ERROR);
230 fn items_without_modifiers(p: &mut Parser, m: Marker) -> Result<(), Marker> {
235 T![extern] if la == T![crate] => extern_crate_item(p, m),
239 T![mod] => mod_item(p, m),
245 // struct Foo(String, usize);
250 adt::struct_def(p, m);
252 // test pub_macro_def
253 // pub macro m($:ident) {}
257 IDENT if p.at_contextual_kw("union") && p.nth(1) == IDENT => {
264 adt::union_def(p, m);
266 T![enum] => adt::enum_def(p, m),
267 T![use] => use_item::use_item(p, m),
268 T![const] if (la == IDENT || la == T![_] || la == T![mut]) => consts::const_def(p, m),
269 T![static] => consts::static_def(p, m),
273 if la == T!['{'] || ((la == STRING || la == RAW_STRING) && p.nth(2) == T!['{']) =>
277 m.complete(p, EXTERN_BLOCK);
284 fn extern_crate_item(p: &mut Parser, m: Marker) {
285 assert!(p.at(T![extern]));
287 assert!(p.at(T![crate]));
292 m.complete(p, EXTERN_CRATE_ITEM);
295 pub(crate) fn extern_item_list(p: &mut Parser) {
296 assert!(p.at(T!['{']));
299 mod_contents(p, true);
301 m.complete(p, EXTERN_ITEM_LIST);
304 fn fn_def(p: &mut Parser, flavor: ItemFlavor) {
305 assert!(p.at(T![fn]));
308 name_r(p, ITEM_RECOVERY_SET);
309 // test function_type_params
310 // fn foo<T: Clone + Copy>(){}
311 type_params::opt_type_param_list(p);
315 ItemFlavor::Mod => params::param_list(p),
316 ItemFlavor::Trait => params::param_list_opt_patterns(p),
319 p.error("expected function arguments");
321 // test function_ret_type
326 // test function_where_clause
327 // fn foo<T>() where T: Copy {}
328 type_params::opt_where_clause(p);
331 // trait T { fn foo(); }
335 expressions::block(p)
341 fn type_def(p: &mut Parser, m: Marker) {
342 assert!(p.at(T![type]));
347 // test type_item_type_params
348 // type Result<T> = ();
349 type_params::opt_type_param_list(p);
352 type_params::bounds(p);
355 // test type_item_where_clause
356 // type Foo where Foo: Copy = ();
357 type_params::opt_where_clause(p);
362 m.complete(p, TYPE_ALIAS_DEF);
365 pub(crate) fn mod_item(p: &mut Parser, m: Marker) {
366 assert!(p.at(T![mod]));
372 } else if !p.eat(T![;]) {
373 p.error("expected `;` or `{`");
375 m.complete(p, MODULE);
378 pub(crate) fn mod_item_list(p: &mut Parser) {
379 assert!(p.at(T!['{']));
382 mod_contents(p, true);
384 m.complete(p, ITEM_LIST);
388 // macro m { ($i:ident) => {} }
389 // macro m($i:ident) {}
390 fn macro_def(p: &mut Parser, m: Marker) {
395 } else if !p.at(T!['(']) {
396 p.error("unmatched `(`");
401 T!['{'] | T!['['] | T!['('] => token_tree(p),
402 _ => p.error("expected `{`, `[`, `(`"),
404 m.complete(p, TOKEN_TREE);
407 m.complete(p, MACRO_DEF);
410 fn macro_call(p: &mut Parser) -> BlockLike {
411 assert!(paths::is_use_path_start(p));
413 macro_call_after_excl(p)
416 pub(super) fn macro_call_after_excl(p: &mut Parser) -> BlockLike {
426 T!['('] | T!['['] => {
431 p.error("expected `{`, `[`, `(`");
437 pub(crate) fn token_tree(p: &mut Parser) {
438 let closing_paren_kind = match p.current() {
446 while !p.at(EOF) && !p.at(closing_paren_kind) {
448 T!['{'] | T!['('] | T!['['] => token_tree(p),
450 p.error("unmatched `}`");
451 m.complete(p, TOKEN_TREE);
454 T![')'] | T![']'] => p.err_and_bump("unmatched brace"),
458 p.expect(closing_paren_kind);
459 m.complete(p, TOKEN_TREE);