From c871022f9810547f3eeaa5af3a3dc4bc0c85a386 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 5 Aug 2018 14:08:46 +0300 Subject: item-macros --- src/grammar.ron | 2 ++ src/grammar/items/mod.rs | 78 ++++++++++++++++++++++++++++++++++++++----- src/grammar/items/traits.rs | 2 +- src/syntax_kinds/generated.rs | 4 +++ 4 files changed, 77 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/grammar.ron b/src/grammar.ron index 9f80b3ebf..0a79eeb95 100644 --- a/src/grammar.ron +++ b/src/grammar.ron @@ -109,6 +109,8 @@ Grammar( "TRAIT_ITEM", "IMPL_ITEM", "TYPE_ITEM", + "MACRO_CALL", + "TOKEN_TREE", "PAREN_TYPE", "TUPLE_TYPE", diff --git a/src/grammar/items/mod.rs b/src/grammar/items/mod.rs index 1ed0aea07..8f766901e 100644 --- a/src/grammar/items/mod.rs +++ b/src/grammar/items/mod.rs @@ -5,27 +5,43 @@ mod structs; mod traits; mod use_item; +// test mod_contents +// fn foo() {} +// macro_rules! foo {} +// foo::bar!(); +// super::baz! {} +// struct S; 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, stop_on_r_curly) + item_or_macro(p, stop_on_r_curly) } } -pub(super) fn item(p: &mut Parser, stop_on_r_curly: bool) { +pub(super) fn item_or_macro(p: &mut Parser, stop_on_r_curly: bool) { let m = p.start(); match maybe_item(p) { MaybeItem::Item(kind) => { m.complete(p, kind); } MaybeItem::None => { - m.abandon(p); - if p.at(L_CURLY) { - error_block(p, "expected an item"); - } else if !p.at(EOF) && !(stop_on_r_curly && p.at(R_CURLY)) { - p.err_and_bump("expected an item"); + if paths::is_path_start(p) { + match macro_call(p) { + MacroFlavor::Curly => (), + MacroFlavor::NonCurly => { + p.expect(SEMI); + } + } + m.complete(p, MACRO_CALL); } else { - p.error("expected an item"); + m.abandon(p); + if p.at(L_CURLY) { + error_block(p, "expected an item"); + } else if !p.at(EOF) && !(stop_on_r_curly && p.at(R_CURLY)) { + p.err_and_bump("expected an item"); + } else { + p.error("expected an item"); + } } } MaybeItem::Modifiers => { @@ -260,3 +276,49 @@ fn mod_item(p: &mut Parser) { } } } + +enum MacroFlavor { + Curly, + NonCurly, +} + +fn macro_call(p: &mut Parser) -> MacroFlavor { + assert!(paths::is_path_start(p)); + paths::use_path(p); + p.expect(EXCL); + p.eat(IDENT); + let flavor = match p.current() { + L_CURLY => { + token_tree(p); + MacroFlavor::Curly + } + L_PAREN | L_BRACK => { + token_tree(p); + MacroFlavor::NonCurly + } + _ => { + p.error("expected `{`, `[`, `(`"); + MacroFlavor::NonCurly + }, + }; + + flavor +} + +fn token_tree(p: &mut Parser) { + let closing_paren_kind = match p.current() { + L_CURLY => R_CURLY, + L_PAREN => R_PAREN, + L_BRACK => R_BRACK, + _ => unreachable!(), + }; + p.bump(); + while !p.at(EOF) && !p.at(closing_paren_kind) { + match p.current() { + L_CURLY | L_PAREN | L_BRACK => token_tree(p), + R_CURLY | R_PAREN | R_BRACK => p.err_and_bump("unmatched brace"), + _ => p.bump() + } + }; + p.expect(closing_paren_kind); +} diff --git a/src/grammar/items/traits.rs b/src/grammar/items/traits.rs index 0614e8ab6..7c0935371 100644 --- a/src/grammar/items/traits.rs +++ b/src/grammar/items/traits.rs @@ -45,7 +45,7 @@ pub(super) fn impl_item(p: &mut Parser) { // fn bar(&self) {} // } while !p.at(EOF) && !p.at(R_CURLY) { - item(p, true); + item_or_macro(p, true); } p.expect(R_CURLY); } diff --git a/src/syntax_kinds/generated.rs b/src/syntax_kinds/generated.rs index 1d3d3b9c1..8ac13fd63 100644 --- a/src/syntax_kinds/generated.rs +++ b/src/syntax_kinds/generated.rs @@ -103,6 +103,8 @@ pub enum SyntaxKind { TRAIT_ITEM, IMPL_ITEM, TYPE_ITEM, + MACRO_CALL, + TOKEN_TREE, PAREN_TYPE, TUPLE_TYPE, NEVER_TYPE, @@ -322,6 +324,8 @@ impl SyntaxKind { TRAIT_ITEM => &SyntaxInfo { name: "TRAIT_ITEM" }, IMPL_ITEM => &SyntaxInfo { name: "IMPL_ITEM" }, TYPE_ITEM => &SyntaxInfo { name: "TYPE_ITEM" }, + MACRO_CALL => &SyntaxInfo { name: "MACRO_CALL" }, + TOKEN_TREE => &SyntaxInfo { name: "TOKEN_TREE" }, PAREN_TYPE => &SyntaxInfo { name: "PAREN_TYPE" }, TUPLE_TYPE => &SyntaxInfo { name: "TUPLE_TYPE" }, NEVER_TYPE => &SyntaxInfo { name: "NEVER_TYPE" }, -- cgit v1.2.3