diff options
Diffstat (limited to 'crates/ra_mbe/src/tt_cursor.rs')
-rw-r--r-- | crates/ra_mbe/src/tt_cursor.rs | 91 |
1 files changed, 91 insertions, 0 deletions
diff --git a/crates/ra_mbe/src/tt_cursor.rs b/crates/ra_mbe/src/tt_cursor.rs index 87bcf8b0d..343416421 100644 --- a/crates/ra_mbe/src/tt_cursor.rs +++ b/crates/ra_mbe/src/tt_cursor.rs | |||
@@ -1,5 +1,7 @@ | |||
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(Clone)] |
5 | pub(crate) struct TtCursor<'a> { | 7 | pub(crate) struct TtCursor<'a> { |
@@ -162,6 +164,95 @@ impl<'a> TtCursor<'a> { | |||
162 | } | 164 | } |
163 | } | 165 | } |
164 | 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 | |||
165 | #[must_use] | 256 | #[must_use] |
166 | pub(crate) fn save(&self) -> TtCursorMemento { | 257 | pub(crate) fn save(&self) -> TtCursorMemento { |
167 | TtCursorMemento { pos: self.pos } | 258 | TtCursorMemento { pos: self.pos } |