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.rs132
1 files changed, 10 insertions, 122 deletions
diff --git a/crates/ra_mbe/src/tt_cursor.rs b/crates/ra_mbe/src/tt_cursor.rs
index 6ac3ac187..52e072599 100644
--- a/crates/ra_mbe/src/tt_cursor.rs
+++ b/crates/ra_mbe/src/tt_cursor.rs
@@ -1,116 +1,17 @@
1use crate::ParseError; 1use crate::ParseError;
2use crate::syntax_bridge::{TtTokenSource, TtToken, TokenPeek}; 2use crate::subtree_source::SubtreeTokenSource;
3
3use ra_parser::{TokenSource, TreeSink}; 4use ra_parser::{TokenSource, TreeSink};
4 5
5use ra_syntax::{ 6use ra_syntax::{
6 SyntaxKind 7 SyntaxKind
7}; 8};
8 9
9struct TtCursorTokenSource { 10struct SubtreeTokenSink {
10 tt_pos: usize,
11 inner: TtTokenSource,
12}
13
14impl TtCursorTokenSource {
15 fn new(subtree: &tt::Subtree, curr: usize) -> TtCursorTokenSource {
16 let mut res = TtCursorTokenSource { inner: TtTokenSource::new(subtree), tt_pos: 1 };
17
18 // Matching `TtToken` cursor to `tt::TokenTree` cursor
19 // It is because TtToken is not One to One mapping to tt::Token
20 // There are 3 case (`TtToken` <=> `tt::TokenTree`) :
21 // * One to One => ident, single char punch
22 // * Many to One => `tt::TokenTree::SubTree`
23 // * One to Many => multibyte punct
24 //
25 // Such that we cannot simpliy advance the cursor
26 // We have to bump it one by one
27 let mut pos = 0;
28 while pos < curr {
29 pos += res.bump(&subtree.token_trees[pos]);
30 }
31
32 res
33 }
34
35 fn skip_sibling_leaf(&self, leaf: &tt::Leaf, iter: &mut std::slice::Iter<tt::TokenTree>) {
36 if let tt::Leaf::Punct(p) = leaf {
37 let mut peek = TokenPeek::new(iter);
38 if let Some((_, _, _, size)) = TtTokenSource::convert_multi_char_punct(p, &mut peek) {
39 for _ in 0..size - 1 {
40 peek.next();
41 }
42 }
43 }
44 }
45
46 fn count_tt_tokens(
47 &self,
48 tt: &tt::TokenTree,
49 iter: Option<&mut std::slice::Iter<tt::TokenTree>>,
50 ) -> usize {
51 assert!(!self.inner.tokens.is_empty());
52
53 match tt {
54 tt::TokenTree::Subtree(sub_tree) => {
55 let mut iter = sub_tree.token_trees.iter();
56 let mut count = match sub_tree.delimiter {
57 tt::Delimiter::None => 0,
58 _ => 2,
59 };
60
61 while let Some(tt) = iter.next() {
62 count += self.count_tt_tokens(&tt, Some(&mut iter));
63 }
64 count
65 }
66
67 tt::TokenTree::Leaf(leaf) => {
68 iter.map(|iter| {
69 self.skip_sibling_leaf(leaf, iter);
70 });
71
72 1
73 }
74 }
75 }
76
77 fn count(&self, tt: &tt::TokenTree) -> usize {
78 self.count_tt_tokens(tt, None)
79 }
80
81 fn bump(&mut self, tt: &tt::TokenTree) -> usize {
82 let cur = self.current().unwrap();
83 let n_tokens = cur.n_tokens;
84 self.tt_pos += self.count(tt);
85 n_tokens
86 }
87
88 fn current(&self) -> Option<&TtToken> {
89 self.inner.tokens.get(self.tt_pos)
90 }
91}
92
93impl TokenSource for TtCursorTokenSource {
94 fn token_kind(&self, pos: usize) -> SyntaxKind {
95 if let Some(tok) = self.inner.tokens.get(self.tt_pos + pos) {
96 tok.kind
97 } else {
98 SyntaxKind::EOF
99 }
100 }
101 fn is_token_joint_to_next(&self, pos: usize) -> bool {
102 self.inner.tokens[self.tt_pos + pos].is_joint_to_next
103 }
104 fn is_keyword(&self, pos: usize, kw: &str) -> bool {
105 self.inner.tokens[self.tt_pos + pos].text == *kw
106 }
107}
108
109struct TtCursorTokenSink {
110 token_pos: usize, 11 token_pos: usize,
111} 12}
112 13
113impl TreeSink for TtCursorTokenSink { 14impl TreeSink for SubtreeTokenSink {
114 fn token(&mut self, _kind: SyntaxKind, n_tokens: u8) { 15 fn token(&mut self, _kind: SyntaxKind, n_tokens: u8) {
115 self.token_pos += n_tokens as usize; 16 self.token_pos += n_tokens as usize;
116 } 17 }
@@ -201,24 +102,10 @@ impl<'a> TtCursor<'a> {
201 fn eat_parse_result( 102 fn eat_parse_result(
202 &mut self, 103 &mut self,
203 parsed_token: usize, 104 parsed_token: usize,
204 src: &mut TtCursorTokenSource, 105 src: &mut SubtreeTokenSource,
205 ) -> Option<tt::TokenTree> { 106 ) -> Option<tt::TokenTree> {
206 let mut res = vec![]; 107 let (adv, res) = src.bump_n(parsed_token, self.pos);
207 108 self.pos += adv;
208 // Matching `TtToken` cursor to `tt::TokenTree` cursor
209 // It is because TtToken is not One to One mapping to tt::Token
210 // There are 3 case (`TtToken` <=> `tt::TokenTree`) :
211 // * One to One => ident, single char punch
212 // * Many to One => `tt::TokenTree::SubTree`
213 // * One to Many => multibyte punct
214 //
215 // Such that we cannot simpliy advance the cursor
216 // We have to bump it one by one
217 let next_pos = src.tt_pos + parsed_token;
218 while src.tt_pos < next_pos {
219 let n = src.bump(self.current().unwrap());
220 res.extend((0..n).map(|_| self.eat().unwrap()));
221 }
222 109
223 let res: Vec<_> = res.into_iter().cloned().collect(); 110 let res: Vec<_> = res.into_iter().cloned().collect();
224 111
@@ -236,8 +123,9 @@ impl<'a> TtCursor<'a> {
236 where 123 where
237 F: FnOnce(&dyn TokenSource, &mut dyn TreeSink), 124 F: FnOnce(&dyn TokenSource, &mut dyn TreeSink),
238 { 125 {
239 let mut src = TtCursorTokenSource::new(self.subtree, self.pos); 126 let mut src = SubtreeTokenSource::new(self.subtree);
240 let mut sink = TtCursorTokenSink { token_pos: 0 }; 127 src.advance(self.pos, true);
128 let mut sink = SubtreeTokenSink { token_pos: 0 };
241 129
242 f(&src, &mut sink); 130 f(&src, &mut sink);
243 131