aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_mbe/src/tt_cursor.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_mbe/src/tt_cursor.rs')
-rw-r--r--crates/ra_mbe/src/tt_cursor.rs281
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 @@
1use crate::{subtree_parser::Parser, ParseError};
2
3use ra_parser::FragmentKind;
4use smallvec::{smallvec, SmallVec};
5
6#[derive(Debug, Clone)]
7pub(crate) struct TtCursor<'a> {
8 subtree: &'a tt::Subtree,
9 pos: usize,
10}
11
12pub(crate) struct TtCursorMemento {
13 pos: usize,
14}
15
16impl<'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
238pub(crate) struct TokenPeek<'a, I>
239where
240 I: Iterator<Item = &'a tt::TokenTree>,
241{
242 iter: itertools::MultiPeek<I>,
243}
244
245// helper function
246fn 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
253impl<'a, I> TokenPeek<'a, I>
254where
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}