diff options
Diffstat (limited to 'crates/ra_mbe/src/subtree_parser.rs')
-rw-r--r-- | crates/ra_mbe/src/subtree_parser.rs | 42 |
1 files changed, 31 insertions, 11 deletions
diff --git a/crates/ra_mbe/src/subtree_parser.rs b/crates/ra_mbe/src/subtree_parser.rs index 9cc989b23..1f12e42ef 100644 --- a/crates/ra_mbe/src/subtree_parser.rs +++ b/crates/ra_mbe/src/subtree_parser.rs | |||
@@ -2,16 +2,38 @@ use crate::subtree_source::SubtreeTokenSource; | |||
2 | 2 | ||
3 | use ra_parser::{TokenSource, TreeSink}; | 3 | use ra_parser::{TokenSource, TreeSink}; |
4 | use ra_syntax::{SyntaxKind}; | 4 | use ra_syntax::{SyntaxKind}; |
5 | use tt::buffer::TokenBuffer; | 5 | use tt::buffer::{TokenBuffer, Cursor}; |
6 | 6 | ||
7 | struct OffsetTokenSink { | 7 | struct OffsetTokenSink<'a> { |
8 | token_pos: usize, | 8 | cursor: Cursor<'a>, |
9 | error: bool, | 9 | error: bool, |
10 | } | 10 | } |
11 | 11 | ||
12 | impl TreeSink for OffsetTokenSink { | 12 | impl<'a> OffsetTokenSink<'a> { |
13 | pub fn collect(&self, begin: Cursor<'a>) -> Vec<tt::TokenTree> { | ||
14 | if !self.cursor.is_root() { | ||
15 | return vec![]; | ||
16 | } | ||
17 | |||
18 | let mut curr = begin; | ||
19 | let mut res = vec![]; | ||
20 | |||
21 | while self.cursor != curr { | ||
22 | if let Some(token) = curr.token_tree() { | ||
23 | res.push(token); | ||
24 | } | ||
25 | curr = curr.bump(); | ||
26 | } | ||
27 | |||
28 | res | ||
29 | } | ||
30 | } | ||
31 | |||
32 | impl<'a> TreeSink for OffsetTokenSink<'a> { | ||
13 | fn token(&mut self, _kind: SyntaxKind, n_tokens: u8) { | 33 | fn token(&mut self, _kind: SyntaxKind, n_tokens: u8) { |
14 | self.token_pos += n_tokens as usize; | 34 | for _ in 0..n_tokens { |
35 | self.cursor = self.cursor.bump_subtree(); | ||
36 | } | ||
15 | } | 37 | } |
16 | fn start_node(&mut self, _kind: SyntaxKind) {} | 38 | fn start_node(&mut self, _kind: SyntaxKind) {} |
17 | fn finish_node(&mut self) {} | 39 | fn finish_node(&mut self) {} |
@@ -72,23 +94,21 @@ impl<'a> Parser<'a> { | |||
72 | { | 94 | { |
73 | let buffer = TokenBuffer::new(&self.subtree.token_trees[*self.cur_pos..]); | 95 | let buffer = TokenBuffer::new(&self.subtree.token_trees[*self.cur_pos..]); |
74 | let mut src = SubtreeTokenSource::new(&buffer); | 96 | let mut src = SubtreeTokenSource::new(&buffer); |
75 | let mut sink = OffsetTokenSink { token_pos: 0, error: false }; | 97 | let mut sink = OffsetTokenSink { cursor: buffer.begin(), error: false }; |
76 | 98 | ||
77 | f(&mut src, &mut sink); | 99 | f(&mut src, &mut sink); |
78 | 100 | ||
79 | let r = self.finish(sink.token_pos, &mut src); | 101 | let r = self.finish(buffer.begin(), &mut sink); |
80 | if sink.error { | 102 | if sink.error { |
81 | return None; | 103 | return None; |
82 | } | 104 | } |
83 | r | 105 | r |
84 | } | 106 | } |
85 | 107 | ||
86 | fn finish(self, parsed_token: usize, src: &mut SubtreeTokenSource) -> Option<tt::TokenTree> { | 108 | fn finish(self, begin: Cursor, sink: &mut OffsetTokenSink) -> Option<tt::TokenTree> { |
87 | let res = src.bump_n(parsed_token); | 109 | let res = sink.collect(begin); |
88 | *self.cur_pos += res.len(); | 110 | *self.cur_pos += res.len(); |
89 | 111 | ||
90 | let res: Vec<_> = res.into_iter().collect(); | ||
91 | |||
92 | match res.len() { | 112 | match res.len() { |
93 | 0 => None, | 113 | 0 => None, |
94 | 1 => Some(res[0].clone()), | 114 | 1 => Some(res[0].clone()), |