diff options
Diffstat (limited to 'crates/ra_mbe/src/subtree_source.rs')
-rw-r--r-- | crates/ra_mbe/src/subtree_source.rs | 354 |
1 files changed, 156 insertions, 198 deletions
diff --git a/crates/ra_mbe/src/subtree_source.rs b/crates/ra_mbe/src/subtree_source.rs index 4b37c2bda..6aa20057e 100644 --- a/crates/ra_mbe/src/subtree_source.rs +++ b/crates/ra_mbe/src/subtree_source.rs | |||
@@ -2,6 +2,64 @@ use ra_parser::{TokenSource}; | |||
2 | use ra_syntax::{classify_literal, SmolStr, SyntaxKind, SyntaxKind::*}; | 2 | use ra_syntax::{classify_literal, SmolStr, SyntaxKind, SyntaxKind::*}; |
3 | use std::cell::{RefCell}; | 3 | use std::cell::{RefCell}; |
4 | 4 | ||
5 | // A Sequece of Token, | ||
6 | #[derive(Debug, Clone, Eq, PartialEq)] | ||
7 | pub(super) enum TokenSeq<'a> { | ||
8 | Subtree(&'a tt::Subtree), | ||
9 | Seq(&'a [tt::TokenTree]), | ||
10 | } | ||
11 | |||
12 | impl<'a> From<&'a tt::Subtree> for TokenSeq<'a> { | ||
13 | fn from(s: &'a tt::Subtree) -> TokenSeq<'a> { | ||
14 | TokenSeq::Subtree(s) | ||
15 | } | ||
16 | } | ||
17 | |||
18 | impl<'a> From<&'a [tt::TokenTree]> for TokenSeq<'a> { | ||
19 | fn from(s: &'a [tt::TokenTree]) -> TokenSeq<'a> { | ||
20 | TokenSeq::Seq(s) | ||
21 | } | ||
22 | } | ||
23 | |||
24 | enum DelimToken<'a> { | ||
25 | Delim(&'a tt::Delimiter, bool), | ||
26 | Token(&'a tt::TokenTree), | ||
27 | End, | ||
28 | } | ||
29 | |||
30 | impl<'a> TokenSeq<'a> { | ||
31 | fn get(&self, pos: usize) -> DelimToken<'a> { | ||
32 | match self { | ||
33 | TokenSeq::Subtree(subtree) => { | ||
34 | let len = subtree.token_trees.len() + 2; | ||
35 | match pos { | ||
36 | p if p >= len => DelimToken::End, | ||
37 | p if p == len - 1 => DelimToken::Delim(&subtree.delimiter, true), | ||
38 | 0 => DelimToken::Delim(&subtree.delimiter, false), | ||
39 | p => DelimToken::Token(&subtree.token_trees[p - 1]), | ||
40 | } | ||
41 | } | ||
42 | TokenSeq::Seq(tokens) => { | ||
43 | tokens.get(pos).map(DelimToken::Token).unwrap_or(DelimToken::End) | ||
44 | } | ||
45 | } | ||
46 | } | ||
47 | |||
48 | fn len(&self) -> usize { | ||
49 | match self { | ||
50 | TokenSeq::Subtree(subtree) => subtree.token_trees.len() + 2, | ||
51 | TokenSeq::Seq(tokens) => tokens.len(), | ||
52 | } | ||
53 | } | ||
54 | |||
55 | fn child_slice(&self) -> &[tt::TokenTree] { | ||
56 | match self { | ||
57 | TokenSeq::Subtree(subtree) => &subtree.token_trees, | ||
58 | TokenSeq::Seq(tokens) => &tokens, | ||
59 | } | ||
60 | } | ||
61 | } | ||
62 | |||
5 | #[derive(Debug, Clone, Eq, PartialEq)] | 63 | #[derive(Debug, Clone, Eq, PartialEq)] |
6 | struct TtToken { | 64 | struct TtToken { |
7 | pub kind: SyntaxKind, | 65 | pub kind: SyntaxKind, |
@@ -12,29 +70,27 @@ struct TtToken { | |||
12 | 70 | ||
13 | #[derive(Debug, Clone, Eq, PartialEq)] | 71 | #[derive(Debug, Clone, Eq, PartialEq)] |
14 | enum WalkCursor { | 72 | enum WalkCursor { |
15 | DelimiterBegin(Option<TtToken>), | 73 | Token(usize, TtToken), |
16 | Token(usize, Option<TtToken>), | ||
17 | DelimiterEnd(Option<TtToken>), | ||
18 | Eof, | 74 | Eof, |
19 | } | 75 | } |
20 | 76 | ||
21 | #[derive(Debug)] | 77 | #[derive(Debug)] |
22 | struct SubTreeWalker<'a> { | 78 | struct SubTreeWalker<'a> { |
23 | pos: usize, | 79 | pos: usize, |
24 | stack: Vec<(&'a tt::Subtree, Option<usize>)>, | 80 | stack: Vec<(TokenSeq<'a>, usize)>, |
25 | cursor: WalkCursor, | 81 | cursor: WalkCursor, |
26 | last_steps: Vec<usize>, | 82 | last_steps: Vec<usize>, |
27 | subtree: &'a tt::Subtree, | 83 | ts: TokenSeq<'a>, |
28 | } | 84 | } |
29 | 85 | ||
30 | impl<'a> SubTreeWalker<'a> { | 86 | impl<'a> SubTreeWalker<'a> { |
31 | fn new(subtree: &tt::Subtree) -> SubTreeWalker { | 87 | fn new(ts: TokenSeq<'a>) -> SubTreeWalker { |
32 | let mut res = SubTreeWalker { | 88 | let mut res = SubTreeWalker { |
33 | pos: 0, | 89 | pos: 0, |
34 | stack: vec![], | 90 | stack: vec![], |
35 | cursor: WalkCursor::Eof, | 91 | cursor: WalkCursor::Eof, |
36 | last_steps: vec![], | 92 | last_steps: vec![], |
37 | subtree, | 93 | ts, |
38 | }; | 94 | }; |
39 | 95 | ||
40 | res.reset(); | 96 | res.reset(); |
@@ -47,209 +103,106 @@ impl<'a> SubTreeWalker<'a> { | |||
47 | 103 | ||
48 | fn reset(&mut self) { | 104 | fn reset(&mut self) { |
49 | self.pos = 0; | 105 | self.pos = 0; |
50 | self.stack = vec![(self.subtree, None)]; | 106 | self.stack = vec![]; |
51 | self.cursor = WalkCursor::DelimiterBegin(convert_delim(self.subtree.delimiter, false)); | ||
52 | self.last_steps = vec![]; | 107 | self.last_steps = vec![]; |
53 | 108 | ||
54 | while self.is_empty_delimiter() { | 109 | self.cursor = match self.ts.get(0) { |
55 | self.forward_unchecked(); | 110 | DelimToken::Token(token) => match token { |
56 | } | 111 | tt::TokenTree::Subtree(subtree) => { |
57 | } | 112 | WalkCursor::Token(0, convert_delim(subtree.delimiter, false)) |
58 | 113 | } | |
59 | // This funciton will fast forward the cursor, | 114 | tt::TokenTree::Leaf(leaf) => { |
60 | // Such that backward will stop at `start_pos` point | 115 | let next_tokens = self.ts.child_slice(); |
61 | fn start_from_nth(&mut self, start_pos: usize) { | 116 | WalkCursor::Token(0, convert_leaf(&next_tokens, leaf)) |
62 | self.reset(); | 117 | } |
63 | self.pos = start_pos; | 118 | }, |
64 | self.cursor = self.walk_token(start_pos, 0, false); | 119 | DelimToken::Delim(delim, is_end) => { |
65 | 120 | assert!(!is_end); | |
66 | while self.is_empty_delimiter() { | 121 | WalkCursor::Token(0, convert_delim(*delim, false)) |
67 | self.forward_unchecked(); | 122 | } |
123 | DelimToken::End => WalkCursor::Eof, | ||
68 | } | 124 | } |
69 | } | 125 | } |
70 | 126 | ||
71 | fn current(&self) -> Option<&TtToken> { | 127 | fn current(&self) -> Option<&TtToken> { |
72 | match &self.cursor { | 128 | match &self.cursor { |
73 | WalkCursor::DelimiterBegin(t) => t.as_ref(), | 129 | WalkCursor::Token(_, t) => Some(t), |
74 | WalkCursor::Token(_, t) => t.as_ref(), | ||
75 | WalkCursor::DelimiterEnd(t) => t.as_ref(), | ||
76 | WalkCursor::Eof => None, | 130 | WalkCursor::Eof => None, |
77 | } | 131 | } |
78 | } | 132 | } |
79 | 133 | ||
80 | fn is_empty_delimiter(&self) -> bool { | 134 | fn top(&self) -> &TokenSeq { |
81 | match &self.cursor { | 135 | self.stack.last().map(|(t, _)| t).unwrap_or(&self.ts) |
82 | WalkCursor::DelimiterBegin(None) => true, | ||
83 | WalkCursor::DelimiterEnd(None) => true, | ||
84 | _ => false, | ||
85 | } | ||
86 | } | 136 | } |
87 | 137 | ||
88 | /// Move cursor backward by 1 step with empty checking | 138 | /// Move cursor backward by 1 step |
89 | fn backward(&mut self) { | 139 | fn backward(&mut self) { |
90 | if self.last_steps.is_empty() { | 140 | if self.last_steps.is_empty() { |
91 | return; | 141 | return; |
92 | } | 142 | } |
143 | |||
93 | self.pos -= 1; | 144 | self.pos -= 1; |
94 | loop { | 145 | let last_step = self.last_steps.pop().unwrap(); |
95 | self.backward_unchecked(); | ||
96 | // Skip Empty delimiter | ||
97 | if self.last_steps.is_empty() || !self.is_empty_delimiter() { | ||
98 | break; | ||
99 | } | ||
100 | } | ||
101 | 146 | ||
102 | // Move forward if it is empty delimiter | 147 | self.cursor = match self.cursor { |
103 | if self.last_steps.is_empty() { | 148 | WalkCursor::Token(idx, _) => self.walk_token(idx, last_step, true), |
104 | while self.is_empty_delimiter() { | 149 | WalkCursor::Eof => { |
105 | self.forward_unchecked(); | 150 | let len = self.top().len(); |
151 | self.walk_token(len, last_step, true) | ||
106 | } | 152 | } |
107 | } | 153 | } |
108 | } | 154 | } |
109 | 155 | ||
110 | /// Move cursor backward by 1 step without empty check | 156 | /// Move cursor forward by 1 step |
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 | ||
118 | fn backward_unchecked(&mut self) { | ||
119 | if self.last_steps.is_empty() { | ||
120 | return; | ||
121 | } | ||
122 | |||
123 | let last_step = self.last_steps.pop().unwrap(); | ||
124 | let do_walk_token = match self.cursor { | ||
125 | WalkCursor::DelimiterBegin(_) => None, | ||
126 | WalkCursor::Token(u, _) => Some(u), | ||
127 | WalkCursor::DelimiterEnd(_) => { | ||
128 | let (top, _) = self.stack.last().unwrap(); | ||
129 | Some(top.token_trees.len()) | ||
130 | } | ||
131 | WalkCursor::Eof => None, | ||
132 | }; | ||
133 | |||
134 | self.cursor = match do_walk_token { | ||
135 | Some(u) => self.walk_token(u, last_step, true), | ||
136 | None => match self.cursor { | ||
137 | WalkCursor::Eof => { | ||
138 | self.stack.push((self.subtree, None)); | ||
139 | WalkCursor::DelimiterEnd(convert_delim( | ||
140 | self.stack.last().unwrap().0.delimiter, | ||
141 | true, | ||
142 | )) | ||
143 | } | ||
144 | _ => { | ||
145 | let (_, last_top_cursor) = self.stack.pop().unwrap(); | ||
146 | assert!(!self.stack.is_empty()); | ||
147 | |||
148 | self.walk_token(last_top_cursor.unwrap(), last_step, true) | ||
149 | } | ||
150 | }, | ||
151 | }; | ||
152 | } | ||
153 | |||
154 | /// Move cursor forward by 1 step with empty checking | ||
155 | fn forward(&mut self) { | 157 | fn forward(&mut self) { |
156 | if self.is_eof() { | 158 | if self.is_eof() { |
157 | return; | 159 | return; |
158 | } | 160 | } |
159 | |||
160 | self.pos += 1; | 161 | self.pos += 1; |
161 | loop { | ||
162 | self.forward_unchecked(); | ||
163 | if !self.is_empty_delimiter() { | ||
164 | break; | ||
165 | } | ||
166 | } | ||
167 | } | ||
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 | /// | ||
177 | fn forward_unchecked(&mut self) { | ||
178 | if self.is_eof() { | ||
179 | return; | ||
180 | } | ||
181 | 162 | ||
182 | let step = self.current().map(|x| x.n_tokens).unwrap_or(1); | 163 | let step = self.current().map(|x| x.n_tokens).unwrap_or(1); |
183 | self.last_steps.push(step); | 164 | self.last_steps.push(step); |
184 | 165 | ||
185 | let do_walk_token = match self.cursor { | 166 | if let WalkCursor::Token(u, _) = self.cursor { |
186 | WalkCursor::DelimiterBegin(_) => Some((0, 0)), | 167 | self.cursor = self.walk_token(u, step, false) |
187 | WalkCursor::Token(u, _) => Some((u, step)), | 168 | } |
188 | WalkCursor::DelimiterEnd(_) => None, | ||
189 | _ => unreachable!(), | ||
190 | }; | ||
191 | |||
192 | self.cursor = match do_walk_token { | ||
193 | Some((u, step)) => self.walk_token(u, step, false), | ||
194 | None => { | ||
195 | let (_, last_top_idx) = self.stack.pop().unwrap(); | ||
196 | match self.stack.last() { | ||
197 | Some(_) => self.walk_token(last_top_idx.unwrap(), 1, false), | ||
198 | None => WalkCursor::Eof, | ||
199 | } | ||
200 | } | ||
201 | }; | ||
202 | } | 169 | } |
203 | 170 | ||
204 | /// Traversal child token | 171 | /// 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 { | 172 | fn walk_token(&mut self, pos: usize, offset: usize, backward: bool) -> WalkCursor { |
214 | let (top, _) = self.stack.last().unwrap(); | 173 | let top = self.stack.last().map(|(t, _)| t).unwrap_or(&self.ts); |
215 | 174 | ||
216 | if backward && pos < offset { | 175 | if backward && pos < offset { |
217 | return WalkCursor::DelimiterBegin(convert_delim( | 176 | let (_, last_idx) = self.stack.pop().unwrap(); |
218 | self.stack.last().unwrap().0.delimiter, | 177 | return self.walk_token(last_idx, offset, backward); |
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 | } | 178 | } |
229 | 179 | ||
230 | let pos = if backward { pos - offset } else { pos + offset }; | 180 | let pos = if backward { pos - offset } else { pos + offset }; |
231 | 181 | ||
232 | match &top.token_trees[pos] { | 182 | match top.get(pos) { |
233 | tt::TokenTree::Subtree(subtree) => { | 183 | DelimToken::Token(token) => match token { |
234 | self.stack.push((subtree, Some(pos))); | 184 | tt::TokenTree::Subtree(subtree) => { |
235 | let delim = convert_delim(self.stack.last().unwrap().0.delimiter, backward); | 185 | let ts = TokenSeq::from(subtree); |
236 | if backward { | 186 | let new_idx = if backward { ts.len() - 1 } else { 0 }; |
237 | WalkCursor::DelimiterEnd(delim) | 187 | self.stack.push((ts, pos)); |
238 | } else { | 188 | WalkCursor::Token(new_idx, convert_delim(subtree.delimiter, backward)) |
239 | WalkCursor::DelimiterBegin(delim) | 189 | } |
190 | tt::TokenTree::Leaf(leaf) => { | ||
191 | let next_tokens = top.child_slice(); | ||
192 | WalkCursor::Token(pos, convert_leaf(&next_tokens[pos..], leaf)) | ||
240 | } | 193 | } |
194 | }, | ||
195 | DelimToken::Delim(delim, is_end) => { | ||
196 | WalkCursor::Token(pos, convert_delim(*delim, is_end)) | ||
241 | } | 197 | } |
242 | tt::TokenTree::Leaf(leaf) => WalkCursor::Token(pos, Some(self.walk_leaf(leaf, pos))), | 198 | DelimToken::End => { |
243 | } | 199 | // it is the top level |
244 | } | 200 | if let Some((_, last_idx)) = self.stack.pop() { |
245 | 201 | assert!(!backward); | |
246 | fn walk_leaf(&mut self, leaf: &tt::Leaf, pos: usize) -> TtToken { | 202 | self.walk_token(last_idx, offset, backward) |
247 | match leaf { | 203 | } else { |
248 | tt::Leaf::Literal(l) => convert_literal(l), | 204 | WalkCursor::Eof |
249 | tt::Leaf::Ident(ident) => convert_ident(ident), | 205 | } |
250 | tt::Leaf::Punct(punct) => { | ||
251 | let (top, _) = self.stack.last().unwrap(); | ||
252 | convert_punct(punct, top, pos) | ||
253 | } | 206 | } |
254 | } | 207 | } |
255 | } | 208 | } |
@@ -263,27 +216,20 @@ pub(crate) trait Querier { | |||
263 | #[derive(Debug)] | 216 | #[derive(Debug)] |
264 | pub(crate) struct WalkerOwner<'a> { | 217 | pub(crate) struct WalkerOwner<'a> { |
265 | walker: RefCell<SubTreeWalker<'a>>, | 218 | walker: RefCell<SubTreeWalker<'a>>, |
266 | offset: usize, | ||
267 | } | 219 | } |
268 | 220 | ||
269 | impl<'a> WalkerOwner<'a> { | 221 | impl<'a> WalkerOwner<'a> { |
270 | fn new(subtree: &'a tt::Subtree) -> Self { | 222 | fn new<I: Into<TokenSeq<'a>>>(ts: I) -> Self { |
271 | WalkerOwner { walker: RefCell::new(SubTreeWalker::new(subtree)), offset: 0 } | 223 | WalkerOwner { walker: RefCell::new(SubTreeWalker::new(ts.into())) } |
272 | } | 224 | } |
273 | 225 | ||
274 | fn get<'b>(&self, pos: usize) -> Option<TtToken> { | 226 | fn get<'b>(&self, pos: usize) -> Option<TtToken> { |
275 | self.set_walker_pos(pos); | 227 | self.set_pos(pos); |
276 | let walker = self.walker.borrow(); | 228 | let walker = self.walker.borrow(); |
277 | walker.current().cloned() | 229 | walker.current().cloned() |
278 | } | 230 | } |
279 | 231 | ||
280 | fn start_from_nth(&mut self, pos: usize) { | 232 | fn set_pos(&self, pos: usize) { |
281 | self.offset = pos; | ||
282 | self.walker.borrow_mut().start_from_nth(pos); | ||
283 | } | ||
284 | |||
285 | fn set_walker_pos(&self, mut pos: usize) { | ||
286 | pos += self.offset; | ||
287 | let mut walker = self.walker.borrow_mut(); | 233 | let mut walker = self.walker.borrow_mut(); |
288 | while pos > walker.pos && !walker.is_eof() { | 234 | while pos > walker.pos && !walker.is_eof() { |
289 | walker.forward(); | 235 | walker.forward(); |
@@ -294,19 +240,26 @@ impl<'a> WalkerOwner<'a> { | |||
294 | } | 240 | } |
295 | 241 | ||
296 | fn collect_token_trees(&mut self, n: usize) -> Vec<&tt::TokenTree> { | 242 | fn collect_token_trees(&mut self, n: usize) -> Vec<&tt::TokenTree> { |
297 | self.start_from_nth(self.offset); | ||
298 | |||
299 | let mut res = vec![]; | 243 | let mut res = vec![]; |
300 | let mut walker = self.walker.borrow_mut(); | 244 | let mut walker = self.walker.borrow_mut(); |
245 | walker.reset(); | ||
301 | 246 | ||
302 | while walker.pos - self.offset < n { | 247 | while walker.pos < n { |
303 | if let WalkCursor::Token(u, tt) = &walker.cursor { | 248 | if let WalkCursor::Token(u, tt) = &walker.cursor { |
304 | if walker.stack.len() == 1 { | 249 | // We only collect the topmost child |
305 | // We only collect the topmost child | 250 | if walker.stack.len() == 0 { |
306 | res.push(&walker.stack[0].0.token_trees[*u]); | 251 | for i in 0..tt.n_tokens { |
307 | if let Some(tt) = tt { | 252 | if let DelimToken::Token(token) = walker.ts.get(u + i) { |
308 | for i in 0..tt.n_tokens - 1 { | 253 | res.push(token); |
309 | res.push(&walker.stack[0].0.token_trees[u + i]); | 254 | } |
255 | } | ||
256 | } else if walker.stack.len() == 1 { | ||
257 | if let DelimToken::Delim(_, is_end) = walker.ts.get(*u) { | ||
258 | if !is_end { | ||
259 | let (_, last_idx) = &walker.stack[0]; | ||
260 | if let DelimToken::Token(token) = walker.ts.get(*last_idx) { | ||
261 | res.push(token); | ||
262 | } | ||
310 | } | 263 | } |
311 | } | 264 | } |
312 | } | 265 | } |
@@ -331,12 +284,8 @@ pub(crate) struct SubtreeTokenSource<'a> { | |||
331 | } | 284 | } |
332 | 285 | ||
333 | impl<'a> SubtreeTokenSource<'a> { | 286 | impl<'a> SubtreeTokenSource<'a> { |
334 | pub fn new(subtree: &tt::Subtree) -> SubtreeTokenSource { | 287 | pub fn new<I: Into<TokenSeq<'a>>>(ts: I) -> SubtreeTokenSource<'a> { |
335 | SubtreeTokenSource { walker: WalkerOwner::new(subtree) } | 288 | SubtreeTokenSource { walker: WalkerOwner::new(ts) } |
336 | } | ||
337 | |||
338 | pub fn start_from_nth(&mut self, n: usize) { | ||
339 | self.walker.start_from_nth(n); | ||
340 | } | 289 | } |
341 | 290 | ||
342 | pub fn querier<'b>(&'a self) -> &'b WalkerOwner<'a> | 291 | pub fn querier<'b>(&'a self) -> &'b WalkerOwner<'a> |
@@ -467,18 +416,18 @@ where | |||
467 | None | 416 | None |
468 | } | 417 | } |
469 | 418 | ||
470 | fn convert_delim(d: tt::Delimiter, closing: bool) -> Option<TtToken> { | 419 | fn convert_delim(d: tt::Delimiter, closing: bool) -> TtToken { |
471 | let (kinds, texts) = match d { | 420 | let (kinds, texts) = match d { |
472 | tt::Delimiter::Parenthesis => ([L_PAREN, R_PAREN], "()"), | 421 | tt::Delimiter::Parenthesis => ([L_PAREN, R_PAREN], "()"), |
473 | tt::Delimiter::Brace => ([L_CURLY, R_CURLY], "{}"), | 422 | tt::Delimiter::Brace => ([L_CURLY, R_CURLY], "{}"), |
474 | tt::Delimiter::Bracket => ([L_BRACK, R_BRACK], "[]"), | 423 | tt::Delimiter::Bracket => ([L_BRACK, R_BRACK], "[]"), |
475 | tt::Delimiter::None => return None, | 424 | tt::Delimiter::None => ([L_DOLLAR, R_DOLLAR], ""), |
476 | }; | 425 | }; |
477 | 426 | ||
478 | let idx = closing as usize; | 427 | let idx = closing as usize; |
479 | let kind = kinds[idx]; | 428 | let kind = kinds[idx]; |
480 | let text = &texts[idx..texts.len() - (1 - idx)]; | 429 | let text = if texts.len() > 0 { &texts[idx..texts.len() - (1 - idx)] } else { "" }; |
481 | Some(TtToken { kind, is_joint_to_next: false, text: SmolStr::new(text), n_tokens: 1 }) | 430 | TtToken { kind, is_joint_to_next: false, text: SmolStr::new(text), n_tokens: 1 } |
482 | } | 431 | } |
483 | 432 | ||
484 | fn convert_literal(l: &tt::Literal) -> TtToken { | 433 | fn convert_literal(l: &tt::Literal) -> TtToken { |
@@ -495,8 +444,9 @@ fn convert_ident(ident: &tt::Ident) -> TtToken { | |||
495 | TtToken { kind, is_joint_to_next: false, text: ident.text.clone(), n_tokens: 1 } | 444 | TtToken { kind, is_joint_to_next: false, text: ident.text.clone(), n_tokens: 1 } |
496 | } | 445 | } |
497 | 446 | ||
498 | fn convert_punct(p: &tt::Punct, parent: &tt::Subtree, next: usize) -> TtToken { | 447 | fn convert_punct(p: &tt::Punct, next_tokens: &[tt::TokenTree]) -> TtToken { |
499 | let iter = parent.token_trees[next + 1..].iter(); | 448 | let mut iter = next_tokens.iter(); |
449 | iter.next(); | ||
500 | let mut peek = TokenPeek::new(iter); | 450 | let mut peek = TokenPeek::new(iter); |
501 | 451 | ||
502 | if let Some((kind, is_joint_to_next, text, size)) = convert_multi_char_punct(p, &mut peek) { | 452 | if let Some((kind, is_joint_to_next, text, size)) = convert_multi_char_punct(p, &mut peek) { |
@@ -519,3 +469,11 @@ fn convert_punct(p: &tt::Punct, parent: &tt::Subtree, next: usize) -> TtToken { | |||
519 | TtToken { kind, is_joint_to_next: p.spacing == tt::Spacing::Joint, text, n_tokens: 1 } | 469 | TtToken { kind, is_joint_to_next: p.spacing == tt::Spacing::Joint, text, n_tokens: 1 } |
520 | } | 470 | } |
521 | } | 471 | } |
472 | |||
473 | fn convert_leaf(tokens: &[tt::TokenTree], leaf: &tt::Leaf) -> TtToken { | ||
474 | match leaf { | ||
475 | tt::Leaf::Literal(l) => convert_literal(l), | ||
476 | tt::Leaf::Ident(ident) => convert_ident(ident), | ||
477 | tt::Leaf::Punct(punct) => convert_punct(punct, tokens), | ||
478 | } | ||
479 | } | ||