1use proc_macro::{
4 token_stream, Delimiter, Group, Ident, Literal, Punct, Spacing, TokenStream, TokenTree,
5};
6
7use crate::error::Result;
8
9#[derive(Clone)]
10pub(crate) struct TokenIter {
11 stack: Vec<token_stream::IntoIter>,
12 peeked: Option<TokenTree>,
13 peeked2: Option<TokenTree>,
14 peeked3: Option<TokenTree>,
15 peeked4: Option<TokenTree>,
16}
17
18impl TokenIter {
19 pub(crate) fn new(tokens: TokenStream) -> Self {
20 Self {
21 stack: vec![tokens.into_iter()],
22 peeked: None,
23 peeked2: None,
24 peeked3: None,
25 peeked4: None,
26 }
27 }
28
29 #[allow(clippy::wrong_self_convention)]
30 pub(crate) fn is_empty(&mut self) -> bool {
31 self.peek().is_none()
32 }
33
34 pub(crate) fn peek(&mut self) -> Option<&TokenTree> {
35 self.peeked = self.next();
36 self.peeked.as_ref()
37 }
38
39 pub(crate) fn peek_t(&mut self, token: &dyn Token) -> bool {
40 match self.peek() {
41 Some(tt) => token.match_token(tt),
42 None => false,
43 }
44 }
45
46 pub(crate) fn peek2(&mut self) -> Option<&TokenTree> {
47 let peeked = self.next();
48 let peeked2 = self.next();
49 self.peeked = peeked;
50 self.peeked2 = peeked2;
51 self.peeked2.as_ref()
52 }
53
54 pub(crate) fn peek2_t(&mut self, token: &dyn Token) -> bool {
55 match self.peek2() {
56 Some(tt) => token.match_token(tt),
57 None => false,
58 }
59 }
60
61 pub(crate) fn peek3(&mut self) -> Option<&TokenTree> {
62 let peeked = self.next();
63 let peeked2 = self.next();
64 let peeked3 = self.next();
65 self.peeked = peeked;
66 self.peeked2 = peeked2;
67 self.peeked3 = peeked3;
68 self.peeked3.as_ref()
69 }
70
71 pub(crate) fn peek3_t(&mut self, token: &dyn Token) -> bool {
72 match self.peek3() {
73 Some(tt) => token.match_token(tt),
74 None => false,
75 }
76 }
77
78 pub(crate) fn peek4(&mut self) -> Option<&TokenTree> {
79 let peeked = self.next();
80 let peeked2 = self.next();
81 let peeked3 = self.next();
82 let peeked4 = self.next();
83 self.peeked = peeked;
84 self.peeked2 = peeked2;
85 self.peeked3 = peeked3;
86 self.peeked4 = peeked4;
87 self.peeked4.as_ref()
88 }
89
90 pub(crate) fn peek4_t(&mut self, token: &dyn Token) -> bool {
91 match self.peek4() {
92 Some(tt) => token.match_token(tt),
93 None => false,
94 }
95 }
96
97 pub(crate) fn peek_ident(&mut self) -> Option<&Ident> {
98 match self.peek() {
99 Some(TokenTree::Ident(i)) => Some(i),
100 _ => None,
101 }
102 }
103
104 pub(crate) fn peek2_ident(&mut self) -> Option<&Ident> {
105 match self.peek2() {
106 Some(TokenTree::Ident(i)) => Some(i),
107 _ => None,
108 }
109 }
110
111 pub(crate) fn peek3_ident(&mut self) -> Option<&Ident> {
112 match self.peek3() {
113 Some(TokenTree::Ident(i)) => Some(i),
114 _ => None,
115 }
116 }
117
118 pub(crate) fn parse_ident(&mut self) -> Result<Ident> {
119 match self.next() {
120 Some(TokenTree::Ident(i)) => Ok(i),
121 tt => bail!(tt, "expected identifier"),
123 }
124 }
125
126 pub(crate) fn parse_ident_opt(&mut self) -> Option<Ident> {
127 self.peek_ident()?;
128 Some(self.parse_ident().unwrap())
129 }
130
131 pub(crate) fn parse_kw(&mut self, kw: &str) -> Result<Ident> {
132 let tt = self.next();
133 match &tt {
134 Some(TokenTree::Ident(i)) if i.to_string() == kw => {
135 if let Some(TokenTree::Ident(i)) = tt {
136 Ok(i)
137 } else {
138 unreachable!()
139 }
140 }
141 tt => bail!(tt, "expected `{}`", kw),
143 }
144 }
145
146 pub(crate) fn parse_kw_opt(&mut self, kw: &str) -> Option<Ident> {
147 if self.peek_t(&kw) {
148 Some(self.parse_ident().unwrap())
149 } else {
150 None
151 }
152 }
153
154 pub(crate) fn peek_punct(&mut self, ch: char) -> Option<&Punct> {
155 match self.peek() {
156 Some(TokenTree::Punct(p)) if p.as_char() == ch => Some(p),
157 _ => None,
158 }
159 }
160
161 pub(crate) fn peek2_punct(&mut self, ch: char) -> Option<&Punct> {
162 match self.peek2() {
163 Some(TokenTree::Punct(p)) if p.as_char() == ch => Some(p),
164 _ => None,
165 }
166 }
167
168 pub(crate) fn parse_punct(&mut self, ch: char) -> Result<Punct> {
169 let tt = self.next();
170 match &tt {
171 Some(TokenTree::Punct(p)) if p.as_char() == ch => {
172 if let Some(TokenTree::Punct(p)) = tt {
173 Ok(p)
174 } else {
175 unreachable!()
176 }
177 }
178 tt => bail!(tt, "expected `{}`", ch),
180 }
181 }
182
183 pub(crate) fn parse_punct_opt(&mut self, ch: char) -> Option<Punct> {
184 self.peek_punct(ch)?;
185 Some(self.parse_punct(ch).unwrap())
186 }
187
188 pub(crate) fn peek_lifetime(&mut self) -> bool {
189 self.peek_punct('\'').map_or(false, |p| p.spacing() == Spacing::Joint)
190 && self.peek2_ident().is_some()
191 }
192
193 pub(crate) fn peek2_lifetime(&mut self) -> bool {
194 self.peek2_punct('\'').map_or(false, |p| p.spacing() == Spacing::Joint)
195 && self.peek3_ident().is_some()
196 }
197
198 pub(crate) fn parse_group(&mut self, delimiter: Delimiter) -> Result<Group> {
199 let tt = self.next();
200 match &tt {
201 Some(TokenTree::Group(g)) if g.delimiter() == delimiter => {
202 if let Some(TokenTree::Group(g)) = tt {
203 Ok(g)
204 } else {
205 unreachable!()
206 }
207 }
208 tt => {
209 let d = match delimiter {
210 Delimiter::Brace => "`{`",
211 Delimiter::Bracket => "`[`",
212 Delimiter::Parenthesis => "`(`",
213 Delimiter::None => "none-delimited group",
214 };
215 bail!(tt, "expected {}", d)
217 }
218 }
219 }
220
221 pub(crate) fn peek_literal(&mut self) -> Option<&Literal> {
222 match self.peek() {
223 Some(TokenTree::Literal(l)) => Some(l),
224 _ => None,
225 }
226 }
227
228 pub(crate) fn parse_literal(&mut self) -> Result<Literal> {
229 match self.next() {
230 Some(TokenTree::Literal(l)) => Ok(l),
231 tt => bail!(tt, "expected literal"),
233 }
234 }
235
236 pub(crate) fn parse_literal_opt(&mut self) -> Option<Literal> {
237 self.peek_literal()?;
238 Some(self.parse_literal().unwrap())
239 }
240
241 pub(crate) fn tt(&mut self) -> Result<TokenTree> {
242 self.next().ok_or_else(|| {
243 format_err!(TokenStream::new(), "unexpected end of input")
245 })
246 }
247}
248
249impl Iterator for TokenIter {
251 type Item = TokenTree;
252
253 fn next(&mut self) -> Option<Self::Item> {
254 if let Some(tt) = self.peeked.take() {
255 return Some(tt);
256 }
257 if let Some(tt) = self.peeked2.take() {
258 return Some(tt);
259 }
260 if let Some(tt) = self.peeked3.take() {
261 return Some(tt);
262 }
263 if let Some(tt) = self.peeked4.take() {
264 return Some(tt);
265 }
266 loop {
267 let top = self.stack.last_mut()?;
268 match top.next() {
269 None => drop(self.stack.pop()),
270 Some(TokenTree::Group(ref group)) if group.delimiter() == Delimiter::None => {
271 self.stack.push(group.stream().into_iter());
272 }
273 Some(tt) => return Some(tt),
274 }
275 }
276 }
277}
278
279pub(crate) trait Token {
280 fn match_token(&self, tt: &TokenTree) -> bool;
281}
282
283impl Token for char {
284 fn match_token(&self, tt: &TokenTree) -> bool {
285 match tt {
286 TokenTree::Punct(p) => p.as_char() == *self,
287 _ => false,
288 }
289 }
290}
291
292impl Token for &str {
293 fn match_token(&self, tt: &TokenTree) -> bool {
294 match tt {
295 TokenTree::Ident(i) => i.to_string() == *self,
296 _ => false,
297 }
298 }
299}
300
301impl Token for Delimiter {
302 fn match_token(&self, tt: &TokenTree) -> bool {
303 match tt {
304 TokenTree::Group(g) => g.delimiter() == *self,
305 _ => false,
306 }
307 }
308}