diff options
Diffstat (limited to 'crates/ra_mbe/src')
-rw-r--r-- | crates/ra_mbe/src/mbe_expander/matcher.rs | 56 | ||||
-rw-r--r-- | crates/ra_mbe/src/tests.rs | 13 | ||||
-rw-r--r-- | crates/ra_mbe/src/tt_iter.rs | 4 |
3 files changed, 72 insertions, 1 deletions
diff --git a/crates/ra_mbe/src/mbe_expander/matcher.rs b/crates/ra_mbe/src/mbe_expander/matcher.rs index 2bdea11e1..ffba03898 100644 --- a/crates/ra_mbe/src/mbe_expander/matcher.rs +++ b/crates/ra_mbe/src/mbe_expander/matcher.rs | |||
@@ -155,6 +155,60 @@ impl<'a> TtIter<'a> { | |||
155 | ok | 155 | ok |
156 | } | 156 | } |
157 | 157 | ||
158 | pub(crate) fn expect_tt(&mut self) -> Result<tt::TokenTree, ()> { | ||
159 | let tt = self.next().ok_or_else(|| ())?.clone(); | ||
160 | let punct = match tt { | ||
161 | tt::TokenTree::Leaf(tt::Leaf::Punct(punct)) if punct.spacing == tt::Spacing::Joint => { | ||
162 | punct | ||
163 | } | ||
164 | _ => return Ok(tt), | ||
165 | }; | ||
166 | |||
167 | let (second, third) = match (self.peek_n(0), self.peek_n(1)) { | ||
168 | ( | ||
169 | Some(tt::TokenTree::Leaf(tt::Leaf::Punct(p2))), | ||
170 | Some(tt::TokenTree::Leaf(tt::Leaf::Punct(p3))), | ||
171 | ) if p2.spacing == tt::Spacing::Joint => (p2.char, Some(p3.char)), | ||
172 | (Some(tt::TokenTree::Leaf(tt::Leaf::Punct(p2))), _) => (p2.char, None), | ||
173 | _ => return Ok(tt), | ||
174 | }; | ||
175 | |||
176 | match (punct.char, second, third) { | ||
177 | ('.', '.', Some('.')) | ||
178 | | ('.', '.', Some('=')) | ||
179 | | ('<', '<', Some('=')) | ||
180 | | ('>', '>', Some('=')) => { | ||
181 | let tt2 = self.next().unwrap().clone(); | ||
182 | let tt3 = self.next().unwrap().clone(); | ||
183 | Ok(tt::Subtree { delimiter: None, token_trees: vec![tt, tt2, tt3] }.into()) | ||
184 | } | ||
185 | ('-', '=', None) | ||
186 | | ('-', '>', None) | ||
187 | | (':', ':', None) | ||
188 | | ('!', '=', None) | ||
189 | | ('.', '.', None) | ||
190 | | ('*', '=', None) | ||
191 | | ('/', '=', None) | ||
192 | | ('&', '&', None) | ||
193 | | ('&', '=', None) | ||
194 | | ('%', '=', None) | ||
195 | | ('^', '=', None) | ||
196 | | ('+', '=', None) | ||
197 | | ('<', '<', None) | ||
198 | | ('<', '=', None) | ||
199 | | ('=', '=', None) | ||
200 | | ('=', '>', None) | ||
201 | | ('>', '=', None) | ||
202 | | ('>', '>', None) | ||
203 | | ('|', '=', None) | ||
204 | | ('|', '|', None) => { | ||
205 | let tt2 = self.next().unwrap().clone(); | ||
206 | Ok(tt::Subtree { delimiter: None, token_trees: vec![tt.clone(), tt2] }.into()) | ||
207 | } | ||
208 | _ => Ok(tt), | ||
209 | } | ||
210 | } | ||
211 | |||
158 | pub(crate) fn expect_lifetime(&mut self) -> Result<&tt::Ident, ()> { | 212 | pub(crate) fn expect_lifetime(&mut self) -> Result<&tt::Ident, ()> { |
159 | let ident = self.expect_ident()?; | 213 | let ident = self.expect_ident()?; |
160 | // check if it start from "`" | 214 | // check if it start from "`" |
@@ -302,7 +356,7 @@ fn match_meta_var(kind: &str, input: &mut TtIter) -> Result<Option<Fragment>, Ex | |||
302 | let ident = input.expect_ident().map_err(|()| err!("expected ident"))?.clone(); | 356 | let ident = input.expect_ident().map_err(|()| err!("expected ident"))?.clone(); |
303 | tt::Leaf::from(ident).into() | 357 | tt::Leaf::from(ident).into() |
304 | } | 358 | } |
305 | "tt" => input.next().ok_or_else(|| err!())?.clone(), | 359 | "tt" => input.expect_tt().map_err(|()| err!())?.clone(), |
306 | "lifetime" => { | 360 | "lifetime" => { |
307 | let ident = input.expect_lifetime().map_err(|()| err!())?; | 361 | let ident = input.expect_lifetime().map_err(|()| err!())?; |
308 | tt::Leaf::Ident(ident.clone()).into() | 362 | tt::Leaf::Ident(ident.clone()).into() |
diff --git a/crates/ra_mbe/src/tests.rs b/crates/ra_mbe/src/tests.rs index 1dba82915..5e6a090aa 100644 --- a/crates/ra_mbe/src/tests.rs +++ b/crates/ra_mbe/src/tests.rs | |||
@@ -825,6 +825,19 @@ fn test_tt_group() { | |||
825 | ) | 825 | ) |
826 | .assert_expand_items(r#"foo! { fn foo() {} }"#, r#"fn foo () {}"#); | 826 | .assert_expand_items(r#"foo! { fn foo() {} }"#, r#"fn foo () {}"#); |
827 | } | 827 | } |
828 | |||
829 | #[test] | ||
830 | fn test_tt_composite() { | ||
831 | parse_macro( | ||
832 | r#" | ||
833 | macro_rules! foo { | ||
834 | ($i:tt) => { 0 } | ||
835 | } | ||
836 | "#, | ||
837 | ) | ||
838 | .assert_expand_items(r#"foo! { => }"#, r#"0"#); | ||
839 | } | ||
840 | |||
828 | #[test] | 841 | #[test] |
829 | fn test_lifetime() { | 842 | fn test_lifetime() { |
830 | parse_macro( | 843 | parse_macro( |
diff --git a/crates/ra_mbe/src/tt_iter.rs b/crates/ra_mbe/src/tt_iter.rs index 319f1ee65..100184e66 100644 --- a/crates/ra_mbe/src/tt_iter.rs +++ b/crates/ra_mbe/src/tt_iter.rs | |||
@@ -53,6 +53,10 @@ impl<'a> TtIter<'a> { | |||
53 | _ => Err(()), | 53 | _ => Err(()), |
54 | } | 54 | } |
55 | } | 55 | } |
56 | |||
57 | pub(crate) fn peek_n(&self, n: usize) -> Option<&tt::TokenTree> { | ||
58 | self.inner.as_slice().get(n) | ||
59 | } | ||
56 | } | 60 | } |
57 | 61 | ||
58 | impl<'a> Iterator for TtIter<'a> { | 62 | impl<'a> Iterator for TtIter<'a> { |