diff options
-rw-r--r-- | crates/ra_mbe/src/subtree_parser.rs | 4 | ||||
-rw-r--r-- | crates/ra_mbe/src/subtree_source.rs | 185 |
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)] |
14 | enum WalkIndex { | 14 | enum 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 { | |||
22 | struct SubTreeWalker<'a> { | 22 | struct 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 | ||
242 | impl<'a> WalkerOwner<'a> { | 269 | impl<'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 | ||
295 | impl<'a> Querier for WalkerOwner<'a> { | 322 | impl<'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 | ||
334 | impl<'a> TokenSource for SubtreeTokenSource<'a> { | 355 | impl<'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 | ||