From 762819864fd78f2e8904a6bde6181b80895db360 Mon Sep 17 00:00:00 2001 From: Edwin Cheng Date: Fri, 19 Apr 2019 19:33:29 +0800 Subject: add block matcher --- crates/ra_mbe/src/lib.rs | 19 +++++++++++++++++++ crates/ra_mbe/src/mbe_expander.rs | 5 +++++ crates/ra_mbe/src/subtree_parser.rs | 4 ++++ crates/ra_mbe/src/tt_cursor.rs | 5 +++++ crates/ra_parser/src/grammar.rs | 27 +++++++++++++++++++++++++++ crates/ra_parser/src/lib.rs | 4 ++++ 6 files changed, 64 insertions(+) (limited to 'crates') diff --git a/crates/ra_mbe/src/lib.rs b/crates/ra_mbe/src/lib.rs index 8e3167e55..d7462d09d 100644 --- a/crates/ra_mbe/src/lib.rs +++ b/crates/ra_mbe/src/lib.rs @@ -743,4 +743,23 @@ MACRO_ITEMS@[0; 40) ); assert_expansion(&rules, "foo! { { 1; } }", "fn foo () {1 ;}"); } + + #[test] + fn test_meta() { + let rules = create_rules( + r#" + macro_rules! foo { + ($ i:meta) => ( + #[$ i] + fn bar() {} + ) + } +"#, + ); + assert_expansion( + &rules, + r#"foo! { cfg(target_os = "windows") }"#, + r#"# [cfg (target_os = "windows")] fn bar () {}"#, + ); + } } diff --git a/crates/ra_mbe/src/mbe_expander.rs b/crates/ra_mbe/src/mbe_expander.rs index a74e477d6..6ada580cc 100644 --- a/crates/ra_mbe/src/mbe_expander.rs +++ b/crates/ra_mbe/src/mbe_expander.rs @@ -166,6 +166,11 @@ fn match_lhs(pattern: &crate::Subtree, input: &mut TtCursor) -> Result { + let meta = + input.eat_meta().ok_or(ExpandError::UnexpectedToken)?.clone(); + res.inner.insert(text.clone(), Binding::Simple(meta.into())); + } "item" => { let item = input.eat_item().ok_or(ExpandError::UnexpectedToken)?.clone(); diff --git a/crates/ra_mbe/src/subtree_parser.rs b/crates/ra_mbe/src/subtree_parser.rs index 2b11186c4..5d5557113 100644 --- a/crates/ra_mbe/src/subtree_parser.rs +++ b/crates/ra_mbe/src/subtree_parser.rs @@ -50,6 +50,10 @@ impl<'a> Parser<'a> { self.parse(ra_parser::parse_block) } + pub fn parse_meta(self) -> Option { + self.parse(ra_parser::parse_meta) + } + pub fn parse_item(self) -> Option { self.parse(ra_parser::parse_item) } diff --git a/crates/ra_mbe/src/tt_cursor.rs b/crates/ra_mbe/src/tt_cursor.rs index d700aad69..04bb6b563 100644 --- a/crates/ra_mbe/src/tt_cursor.rs +++ b/crates/ra_mbe/src/tt_cursor.rs @@ -109,6 +109,11 @@ impl<'a> TtCursor<'a> { parser.parse_block() } + pub(crate) fn eat_meta(&mut self) -> Option { + let parser = Parser::new(&mut self.pos, self.subtree); + parser.parse_meta() + } + pub(crate) fn eat_item(&mut self) -> Option { let parser = Parser::new(&mut self.pos, self.subtree); parser.parse_item() diff --git a/crates/ra_parser/src/grammar.rs b/crates/ra_parser/src/grammar.rs index 7bae0bc7b..13c50c79c 100644 --- a/crates/ra_parser/src/grammar.rs +++ b/crates/ra_parser/src/grammar.rs @@ -99,6 +99,33 @@ pub(crate) fn block(p: &mut Parser) { expressions::block(p); } +// Parse a meta item , which excluded [], e.g : #[ MetaItem ] +pub(crate) fn meta_item(p: &mut Parser) { + fn is_delimiter(p: &mut Parser) -> bool { + match p.current() { + L_CURLY | L_PAREN | L_BRACK => true, + _ => false, + } + } + + if is_delimiter(p) { + items::token_tree(p); + return; + } + + let m = p.start(); + while !p.at(EOF) { + if is_delimiter(p) { + items::token_tree(p); + break; + } else { + p.bump(); + } + } + + m.complete(p, TOKEN_TREE); +} + pub(crate) fn item(p: &mut Parser) { items::item_or_macro(p, true, items::ItemFlavor::Mod) } diff --git a/crates/ra_parser/src/lib.rs b/crates/ra_parser/src/lib.rs index 1e6a00642..4787b5b9e 100644 --- a/crates/ra_parser/src/lib.rs +++ b/crates/ra_parser/src/lib.rs @@ -98,6 +98,10 @@ pub fn parse_block(token_source: &dyn TokenSource, tree_sink: &mut dyn TreeSink) parse_from_tokens(token_source, tree_sink, grammar::block); } +pub fn parse_meta(token_source: &dyn TokenSource, tree_sink: &mut dyn TreeSink) { + parse_from_tokens(token_source, tree_sink, grammar::meta_item); +} + /// Parse given tokens into the given sink as an item pub fn parse_item(token_source: &dyn TokenSource, tree_sink: &mut dyn TreeSink) { parse_from_tokens(token_source, tree_sink, grammar::item); -- cgit v1.2.3