use super::*; mod structs; mod use_item; mod consts; mod traits; pub(super) fn mod_contents(p: &mut Parser, stop_on_r_curly: bool) { attributes::inner_attributes(p); while !p.at(EOF) && !(stop_on_r_curly && p.at(R_CURLY)) { item(p); } } pub(super) const ITEM_FIRST: TokenSet = token_set![ EXTERN_KW, MOD_KW, USE_KW, STRUCT_KW, ENUM_KW, FN_KW, PUB_KW, POUND ]; fn item(p: &mut Parser) { let item = p.start(); attributes::outer_attributes(p); visibility(p); let la = p.nth(1); let item_kind = match p.current() { USE_KW => { use_item::use_item(p); USE_ITEM } // test extern_crate // extern crate foo; EXTERN_KW if la == CRATE_KW => { extern_crate_item(p); EXTERN_CRATE_ITEM } EXTERN_KW => { abi(p); match p.current() { // test extern_fn // extern fn foo() {} FN_KW => { fn_item(p); FN_ITEM } // test extern_block // extern {} L_CURLY => { extern_block(p); EXTERN_BLOCK } // test extern_struct // extern struct Foo; _ => { item.abandon(p); p.error("expected `fn` or `{`"); return; } } } STATIC_KW => { consts::static_item(p); STATIC_ITEM } CONST_KW => match p.nth(1) { // test const_fn // const fn foo() {} FN_KW => { p.bump(); fn_item(p); FN_ITEM } // test const_unsafe_fn // const unsafe fn foo() {} UNSAFE_KW if p.nth(2) == FN_KW => { p.bump(); p.bump(); fn_item(p); FN_ITEM } _ => { consts::const_item(p); CONST_ITEM } }, UNSAFE_KW => { p.bump(); let la = p.nth(1); match p.current() { // test unsafe_trait // unsafe trait T {} TRAIT_KW => { traits::trait_item(p); TRAIT_ITEM } // test unsafe_auto_trait // unsafe auto trait T {} IDENT if p.at_kw("auto") && la == TRAIT_KW => { p.bump_remap(AUTO_KW); traits::trait_item(p); TRAIT_ITEM } // test unsafe_impl // unsafe impl Foo {} IMPL_KW => { traits::impl_item(p); IMPL_ITEM } // test unsafe_default_impl // unsafe default impl Foo {} IDENT if p.at_kw("default") && la == IMPL_KW => { p.bump_remap(DEFAULT_KW); traits::impl_item(p); IMPL_ITEM } // test unsafe_extern_fn // unsafe extern "C" fn foo() {} EXTERN_KW => { abi(p); if !p.at(FN_KW) { item.abandon(p); p.error("expected function"); return; } fn_item(p); FN_ITEM } // test unsafe_fn // unsafe fn foo() {} FN_KW => { fn_item(p); FN_ITEM } t => { item.abandon(p); let message = "expected `trait`, `impl` or `fn`"; // test unsafe_block_in_mod // fn foo(){} unsafe { } fn bar(){} if t == L_CURLY { error_block(p, message); } else { p.error(message); } return; } } } MOD_KW => { mod_item(p); MOD_ITEM } STRUCT_KW => { structs::struct_item(p); STRUCT_ITEM } ENUM_KW => { structs::enum_item(p); ENUM_ITEM } FN_KW => { fn_item(p); FN_ITEM } L_CURLY => { item.abandon(p); error_block(p, "expected item"); return; } err_token => { item.abandon(p); let message = if err_token == SEMI { //TODO: if the item is incomplete, this message is misleading "expected item, found `;`\n\ consider removing this semicolon" } else { "expected item" }; p.err_and_bump(message); return; } }; item.complete(p, item_kind); } fn extern_crate_item(p: &mut Parser) { assert!(p.at(EXTERN_KW)); p.bump(); assert!(p.at(CRATE_KW)); p.bump(); p.expect(IDENT) && alias(p) && p.expect(SEMI); } fn extern_block(p: &mut Parser) { assert!(p.at(L_CURLY)); p.bump(); p.expect(R_CURLY); } fn mod_item(p: &mut Parser) { assert!(p.at(MOD_KW)); p.bump(); if p.expect(IDENT) && !p.eat(SEMI) { if p.expect(L_CURLY) { mod_contents(p, true); p.expect(R_CURLY); } } } fn abi(p: &mut Parser) { assert!(p.at(EXTERN_KW)); let abi = p.start(); p.bump(); match p.current() { STRING | RAW_STRING => p.bump(), _ => (), } abi.complete(p, ABI); } fn fn_item(p: &mut Parser) { assert!(p.at(FN_KW)); p.bump(); p.expect(IDENT); if p.at(L_PAREN) { fn_value_parameters(p); } else { p.error("expected function arguments"); } if p.at(L_CURLY) { p.expect(L_CURLY); p.expect(R_CURLY); } fn fn_value_parameters(p: &mut Parser) { assert!(p.at(L_PAREN)); p.bump(); p.expect(R_PAREN); } }