aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_mbe/src/subtree_parser.rs4
-rw-r--r--crates/ra_mbe/src/subtree_source.rs185
2 files changed, 106 insertions, 83 deletions
diff --git a/crates/ra_mbe/src/subtree_parser.rs b/crates/ra_mbe/src/subtree_parser.rs
index f198c8224..ce39a40bb 100644
--- a/crates/ra_mbe/src/subtree_parser.rs
+++ b/crates/ra_mbe/src/subtree_parser.rs
@@ -44,7 +44,9 @@ impl<'a> Parser<'a> {
44 } 44 }
45 45
46 fn finish(self, parsed_token: usize, src: &mut SubtreeTokenSource) -> Option<tt::TokenTree> { 46 fn finish(self, parsed_token: usize, src: &mut SubtreeTokenSource) -> Option<tt::TokenTree> {
47 let res = src.bump_n(parsed_token, self.cur_pos); 47 let res = src.bump_n(parsed_token);
48 *self.cur_pos += res.len();
49
48 let res: Vec<_> = res.into_iter().cloned().collect(); 50 let res: Vec<_> = res.into_iter().cloned().collect();
49 51
50 match res.len() { 52 match res.len() {
diff --git a/crates/ra_mbe/src/subtree_source.rs b/crates/ra_mbe/src/subtree_source.rs
index 5f20112ce..4b37c2bda 100644
--- a/crates/ra_mbe/src/subtree_source.rs
+++ b/crates/ra_mbe/src/subtree_source.rs
@@ -11,7 +11,7 @@ struct TtToken {
11} 11}
12 12
13#[derive(Debug, Clone, Eq, PartialEq)] 13#[derive(Debug, Clone, Eq, PartialEq)]
14enum WalkIndex { 14enum WalkCursor {
15 DelimiterBegin(Option<TtToken>), 15 DelimiterBegin(Option<TtToken>),
16 Token(usize, Option<TtToken>), 16 Token(usize, Option<TtToken>),
17 DelimiterEnd(Option<TtToken>), 17 DelimiterEnd(Option<TtToken>),
@@ -22,7 +22,7 @@ enum WalkIndex {
22struct SubTreeWalker<'a> { 22struct SubTreeWalker<'a> {
23 pos: usize, 23 pos: usize,
24 stack: Vec<(&'a tt::Subtree, Option<usize>)>, 24 stack: Vec<(&'a tt::Subtree, Option<usize>)>,
25 idx: WalkIndex, 25 cursor: WalkCursor,
26 last_steps: Vec<usize>, 26 last_steps: Vec<usize>,
27 subtree: &'a tt::Subtree, 27 subtree: &'a tt::Subtree,
28} 28}
@@ -32,7 +32,7 @@ impl<'a> SubTreeWalker<'a> {
32 let mut res = SubTreeWalker { 32 let mut res = SubTreeWalker {
33 pos: 0, 33 pos: 0,
34 stack: vec![], 34 stack: vec![],
35 idx: WalkIndex::Eof, 35 cursor: WalkCursor::Eof,
36 last_steps: vec![], 36 last_steps: vec![],
37 subtree, 37 subtree,
38 }; 38 };
@@ -41,10 +41,14 @@ impl<'a> SubTreeWalker<'a> {
41 res 41 res
42 } 42 }
43 43
44 fn is_eof(&self) -> bool {
45 self.cursor == WalkCursor::Eof
46 }
47
44 fn reset(&mut self) { 48 fn reset(&mut self) {
45 self.pos = 0; 49 self.pos = 0;
46 self.stack = vec![(self.subtree, None)]; 50 self.stack = vec![(self.subtree, None)];
47 self.idx = WalkIndex::DelimiterBegin(convert_delim(self.subtree.delimiter, false)); 51 self.cursor = WalkCursor::DelimiterBegin(convert_delim(self.subtree.delimiter, false));
48 self.last_steps = vec![]; 52 self.last_steps = vec![];
49 53
50 while self.is_empty_delimiter() { 54 while self.is_empty_delimiter() {
@@ -52,12 +56,12 @@ impl<'a> SubTreeWalker<'a> {
52 } 56 }
53 } 57 }
54 58
55 // This funciton will fast forward the pos cursor, 59 // This funciton will fast forward the cursor,
56 // Such that backward will stop at `start_pos` point 60 // Such that backward will stop at `start_pos` point
57 fn start_from_nth(&mut self, start_pos: usize) { 61 fn start_from_nth(&mut self, start_pos: usize) {
58 self.reset(); 62 self.reset();
59 self.pos = start_pos; 63 self.pos = start_pos;
60 self.idx = self.walk_token(start_pos, false); 64 self.cursor = self.walk_token(start_pos, 0, false);
61 65
62 while self.is_empty_delimiter() { 66 while self.is_empty_delimiter() {
63 self.forward_unchecked(); 67 self.forward_unchecked();
@@ -65,22 +69,23 @@ impl<'a> SubTreeWalker<'a> {
65 } 69 }
66 70
67 fn current(&self) -> Option<&TtToken> { 71 fn current(&self) -> Option<&TtToken> {
68 match &self.idx { 72 match &self.cursor {
69 WalkIndex::DelimiterBegin(t) => t.as_ref(), 73 WalkCursor::DelimiterBegin(t) => t.as_ref(),
70 WalkIndex::Token(_, t) => t.as_ref(), 74 WalkCursor::Token(_, t) => t.as_ref(),
71 WalkIndex::DelimiterEnd(t) => t.as_ref(), 75 WalkCursor::DelimiterEnd(t) => t.as_ref(),
72 WalkIndex::Eof => None, 76 WalkCursor::Eof => None,
73 } 77 }
74 } 78 }
75 79
76 fn is_empty_delimiter(&self) -> bool { 80 fn is_empty_delimiter(&self) -> bool {
77 match &self.idx { 81 match &self.cursor {
78 WalkIndex::DelimiterBegin(None) => true, 82 WalkCursor::DelimiterBegin(None) => true,
79 WalkIndex::DelimiterEnd(None) => true, 83 WalkCursor::DelimiterEnd(None) => true,
80 _ => false, 84 _ => false,
81 } 85 }
82 } 86 }
83 87
88 /// Move cursor backward by 1 step with empty checking
84 fn backward(&mut self) { 89 fn backward(&mut self) {
85 if self.last_steps.is_empty() { 90 if self.last_steps.is_empty() {
86 return; 91 return;
@@ -94,7 +99,7 @@ impl<'a> SubTreeWalker<'a> {
94 } 99 }
95 } 100 }
96 101
97 // Move forward a little bit 102 // Move forward if it is empty delimiter
98 if self.last_steps.is_empty() { 103 if self.last_steps.is_empty() {
99 while self.is_empty_delimiter() { 104 while self.is_empty_delimiter() {
100 self.forward_unchecked(); 105 self.forward_unchecked();
@@ -102,54 +107,53 @@ impl<'a> SubTreeWalker<'a> {
102 } 107 }
103 } 108 }
104 109
110 /// Move cursor backward by 1 step without empty check
111 ///
112 /// Depends on the current state of cursor:
113 ///
114 /// * Delimiter Begin => Pop the stack, goto last walking token (`walk_token`)
115 /// * Token => Goto prev token (`walk_token`)
116 /// * Delimiter End => Goto the last child token (`walk_token`)
117 /// * Eof => push the root subtree, and set it as Delimiter End
105 fn backward_unchecked(&mut self) { 118 fn backward_unchecked(&mut self) {
106 if self.last_steps.is_empty() { 119 if self.last_steps.is_empty() {
107 return; 120 return;
108 } 121 }
109 122
110 let last_step = self.last_steps.pop().unwrap(); 123 let last_step = self.last_steps.pop().unwrap();
111 let do_walk_token = match self.idx { 124 let do_walk_token = match self.cursor {
112 WalkIndex::DelimiterBegin(_) => None, 125 WalkCursor::DelimiterBegin(_) => None,
113 WalkIndex::Token(u, _) => Some(u), 126 WalkCursor::Token(u, _) => Some(u),
114 WalkIndex::DelimiterEnd(_) => { 127 WalkCursor::DelimiterEnd(_) => {
115 let (top, _) = self.stack.last().unwrap(); 128 let (top, _) = self.stack.last().unwrap();
116 Some(top.token_trees.len()) 129 Some(top.token_trees.len())
117 } 130 }
118 WalkIndex::Eof => None, 131 WalkCursor::Eof => None,
119 }; 132 };
120 133
121 self.idx = match do_walk_token { 134 self.cursor = match do_walk_token {
122 Some(u) if last_step > u => WalkIndex::DelimiterBegin(convert_delim( 135 Some(u) => self.walk_token(u, last_step, true),
123 self.stack.last().unwrap().0.delimiter, 136 None => match self.cursor {
124 false, 137 WalkCursor::Eof => {
125 )),
126 Some(u) => self.walk_token(u - last_step, true),
127 None => match self.idx {
128 WalkIndex::Eof => {
129 self.stack.push((self.subtree, None)); 138 self.stack.push((self.subtree, None));
130 WalkIndex::DelimiterEnd(convert_delim( 139 WalkCursor::DelimiterEnd(convert_delim(
131 self.stack.last().unwrap().0.delimiter, 140 self.stack.last().unwrap().0.delimiter,
132 true, 141 true,
133 )) 142 ))
134 } 143 }
135 _ => { 144 _ => {
136 let (_, last_top_idx) = self.stack.pop().unwrap(); 145 let (_, last_top_cursor) = self.stack.pop().unwrap();
137 assert!(!self.stack.is_empty()); 146 assert!(!self.stack.is_empty());
138 147
139 match last_top_idx.unwrap() { 148 self.walk_token(last_top_cursor.unwrap(), last_step, true)
140 0 => WalkIndex::DelimiterBegin(convert_delim(
141 self.stack.last().unwrap().0.delimiter,
142 false,
143 )),
144 c => self.walk_token(c - 1, true),
145 }
146 } 149 }
147 }, 150 },
148 }; 151 };
149 } 152 }
150 153
154 /// Move cursor forward by 1 step with empty checking
151 fn forward(&mut self) { 155 fn forward(&mut self) {
152 if self.idx == WalkIndex::Eof { 156 if self.is_eof() {
153 return; 157 return;
154 } 158 }
155 159
@@ -162,57 +166,80 @@ impl<'a> SubTreeWalker<'a> {
162 } 166 }
163 } 167 }
164 168
169 /// Move cursor forward by 1 step without empty checking
170 ///
171 /// Depends on the current state of cursor:
172 ///
173 /// * Delimiter Begin => Goto the first child token (`walk_token`)
174 /// * Token => Goto next token (`walk_token`)
175 /// * Delimiter End => Pop the stack, goto last walking token (`walk_token`)
176 ///
165 fn forward_unchecked(&mut self) { 177 fn forward_unchecked(&mut self) {
166 if self.idx == WalkIndex::Eof { 178 if self.is_eof() {
167 return; 179 return;
168 } 180 }
169 181
170 let step = self.current().map(|x| x.n_tokens).unwrap_or(1); 182 let step = self.current().map(|x| x.n_tokens).unwrap_or(1);
171 self.last_steps.push(step); 183 self.last_steps.push(step);
172 184
173 let do_walk_token = match self.idx { 185 let do_walk_token = match self.cursor {
174 WalkIndex::DelimiterBegin(_) => Some(0), 186 WalkCursor::DelimiterBegin(_) => Some((0, 0)),
175 WalkIndex::Token(u, _) => Some(u + step), 187 WalkCursor::Token(u, _) => Some((u, step)),
176 WalkIndex::DelimiterEnd(_) => None, 188 WalkCursor::DelimiterEnd(_) => None,
177 _ => unreachable!(), 189 _ => unreachable!(),
178 }; 190 };
179 191
180 let (top, _) = self.stack.last().unwrap(); 192 self.cursor = match do_walk_token {
181 193 Some((u, step)) => self.walk_token(u, step, false),
182 self.idx = match do_walk_token {
183 Some(u) if u >= top.token_trees.len() => {
184 WalkIndex::DelimiterEnd(convert_delim(self.stack.last().unwrap().0.delimiter, true))
185 }
186 Some(u) => self.walk_token(u, false),
187 None => { 194 None => {
188 let (_, last_top_idx) = self.stack.pop().unwrap(); 195 let (_, last_top_idx) = self.stack.pop().unwrap();
189 match self.stack.last() { 196 match self.stack.last() {
190 Some(top) => match last_top_idx.unwrap() { 197 Some(_) => self.walk_token(last_top_idx.unwrap(), 1, false),
191 idx if idx + 1 >= top.0.token_trees.len() => { 198 None => WalkCursor::Eof,
192 WalkIndex::DelimiterEnd(convert_delim(top.0.delimiter, true))
193 }
194 idx => self.walk_token(idx + 1, false),
195 },
196
197 None => WalkIndex::Eof,
198 } 199 }
199 } 200 }
200 }; 201 };
201 } 202 }
202 203
203 fn walk_token(&mut self, pos: usize, backward: bool) -> WalkIndex { 204 /// Traversal child token
205 /// Depends on the new position, it returns:
206 ///
207 /// * new position < 0 => DelimiterBegin
208 /// * new position > token_tree.len() => DelimiterEnd
209 /// * if new position is a subtree, depends on traversal direction:
210 /// ** backward => DelimiterEnd
211 /// ** forward => DelimiterBegin
212 /// * if new psoition is a leaf, return walk_leaf()
213 fn walk_token(&mut self, pos: usize, offset: usize, backward: bool) -> WalkCursor {
204 let (top, _) = self.stack.last().unwrap(); 214 let (top, _) = self.stack.last().unwrap();
215
216 if backward && pos < offset {
217 return WalkCursor::DelimiterBegin(convert_delim(
218 self.stack.last().unwrap().0.delimiter,
219 false,
220 ));
221 }
222
223 if !backward && pos + offset >= top.token_trees.len() {
224 return WalkCursor::DelimiterEnd(convert_delim(
225 self.stack.last().unwrap().0.delimiter,
226 true,
227 ));
228 }
229
230 let pos = if backward { pos - offset } else { pos + offset };
231
205 match &top.token_trees[pos] { 232 match &top.token_trees[pos] {
206 tt::TokenTree::Subtree(subtree) => { 233 tt::TokenTree::Subtree(subtree) => {
207 self.stack.push((subtree, Some(pos))); 234 self.stack.push((subtree, Some(pos)));
208 let delim = convert_delim(self.stack.last().unwrap().0.delimiter, backward); 235 let delim = convert_delim(self.stack.last().unwrap().0.delimiter, backward);
209 if backward { 236 if backward {
210 WalkIndex::DelimiterEnd(delim) 237 WalkCursor::DelimiterEnd(delim)
211 } else { 238 } else {
212 WalkIndex::DelimiterBegin(delim) 239 WalkCursor::DelimiterBegin(delim)
213 } 240 }
214 } 241 }
215 tt::TokenTree::Leaf(leaf) => WalkIndex::Token(pos, Some(self.walk_leaf(leaf, pos))), 242 tt::TokenTree::Leaf(leaf) => WalkCursor::Token(pos, Some(self.walk_leaf(leaf, pos))),
216 } 243 }
217 } 244 }
218 245
@@ -240,7 +267,11 @@ pub(crate) struct WalkerOwner<'a> {
240} 267}
241 268
242impl<'a> WalkerOwner<'a> { 269impl<'a> WalkerOwner<'a> {
243 fn token_idx<'b>(&self, pos: usize) -> Option<TtToken> { 270 fn new(subtree: &'a tt::Subtree) -> Self {
271 WalkerOwner { walker: RefCell::new(SubTreeWalker::new(subtree)), offset: 0 }
272 }
273
274 fn get<'b>(&self, pos: usize) -> Option<TtToken> {
244 self.set_walker_pos(pos); 275 self.set_walker_pos(pos);
245 let walker = self.walker.borrow(); 276 let walker = self.walker.borrow();
246 walker.current().cloned() 277 walker.current().cloned()
@@ -254,7 +285,7 @@ impl<'a> WalkerOwner<'a> {
254 fn set_walker_pos(&self, mut pos: usize) { 285 fn set_walker_pos(&self, mut pos: usize) {
255 pos += self.offset; 286 pos += self.offset;
256 let mut walker = self.walker.borrow_mut(); 287 let mut walker = self.walker.borrow_mut();
257 while pos > walker.pos && walker.idx != WalkIndex::Eof { 288 while pos > walker.pos && !walker.is_eof() {
258 walker.forward(); 289 walker.forward();
259 } 290 }
260 while pos < walker.pos { 291 while pos < walker.pos {
@@ -262,18 +293,14 @@ impl<'a> WalkerOwner<'a> {
262 } 293 }
263 } 294 }
264 295
265 fn new(subtree: &'a tt::Subtree) -> Self { 296 fn collect_token_trees(&mut self, n: usize) -> Vec<&tt::TokenTree> {
266 WalkerOwner { walker: RefCell::new(SubTreeWalker::new(subtree)), offset: 0 }
267 }
268
269 fn collect_token_tree(&mut self, n: usize) -> Vec<&tt::TokenTree> {
270 self.start_from_nth(self.offset); 297 self.start_from_nth(self.offset);
271 298
272 let mut res = vec![]; 299 let mut res = vec![];
273 let mut walker = self.walker.borrow_mut(); 300 let mut walker = self.walker.borrow_mut();
274 301
275 while walker.pos - self.offset < n { 302 while walker.pos - self.offset < n {
276 if let WalkIndex::Token(u, tt) = &walker.idx { 303 if let WalkCursor::Token(u, tt) = &walker.cursor {
277 if walker.stack.len() == 1 { 304 if walker.stack.len() == 1 {
278 // We only collect the topmost child 305 // We only collect the topmost child
279 res.push(&walker.stack[0].0.token_trees[*u]); 306 res.push(&walker.stack[0].0.token_trees[*u]);
@@ -294,7 +321,7 @@ impl<'a> WalkerOwner<'a> {
294 321
295impl<'a> Querier for WalkerOwner<'a> { 322impl<'a> Querier for WalkerOwner<'a> {
296 fn token(&self, uidx: usize) -> (SyntaxKind, SmolStr) { 323 fn token(&self, uidx: usize) -> (SyntaxKind, SmolStr) {
297 let tkn = self.token_idx(uidx).unwrap(); 324 let tkn = self.get(uidx).unwrap();
298 (tkn.kind, tkn.text) 325 (tkn.kind, tkn.text)
299 } 326 }
300} 327}
@@ -319,31 +346,25 @@ impl<'a> SubtreeTokenSource<'a> {
319 &self.walker 346 &self.walker
320 } 347 }
321 348
322 pub(crate) fn bump_n( 349 pub(crate) fn bump_n(&mut self, parsed_tokens: usize) -> Vec<&tt::TokenTree> {
323 &mut self, 350 let res = self.walker.collect_token_trees(parsed_tokens);
324 parsed_tokens: usize,
325 cursor_pos: &mut usize,
326 ) -> Vec<&tt::TokenTree> {
327 let res = self.walker.collect_token_tree(parsed_tokens);
328 *cursor_pos += res.len();
329
330 res 351 res
331 } 352 }
332} 353}
333 354
334impl<'a> TokenSource for SubtreeTokenSource<'a> { 355impl<'a> TokenSource for SubtreeTokenSource<'a> {
335 fn token_kind(&self, pos: usize) -> SyntaxKind { 356 fn token_kind(&self, pos: usize) -> SyntaxKind {
336 if let Some(tok) = self.walker.token_idx(pos) { 357 if let Some(tok) = self.walker.get(pos) {
337 tok.kind 358 tok.kind
338 } else { 359 } else {
339 SyntaxKind::EOF 360 SyntaxKind::EOF
340 } 361 }
341 } 362 }
342 fn is_token_joint_to_next(&self, pos: usize) -> bool { 363 fn is_token_joint_to_next(&self, pos: usize) -> bool {
343 self.walker.token_idx(pos).unwrap().is_joint_to_next 364 self.walker.get(pos).unwrap().is_joint_to_next
344 } 365 }
345 fn is_keyword(&self, pos: usize, kw: &str) -> bool { 366 fn is_keyword(&self, pos: usize, kw: &str) -> bool {
346 self.walker.token_idx(pos).unwrap().text == *kw 367 self.walker.get(pos).unwrap().text == *kw
347 } 368 }
348} 369}
349 370