From d94124e3b4a4380ad23c1a317fd3943664b7182a Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 4 Feb 2018 13:53:47 +0300 Subject: Somewhat more san directory structure --- src/parser/grammar/items/mod.rs | 196 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 196 insertions(+) create mode 100644 src/parser/grammar/items/mod.rs (limited to 'src/parser/grammar/items/mod.rs') diff --git a/src/parser/grammar/items/mod.rs b/src/parser/grammar/items/mod.rs new file mode 100644 index 000000000..3612802e1 --- /dev/null +++ b/src/parser/grammar/items/mod.rs @@ -0,0 +1,196 @@ +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().message("expected `fn` or `{`").emit(); + 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 + } + }, + // TODO: auto trait + // test unsafe_trait + // unsafe trait T {} + UNSAFE_KW if la == TRAIT_KW => { + p.bump(); + traits::trait_item(p); + TRAIT_ITEM + } + // TODO: default impl + // test unsafe_impl + // unsafe impl Foo {} + UNSAFE_KW if la == IMPL_KW => { + p.bump(); + traits::impl_item(p); + IMPL_ITEM + } + 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().message("expected function arguments").emit(); + } + + 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); + } +} -- cgit v1.2.3