aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEdwin Cheng <[email protected]>2019-04-19 12:33:29 +0100
committerEdwin Cheng <[email protected]>2019-04-19 12:33:29 +0100
commit762819864fd78f2e8904a6bde6181b80895db360 (patch)
tree1cade2d6eb97a52785a91258cfd3f03c57fba027
parent8092b6487f301bf9219c55fc714744fa2616fb9a (diff)
add block matcher
-rw-r--r--crates/ra_mbe/src/lib.rs19
-rw-r--r--crates/ra_mbe/src/mbe_expander.rs5
-rw-r--r--crates/ra_mbe/src/subtree_parser.rs4
-rw-r--r--crates/ra_mbe/src/tt_cursor.rs5
-rw-r--r--crates/ra_parser/src/grammar.rs27
-rw-r--r--crates/ra_parser/src/lib.rs4
6 files changed, 64 insertions, 0 deletions
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)
743 ); 743 );
744 assert_expansion(&rules, "foo! { { 1; } }", "fn foo () {1 ;}"); 744 assert_expansion(&rules, "foo! { { 1; } }", "fn foo () {1 ;}");
745 } 745 }
746
747 #[test]
748 fn test_meta() {
749 let rules = create_rules(
750 r#"
751 macro_rules! foo {
752 ($ i:meta) => (
753 #[$ i]
754 fn bar() {}
755 )
756 }
757"#,
758 );
759 assert_expansion(
760 &rules,
761 r#"foo! { cfg(target_os = "windows") }"#,
762 r#"# [cfg (target_os = "windows")] fn bar () {}"#,
763 );
764 }
746} 765}
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<Bindings,
166 input.eat_block().ok_or(ExpandError::UnexpectedToken)?.clone(); 166 input.eat_block().ok_or(ExpandError::UnexpectedToken)?.clone();
167 res.inner.insert(text.clone(), Binding::Simple(block.into())); 167 res.inner.insert(text.clone(), Binding::Simple(block.into()));
168 } 168 }
169 "meta" => {
170 let meta =
171 input.eat_meta().ok_or(ExpandError::UnexpectedToken)?.clone();
172 res.inner.insert(text.clone(), Binding::Simple(meta.into()));
173 }
169 "item" => { 174 "item" => {
170 let item = 175 let item =
171 input.eat_item().ok_or(ExpandError::UnexpectedToken)?.clone(); 176 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> {
50 self.parse(ra_parser::parse_block) 50 self.parse(ra_parser::parse_block)
51 } 51 }
52 52
53 pub fn parse_meta(self) -> Option<tt::TokenTree> {
54 self.parse(ra_parser::parse_meta)
55 }
56
53 pub fn parse_item(self) -> Option<tt::TokenTree> { 57 pub fn parse_item(self) -> Option<tt::TokenTree> {
54 self.parse(ra_parser::parse_item) 58 self.parse(ra_parser::parse_item)
55 } 59 }
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> {
109 parser.parse_block() 109 parser.parse_block()
110 } 110 }
111 111
112 pub(crate) fn eat_meta(&mut self) -> Option<tt::TokenTree> {
113 let parser = Parser::new(&mut self.pos, self.subtree);
114 parser.parse_meta()
115 }
116
112 pub(crate) fn eat_item(&mut self) -> Option<tt::TokenTree> { 117 pub(crate) fn eat_item(&mut self) -> Option<tt::TokenTree> {
113 let parser = Parser::new(&mut self.pos, self.subtree); 118 let parser = Parser::new(&mut self.pos, self.subtree);
114 parser.parse_item() 119 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) {
99 expressions::block(p); 99 expressions::block(p);
100} 100}
101 101
102// Parse a meta item , which excluded [], e.g : #[ MetaItem ]
103pub(crate) fn meta_item(p: &mut Parser) {
104 fn is_delimiter(p: &mut Parser) -> bool {
105 match p.current() {
106 L_CURLY | L_PAREN | L_BRACK => true,
107 _ => false,
108 }
109 }
110
111 if is_delimiter(p) {
112 items::token_tree(p);
113 return;
114 }
115
116 let m = p.start();
117 while !p.at(EOF) {
118 if is_delimiter(p) {
119 items::token_tree(p);
120 break;
121 } else {
122 p.bump();
123 }
124 }
125
126 m.complete(p, TOKEN_TREE);
127}
128
102pub(crate) fn item(p: &mut Parser) { 129pub(crate) fn item(p: &mut Parser) {
103 items::item_or_macro(p, true, items::ItemFlavor::Mod) 130 items::item_or_macro(p, true, items::ItemFlavor::Mod)
104} 131}
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)
98 parse_from_tokens(token_source, tree_sink, grammar::block); 98 parse_from_tokens(token_source, tree_sink, grammar::block);
99} 99}
100 100
101pub fn parse_meta(token_source: &dyn TokenSource, tree_sink: &mut dyn TreeSink) {
102 parse_from_tokens(token_source, tree_sink, grammar::meta_item);
103}
104
101/// Parse given tokens into the given sink as an item 105/// Parse given tokens into the given sink as an item
102pub fn parse_item(token_source: &dyn TokenSource, tree_sink: &mut dyn TreeSink) { 106pub fn parse_item(token_source: &dyn TokenSource, tree_sink: &mut dyn TreeSink) {
103 parse_from_tokens(token_source, tree_sink, grammar::item); 107 parse_from_tokens(token_source, tree_sink, grammar::item);