diff options
Diffstat (limited to 'crates/ra_mbe/src/tt_cursor.rs')
-rw-r--r-- | crates/ra_mbe/src/tt_cursor.rs | 281 |
1 files changed, 0 insertions, 281 deletions
diff --git a/crates/ra_mbe/src/tt_cursor.rs b/crates/ra_mbe/src/tt_cursor.rs deleted file mode 100644 index a69c006c7..000000000 --- a/crates/ra_mbe/src/tt_cursor.rs +++ /dev/null | |||
@@ -1,281 +0,0 @@ | |||
1 | use crate::{subtree_parser::Parser, ParseError}; | ||
2 | |||
3 | use ra_parser::FragmentKind; | ||
4 | use smallvec::{smallvec, SmallVec}; | ||
5 | |||
6 | #[derive(Debug, Clone)] | ||
7 | pub(crate) struct TtCursor<'a> { | ||
8 | subtree: &'a tt::Subtree, | ||
9 | pos: usize, | ||
10 | } | ||
11 | |||
12 | pub(crate) struct TtCursorMemento { | ||
13 | pos: usize, | ||
14 | } | ||
15 | |||
16 | impl<'a> TtCursor<'a> { | ||
17 | pub(crate) fn new(subtree: &'a tt::Subtree) -> TtCursor<'a> { | ||
18 | TtCursor { subtree, pos: 0 } | ||
19 | } | ||
20 | |||
21 | pub(crate) fn is_eof(&self) -> bool { | ||
22 | self.pos == self.subtree.token_trees.len() | ||
23 | } | ||
24 | |||
25 | pub(crate) fn current(&self) -> Option<&'a tt::TokenTree> { | ||
26 | self.subtree.token_trees.get(self.pos) | ||
27 | } | ||
28 | |||
29 | pub(crate) fn at_punct(&self) -> Option<&'a tt::Punct> { | ||
30 | match self.current() { | ||
31 | Some(tt::TokenTree::Leaf(tt::Leaf::Punct(it))) => Some(it), | ||
32 | _ => None, | ||
33 | } | ||
34 | } | ||
35 | |||
36 | pub(crate) fn at_char(&self, char: char) -> bool { | ||
37 | match self.at_punct() { | ||
38 | Some(tt::Punct { char: c, .. }) if *c == char => true, | ||
39 | _ => false, | ||
40 | } | ||
41 | } | ||
42 | |||
43 | pub(crate) fn at_ident(&mut self) -> Option<&'a tt::Ident> { | ||
44 | match self.current() { | ||
45 | Some(tt::TokenTree::Leaf(tt::Leaf::Ident(i))) => Some(i), | ||
46 | _ => None, | ||
47 | } | ||
48 | } | ||
49 | |||
50 | pub(crate) fn at_literal(&mut self) -> Option<&'a tt::Literal> { | ||
51 | match self.current() { | ||
52 | Some(tt::TokenTree::Leaf(tt::Leaf::Literal(i))) => Some(i), | ||
53 | _ => None, | ||
54 | } | ||
55 | } | ||
56 | |||
57 | pub(crate) fn bump(&mut self) { | ||
58 | self.pos += 1; | ||
59 | } | ||
60 | pub(crate) fn rev_bump(&mut self) { | ||
61 | self.pos -= 1; | ||
62 | } | ||
63 | |||
64 | pub(crate) fn eat(&mut self) -> Option<&'a tt::TokenTree> { | ||
65 | self.current().map(|it| { | ||
66 | self.bump(); | ||
67 | it | ||
68 | }) | ||
69 | } | ||
70 | |||
71 | pub(crate) fn eat_subtree(&mut self) -> Result<&'a tt::Subtree, ParseError> { | ||
72 | match self.current() { | ||
73 | Some(tt::TokenTree::Subtree(sub)) => { | ||
74 | self.bump(); | ||
75 | Ok(sub) | ||
76 | } | ||
77 | _ => Err(ParseError::Expected(String::from("subtree"))), | ||
78 | } | ||
79 | } | ||
80 | |||
81 | pub(crate) fn eat_punct(&mut self) -> Option<&'a tt::Punct> { | ||
82 | self.at_punct().map(|it| { | ||
83 | self.bump(); | ||
84 | it | ||
85 | }) | ||
86 | } | ||
87 | |||
88 | pub(crate) fn eat_ident(&mut self) -> Option<&'a tt::Ident> { | ||
89 | self.at_ident().map(|i| { | ||
90 | self.bump(); | ||
91 | i | ||
92 | }) | ||
93 | } | ||
94 | |||
95 | pub(crate) fn eat_literal(&mut self) -> Option<&'a tt::Literal> { | ||
96 | self.at_literal().map(|i| { | ||
97 | self.bump(); | ||
98 | i | ||
99 | }) | ||
100 | } | ||
101 | |||
102 | pub(crate) fn eat_fragment(&mut self, fragment_kind: FragmentKind) -> Option<tt::TokenTree> { | ||
103 | let parser = Parser::new(&mut self.pos, self.subtree); | ||
104 | parser.parse_fragment(fragment_kind) | ||
105 | } | ||
106 | |||
107 | pub(crate) fn eat_lifetime(&mut self) -> Option<tt::TokenTree> { | ||
108 | // check if it start from "`" | ||
109 | if let Some(ident) = self.at_ident() { | ||
110 | if ident.text.chars().next()? != '\'' { | ||
111 | return None; | ||
112 | } | ||
113 | } | ||
114 | |||
115 | self.eat_ident().cloned().map(|ident| tt::Leaf::from(ident).into()) | ||
116 | } | ||
117 | |||
118 | pub(crate) fn try_eat_vis(&mut self) -> Option<tt::TokenTree> { | ||
119 | // `vis` matcher is optional | ||
120 | let old_pos = self.pos; | ||
121 | let parser = Parser::new(&mut self.pos, self.subtree); | ||
122 | |||
123 | let res = parser.parse_fragment(FragmentKind::Visibility); | ||
124 | if res.is_none() { | ||
125 | self.pos = old_pos; | ||
126 | } | ||
127 | res | ||
128 | } | ||
129 | |||
130 | pub(crate) fn expect_char(&mut self, char: char) -> Result<(), ParseError> { | ||
131 | if self.at_char(char) { | ||
132 | self.bump(); | ||
133 | Ok(()) | ||
134 | } else { | ||
135 | Err(ParseError::Expected(format!("`{}`", char))) | ||
136 | } | ||
137 | } | ||
138 | |||
139 | fn eat_punct3(&mut self, p: tt::Punct) -> Option<SmallVec<[tt::Punct; 3]>> { | ||
140 | let sec = *self.eat_punct()?; | ||
141 | let third = *self.eat_punct()?; | ||
142 | Some(smallvec![p, sec, third]) | ||
143 | } | ||
144 | |||
145 | fn eat_punct2(&mut self, p: tt::Punct) -> Option<SmallVec<[tt::Punct; 3]>> { | ||
146 | let sec = *self.eat_punct()?; | ||
147 | Some(smallvec![p, sec]) | ||
148 | } | ||
149 | |||
150 | fn eat_multi_char_punct<'b, I>( | ||
151 | &mut self, | ||
152 | p: tt::Punct, | ||
153 | iter: &mut TokenPeek<'b, I>, | ||
154 | ) -> Option<SmallVec<[tt::Punct; 3]>> | ||
155 | where | ||
156 | I: Iterator<Item = &'b tt::TokenTree>, | ||
157 | { | ||
158 | if let Some((m, _)) = iter.current_punct3(p) { | ||
159 | if let r @ Some(_) = match m { | ||
160 | ('<', '<', '=') | ('>', '>', '=') | ('.', '.', '.') | ('.', '.', '=') => { | ||
161 | self.eat_punct3(p) | ||
162 | } | ||
163 | _ => None, | ||
164 | } { | ||
165 | return r; | ||
166 | } | ||
167 | } | ||
168 | |||
169 | if let Some((m, _)) = iter.current_punct2(p) { | ||
170 | if let r @ Some(_) = match m { | ||
171 | ('<', '=') | ||
172 | | ('>', '=') | ||
173 | | ('+', '=') | ||
174 | | ('-', '=') | ||
175 | | ('|', '=') | ||
176 | | ('&', '=') | ||
177 | | ('^', '=') | ||
178 | | ('/', '=') | ||
179 | | ('*', '=') | ||
180 | | ('%', '=') | ||
181 | | ('&', '&') | ||
182 | | ('|', '|') | ||
183 | | ('<', '<') | ||
184 | | ('>', '>') | ||
185 | | ('-', '>') | ||
186 | | ('!', '=') | ||
187 | | ('=', '>') | ||
188 | | ('=', '=') | ||
189 | | ('.', '.') | ||
190 | | (':', ':') => self.eat_punct2(p), | ||
191 | |||
192 | _ => None, | ||
193 | } { | ||
194 | return r; | ||
195 | } | ||
196 | } | ||
197 | |||
198 | None | ||
199 | } | ||
200 | |||
201 | pub(crate) fn eat_seperator(&mut self) -> Option<crate::Separator> { | ||
202 | match self.eat()? { | ||
203 | tt::TokenTree::Leaf(tt::Leaf::Literal(lit)) => { | ||
204 | Some(crate::Separator::Literal(lit.clone())) | ||
205 | } | ||
206 | tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) => { | ||
207 | Some(crate::Separator::Ident(ident.clone())) | ||
208 | } | ||
209 | tt::TokenTree::Leaf(tt::Leaf::Punct(punct)) => { | ||
210 | match punct.char { | ||
211 | '*' | '+' | '?' => return None, | ||
212 | _ => {} | ||
213 | }; | ||
214 | |||
215 | // FIXME: The parser is only handle some compositeable punct, | ||
216 | // But at this phase, some punct still is jointed. | ||
217 | // So we by pass that check here. | ||
218 | let mut peekable = TokenPeek::new(self.subtree.token_trees[self.pos..].iter()); | ||
219 | let puncts = self.eat_multi_char_punct(*punct, &mut peekable); | ||
220 | let puncts = puncts.unwrap_or_else(|| smallvec![*punct]); | ||
221 | |||
222 | Some(crate::Separator::Puncts(puncts)) | ||
223 | } | ||
224 | _ => None, | ||
225 | } | ||
226 | } | ||
227 | |||
228 | #[must_use] | ||
229 | pub(crate) fn save(&self) -> TtCursorMemento { | ||
230 | TtCursorMemento { pos: self.pos } | ||
231 | } | ||
232 | |||
233 | pub(crate) fn rollback(&mut self, memento: TtCursorMemento) { | ||
234 | self.pos = memento.pos; | ||
235 | } | ||
236 | } | ||
237 | |||
238 | pub(crate) struct TokenPeek<'a, I> | ||
239 | where | ||
240 | I: Iterator<Item = &'a tt::TokenTree>, | ||
241 | { | ||
242 | iter: itertools::MultiPeek<I>, | ||
243 | } | ||
244 | |||
245 | // helper function | ||
246 | fn to_punct(tt: &tt::TokenTree) -> Option<&tt::Punct> { | ||
247 | if let tt::TokenTree::Leaf(tt::Leaf::Punct(pp)) = tt { | ||
248 | return Some(pp); | ||
249 | } | ||
250 | None | ||
251 | } | ||
252 | |||
253 | impl<'a, I> TokenPeek<'a, I> | ||
254 | where | ||
255 | I: Iterator<Item = &'a tt::TokenTree>, | ||
256 | { | ||
257 | pub fn new(iter: I) -> Self { | ||
258 | TokenPeek { iter: itertools::multipeek(iter) } | ||
259 | } | ||
260 | |||
261 | pub fn current_punct2(&mut self, p: tt::Punct) -> Option<((char, char), bool)> { | ||
262 | if p.spacing != tt::Spacing::Joint { | ||
263 | return None; | ||
264 | } | ||
265 | |||
266 | self.iter.reset_peek(); | ||
267 | let p1 = to_punct(self.iter.peek()?)?; | ||
268 | Some(((p.char, p1.char), p1.spacing == tt::Spacing::Joint)) | ||
269 | } | ||
270 | |||
271 | pub fn current_punct3(&mut self, p: tt::Punct) -> Option<((char, char, char), bool)> { | ||
272 | self.current_punct2(p).and_then(|((p0, p1), last_joint)| { | ||
273 | if !last_joint { | ||
274 | None | ||
275 | } else { | ||
276 | let p2 = to_punct(*self.iter.peek()?)?; | ||
277 | Some(((p0, p1, p2.char), p2.spacing == tt::Spacing::Joint)) | ||
278 | } | ||
279 | }) | ||
280 | } | ||
281 | } | ||