diff options
author | Edwin Cheng <[email protected]> | 2019-04-18 03:21:36 +0100 |
---|---|---|
committer | Edwin Cheng <[email protected]> | 2019-04-18 03:21:36 +0100 |
commit | e944fd059de93f305d6a8c40cfac5ebe84548771 (patch) | |
tree | 9e7ff9215e3490169c63c12e03c2eb03ca59ba20 | |
parent | 112fd0ec7d65b5f23865410fd3e188e761d97110 (diff) |
Add `item` matcher in mbe
-rw-r--r-- | crates/ra_mbe/src/lib.rs | 44 | ||||
-rw-r--r-- | crates/ra_mbe/src/mbe_expander.rs | 8 | ||||
-rw-r--r-- | crates/ra_mbe/src/subtree_parser.rs | 4 | ||||
-rw-r--r-- | crates/ra_mbe/src/tt_cursor.rs | 5 | ||||
-rw-r--r-- | crates/ra_parser/src/grammar.rs | 4 | ||||
-rw-r--r-- | crates/ra_parser/src/lib.rs | 5 |
6 files changed, 70 insertions, 0 deletions
diff --git a/crates/ra_mbe/src/lib.rs b/crates/ra_mbe/src/lib.rs index a1f438906..2f47e32d3 100644 --- a/crates/ra_mbe/src/lib.rs +++ b/crates/ra_mbe/src/lib.rs | |||
@@ -597,4 +597,48 @@ SOURCE_FILE@[0; 40) | |||
597 | assert_expansion(&rules, "foo! { 2 }", "fn bar () {2 ;}"); | 597 | assert_expansion(&rules, "foo! { 2 }", "fn bar () {2 ;}"); |
598 | assert_expansion(&rules, "foo! { let a = 0 }", "fn bar () {let a = 0 ;}"); | 598 | assert_expansion(&rules, "foo! { let a = 0 }", "fn bar () {let a = 0 ;}"); |
599 | } | 599 | } |
600 | |||
601 | #[test] | ||
602 | fn test_single_item() { | ||
603 | let rules = create_rules( | ||
604 | r#" | ||
605 | macro_rules! foo { | ||
606 | ($ i:item) => ( | ||
607 | $ i | ||
608 | ) | ||
609 | } | ||
610 | "#, | ||
611 | ); | ||
612 | assert_expansion(&rules, "foo! {mod c {}}", "mod c {}"); | ||
613 | } | ||
614 | |||
615 | #[test] | ||
616 | fn test_all_items() { | ||
617 | let rules = create_rules( | ||
618 | r#" | ||
619 | macro_rules! foo { | ||
620 | ($ ($ i:item)*) => ($ ( | ||
621 | $ i | ||
622 | )*) | ||
623 | } | ||
624 | "#, | ||
625 | ); | ||
626 | assert_expansion(&rules, r#" | ||
627 | foo! { | ||
628 | extern crate a; | ||
629 | mod b; | ||
630 | mod c {} | ||
631 | use d; | ||
632 | const E: i32 = 0; | ||
633 | static F: i32 = 0; | ||
634 | impl G {} | ||
635 | struct H; | ||
636 | enum I { Foo } | ||
637 | trait J {} | ||
638 | fn h() {} | ||
639 | extern {} | ||
640 | type T = u8; | ||
641 | } | ||
642 | "#, r#"extern crate a ; mod b ; mod c {} use d ; const E : i32 = 0 ; static F : i32 = 0 ; impl G {} struct H ; enum I {Foo} trait J {} fn h () {} extern {} type T = u8 ;"#); | ||
643 | } | ||
600 | } | 644 | } |
diff --git a/crates/ra_mbe/src/mbe_expander.rs b/crates/ra_mbe/src/mbe_expander.rs index 7587b575d..acba42809 100644 --- a/crates/ra_mbe/src/mbe_expander.rs +++ b/crates/ra_mbe/src/mbe_expander.rs | |||
@@ -161,6 +161,11 @@ fn match_lhs(pattern: &crate::Subtree, input: &mut TtCursor) -> Result<Bindings, | |||
161 | let pat = input.eat_stmt().ok_or(ExpandError::UnexpectedToken)?.clone(); | 161 | let pat = input.eat_stmt().ok_or(ExpandError::UnexpectedToken)?.clone(); |
162 | res.inner.insert(text.clone(), Binding::Simple(pat.into())); | 162 | res.inner.insert(text.clone(), Binding::Simple(pat.into())); |
163 | } | 163 | } |
164 | "item" => { | ||
165 | let item = | ||
166 | input.eat_item().ok_or(ExpandError::UnexpectedToken)?.clone(); | ||
167 | res.inner.insert(text.clone(), Binding::Simple(item.into())); | ||
168 | } | ||
164 | _ => return Err(ExpandError::UnexpectedToken), | 169 | _ => return Err(ExpandError::UnexpectedToken), |
165 | } | 170 | } |
166 | } | 171 | } |
@@ -278,6 +283,9 @@ mod tests { | |||
278 | 283 | ||
279 | assert_err("($i) => ($i)", "foo!{a}", ExpandError::UnexpectedToken); | 284 | assert_err("($i) => ($i)", "foo!{a}", ExpandError::UnexpectedToken); |
280 | assert_err("($i:) => ($i)", "foo!{a}", ExpandError::UnexpectedToken); | 285 | assert_err("($i:) => ($i)", "foo!{a}", ExpandError::UnexpectedToken); |
286 | |||
287 | // FIXME: | ||
288 | // Add an err test case for ($($i:ident)) => ($()) | ||
281 | } | 289 | } |
282 | 290 | ||
283 | fn assert_err(macro_body: &str, invocation: &str, err: ExpandError) { | 291 | fn assert_err(macro_body: &str, invocation: &str, err: ExpandError) { |
diff --git a/crates/ra_mbe/src/subtree_parser.rs b/crates/ra_mbe/src/subtree_parser.rs index f075ce245..195e4c3ac 100644 --- a/crates/ra_mbe/src/subtree_parser.rs +++ b/crates/ra_mbe/src/subtree_parser.rs | |||
@@ -46,6 +46,10 @@ impl<'a> Parser<'a> { | |||
46 | self.parse(|src, sink| ra_parser::parse_stmt(src, sink, false)) | 46 | self.parse(|src, sink| ra_parser::parse_stmt(src, sink, false)) |
47 | } | 47 | } |
48 | 48 | ||
49 | pub fn parse_item(self) -> Option<tt::TokenTree> { | ||
50 | self.parse(ra_parser::parse_item) | ||
51 | } | ||
52 | |||
49 | fn parse<F>(self, f: F) -> Option<tt::TokenTree> | 53 | fn parse<F>(self, f: F) -> Option<tt::TokenTree> |
50 | where | 54 | where |
51 | F: FnOnce(&dyn TokenSource, &mut dyn TreeSink), | 55 | F: FnOnce(&dyn TokenSource, &mut dyn TreeSink), |
diff --git a/crates/ra_mbe/src/tt_cursor.rs b/crates/ra_mbe/src/tt_cursor.rs index adfe5520d..484437b0e 100644 --- a/crates/ra_mbe/src/tt_cursor.rs +++ b/crates/ra_mbe/src/tt_cursor.rs | |||
@@ -104,6 +104,11 @@ impl<'a> TtCursor<'a> { | |||
104 | parser.parse_stmt() | 104 | parser.parse_stmt() |
105 | } | 105 | } |
106 | 106 | ||
107 | pub(crate) fn eat_item(&mut self) -> Option<tt::TokenTree> { | ||
108 | let parser = Parser::new(&mut self.pos, self.subtree); | ||
109 | parser.parse_item() | ||
110 | } | ||
111 | |||
107 | pub(crate) fn expect_char(&mut self, char: char) -> Result<(), ParseError> { | 112 | pub(crate) fn expect_char(&mut self, char: char) -> Result<(), ParseError> { |
108 | if self.at_char(char) { | 113 | if self.at_char(char) { |
109 | self.bump(); | 114 | self.bump(); |
diff --git a/crates/ra_parser/src/grammar.rs b/crates/ra_parser/src/grammar.rs index 2c2f785d0..f8ed1299a 100644 --- a/crates/ra_parser/src/grammar.rs +++ b/crates/ra_parser/src/grammar.rs | |||
@@ -69,6 +69,10 @@ pub(crate) fn stmt(p: &mut Parser, with_semi: bool) { | |||
69 | expressions::stmt(p, with_semi) | 69 | expressions::stmt(p, with_semi) |
70 | } | 70 | } |
71 | 71 | ||
72 | pub(crate) fn item(p: &mut Parser) { | ||
73 | items::item_or_macro(p, true, items::ItemFlavor::Mod) | ||
74 | } | ||
75 | |||
72 | pub(crate) fn reparser( | 76 | pub(crate) fn reparser( |
73 | node: SyntaxKind, | 77 | node: SyntaxKind, |
74 | first_child: Option<SyntaxKind>, | 78 | first_child: Option<SyntaxKind>, |
diff --git a/crates/ra_parser/src/lib.rs b/crates/ra_parser/src/lib.rs index 9133c1b8a..11b5b9a75 100644 --- a/crates/ra_parser/src/lib.rs +++ b/crates/ra_parser/src/lib.rs | |||
@@ -93,6 +93,11 @@ pub fn parse_stmt(token_source: &dyn TokenSource, tree_sink: &mut dyn TreeSink, | |||
93 | parse_from_tokens(token_source, tree_sink, |p| grammar::stmt(p, with_semi)); | 93 | parse_from_tokens(token_source, tree_sink, |p| grammar::stmt(p, with_semi)); |
94 | } | 94 | } |
95 | 95 | ||
96 | /// Parse given tokens into the given sink as an item | ||
97 | pub fn parse_item(token_source: &dyn TokenSource, tree_sink: &mut dyn TreeSink) { | ||
98 | parse_from_tokens(token_source, tree_sink, grammar::item); | ||
99 | } | ||
100 | |||
96 | /// A parsing function for a specific braced-block. | 101 | /// A parsing function for a specific braced-block. |
97 | pub struct Reparser(fn(&mut parser::Parser)); | 102 | pub struct Reparser(fn(&mut parser::Parser)); |
98 | 103 | ||