aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_mbe/src/tt_cursor.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_mbe/src/tt_cursor.rs')
-rw-r--r--crates/ra_mbe/src/tt_cursor.rs48
1 files changed, 46 insertions, 2 deletions
diff --git a/crates/ra_mbe/src/tt_cursor.rs b/crates/ra_mbe/src/tt_cursor.rs
index eef642a9c..53bc305be 100644
--- a/crates/ra_mbe/src/tt_cursor.rs
+++ b/crates/ra_mbe/src/tt_cursor.rs
@@ -1,6 +1,5 @@
1use crate::ParseError; 1use crate::ParseError;
2use crate::subtree_parser::Parser; 2use crate::subtree_parser::Parser;
3use crate::subtree_source::TokenPeek;
4use smallvec::{SmallVec, smallvec}; 3use smallvec::{SmallVec, smallvec};
5 4
6#[derive(Debug, Clone)] 5#[derive(Debug, Clone)]
@@ -153,7 +152,7 @@ impl<'a> TtCursor<'a> {
153 pub(crate) fn eat_vis(&mut self) -> Option<tt::TokenTree> { 152 pub(crate) fn eat_vis(&mut self) -> Option<tt::TokenTree> {
154 let parser = Parser::new(&mut self.pos, self.subtree); 153 let parser = Parser::new(&mut self.pos, self.subtree);
155 parser.parse_vis() 154 parser.parse_vis()
156 } 155 }
157 156
158 pub(crate) fn expect_char(&mut self, char: char) -> Result<(), ParseError> { 157 pub(crate) fn expect_char(&mut self, char: char) -> Result<(), ParseError> {
159 if self.at_char(char) { 158 if self.at_char(char) {
@@ -262,3 +261,48 @@ impl<'a> TtCursor<'a> {
262 self.pos = memento.pos; 261 self.pos = memento.pos;
263 } 262 }
264} 263}
264
265pub(crate) struct TokenPeek<'a, I>
266where
267 I: Iterator<Item = &'a tt::TokenTree>,
268{
269 iter: itertools::MultiPeek<I>,
270}
271
272// helper function
273fn to_punct(tt: &tt::TokenTree) -> Option<&tt::Punct> {
274 if let tt::TokenTree::Leaf(tt::Leaf::Punct(pp)) = tt {
275 return Some(pp);
276 }
277 None
278}
279
280impl<'a, I> TokenPeek<'a, I>
281where
282 I: Iterator<Item = &'a tt::TokenTree>,
283{
284 pub fn new(iter: I) -> Self {
285 TokenPeek { iter: itertools::multipeek(iter) }
286 }
287
288 pub fn current_punct2(&mut self, p: &tt::Punct) -> Option<((char, char), bool)> {
289 if p.spacing != tt::Spacing::Joint {
290 return None;
291 }
292
293 self.iter.reset_peek();
294 let p1 = to_punct(self.iter.peek()?)?;
295 Some(((p.char, p1.char), p1.spacing == tt::Spacing::Joint))
296 }
297
298 pub fn current_punct3(&mut self, p: &tt::Punct) -> Option<((char, char, char), bool)> {
299 self.current_punct2(p).and_then(|((p0, p1), last_joint)| {
300 if !last_joint {
301 None
302 } else {
303 let p2 = to_punct(*self.iter.peek()?)?;
304 Some(((p0, p1, p2.char), p2.spacing == tt::Spacing::Joint))
305 }
306 })
307 }
308}