diff options
Diffstat (limited to 'crates/ra_mbe/src/tt_cursor.rs')
-rw-r--r-- | crates/ra_mbe/src/tt_cursor.rs | 106 |
1 files changed, 105 insertions, 1 deletions
diff --git a/crates/ra_mbe/src/tt_cursor.rs b/crates/ra_mbe/src/tt_cursor.rs index 741b5ea1c..eef642a9c 100644 --- a/crates/ra_mbe/src/tt_cursor.rs +++ b/crates/ra_mbe/src/tt_cursor.rs | |||
@@ -1,12 +1,18 @@ | |||
1 | use crate::ParseError; | 1 | use crate::ParseError; |
2 | use crate::subtree_parser::Parser; | 2 | use crate::subtree_parser::Parser; |
3 | use crate::subtree_source::TokenPeek; | ||
4 | use smallvec::{SmallVec, smallvec}; | ||
3 | 5 | ||
4 | #[derive(Clone)] | 6 | #[derive(Debug, Clone)] |
5 | pub(crate) struct TtCursor<'a> { | 7 | pub(crate) struct TtCursor<'a> { |
6 | subtree: &'a tt::Subtree, | 8 | subtree: &'a tt::Subtree, |
7 | pos: usize, | 9 | pos: usize, |
8 | } | 10 | } |
9 | 11 | ||
12 | pub(crate) struct TtCursorMemento { | ||
13 | pos: usize, | ||
14 | } | ||
15 | |||
10 | impl<'a> TtCursor<'a> { | 16 | impl<'a> TtCursor<'a> { |
11 | pub(crate) fn new(subtree: &'a tt::Subtree) -> TtCursor<'a> { | 17 | pub(crate) fn new(subtree: &'a tt::Subtree) -> TtCursor<'a> { |
12 | TtCursor { subtree, pos: 0 } | 18 | TtCursor { subtree, pos: 0 } |
@@ -157,4 +163,102 @@ impl<'a> TtCursor<'a> { | |||
157 | Err(ParseError::Expected(format!("`{}`", char))) | 163 | Err(ParseError::Expected(format!("`{}`", char))) |
158 | } | 164 | } |
159 | } | 165 | } |
166 | |||
167 | fn eat_punct3(&mut self, p: &tt::Punct) -> Option<SmallVec<[tt::Punct; 3]>> { | ||
168 | let sec = self.eat_punct()?.clone(); | ||
169 | let third = self.eat_punct()?.clone(); | ||
170 | Some(smallvec![p.clone(), sec, third]) | ||
171 | } | ||
172 | |||
173 | fn eat_punct2(&mut self, p: &tt::Punct) -> Option<SmallVec<[tt::Punct; 3]>> { | ||
174 | let sec = self.eat_punct()?.clone(); | ||
175 | Some(smallvec![p.clone(), sec]) | ||
176 | } | ||
177 | |||
178 | fn eat_multi_char_punct<'b, I>( | ||
179 | &mut self, | ||
180 | p: &tt::Punct, | ||
181 | iter: &mut TokenPeek<'b, I>, | ||
182 | ) -> Option<SmallVec<[tt::Punct; 3]>> | ||
183 | where | ||
184 | I: Iterator<Item = &'b tt::TokenTree>, | ||
185 | { | ||
186 | if let Some((m, _)) = iter.current_punct3(p) { | ||
187 | if let r @ Some(_) = match m { | ||
188 | ('<', '<', '=') | ('>', '>', '=') | ('.', '.', '.') | ('.', '.', '=') => { | ||
189 | self.eat_punct3(p) | ||
190 | } | ||
191 | _ => None, | ||
192 | } { | ||
193 | return r; | ||
194 | } | ||
195 | } | ||
196 | |||
197 | if let Some((m, _)) = iter.current_punct2(p) { | ||
198 | if let r @ Some(_) = match m { | ||
199 | ('<', '=') | ||
200 | | ('>', '=') | ||
201 | | ('+', '=') | ||
202 | | ('-', '=') | ||
203 | | ('|', '=') | ||
204 | | ('&', '=') | ||
205 | | ('^', '=') | ||
206 | | ('/', '=') | ||
207 | | ('*', '=') | ||
208 | | ('%', '=') | ||
209 | | ('&', '&') | ||
210 | | ('|', '|') | ||
211 | | ('<', '<') | ||
212 | | ('>', '>') | ||
213 | | ('-', '>') | ||
214 | | ('!', '=') | ||
215 | | ('=', '>') | ||
216 | | ('=', '=') | ||
217 | | ('.', '.') | ||
218 | | (':', ':') => self.eat_punct2(p), | ||
219 | |||
220 | _ => None, | ||
221 | } { | ||
222 | return r; | ||
223 | } | ||
224 | } | ||
225 | |||
226 | None | ||
227 | } | ||
228 | |||
229 | pub(crate) fn eat_seperator(&mut self) -> Option<crate::Separator> { | ||
230 | match self.eat()? { | ||
231 | tt::TokenTree::Leaf(tt::Leaf::Literal(lit)) => { | ||
232 | Some(crate::Separator::Literal(lit.clone())) | ||
233 | } | ||
234 | tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) => { | ||
235 | Some(crate::Separator::Ident(ident.clone())) | ||
236 | } | ||
237 | tt::TokenTree::Leaf(tt::Leaf::Punct(punct)) => { | ||
238 | match punct.char { | ||
239 | '*' | '+' | '?' => return None, | ||
240 | _ => {} | ||
241 | }; | ||
242 | |||
243 | // FIXME: The parser is only handle some compositeable punct, | ||
244 | // But at this phase, some punct still is jointed. | ||
245 | // So we by pass that check here. | ||
246 | let mut peekable = TokenPeek::new(self.subtree.token_trees[self.pos..].iter()); | ||
247 | let puncts = self.eat_multi_char_punct(punct, &mut peekable); | ||
248 | let puncts = puncts.unwrap_or_else(|| smallvec![punct.clone()]); | ||
249 | |||
250 | Some(crate::Separator::Puncts(puncts)) | ||
251 | } | ||
252 | _ => None, | ||
253 | } | ||
254 | } | ||
255 | |||
256 | #[must_use] | ||
257 | pub(crate) fn save(&self) -> TtCursorMemento { | ||
258 | TtCursorMemento { pos: self.pos } | ||
259 | } | ||
260 | |||
261 | pub(crate) fn rollback(&mut self, memento: TtCursorMemento) { | ||
262 | self.pos = memento.pos; | ||
263 | } | ||
160 | } | 264 | } |