tenda_parser/
token_iter.rs

1use peekmore::{PeekMore, PeekMoreIterator};
2use std::{cell::RefCell, ops::Neg, rc::Rc, slice::Iter};
3use tenda_scanner::{Token, TokenKind};
4
5#[derive(Debug, Clone)]
6pub struct TokenIterator<'a> {
7    tokens: PeekMoreIterator<Iter<'a, Token>>,
8    ignoring_newline_counter: Rc<RefCell<isize>>,
9    last_token: &'a Token,
10}
11
12impl TokenIterator<'_> {
13    pub fn peek(&mut self) -> Option<&&Token> {
14        self.skip_ignored_newlines();
15        self.tokens.peek()
16    }
17
18    pub fn set_ignoring_newline(&mut self) -> NewlineGuard {
19        NewlineGuard::new(self.ignoring_newline_counter.clone(), None)
20    }
21
22    pub fn halt_ignoring_newline(&mut self) -> NewlineGuard {
23        let size = self.ignoring_newline_counter.borrow().neg();
24
25        NewlineGuard::new(self.ignoring_newline_counter.clone(), Some(size))
26    }
27
28    pub fn consume_one_of(&mut self, token_types: &[TokenKind]) -> Option<Token> {
29        self.tokens.reset_cursor();
30
31        while let Some(token) = self.tokens.peek() {
32            if token.kind == TokenKind::Newline && *self.ignoring_newline_counter.borrow() > 0 {
33                self.tokens.advance_cursor();
34            } else {
35                break;
36            }
37        }
38
39        let skipped = self.tokens.cursor();
40
41        if let Some(token) = self.tokens.peek() {
42            if token_types.contains(&token.kind) {
43                for _ in 0..skipped {
44                    self.tokens.next();
45                }
46
47                return self.tokens.next().cloned();
48            }
49        }
50
51        self.tokens.reset_cursor();
52
53        None
54    }
55
56    pub fn consume_sequence(&mut self, token_types: &[TokenKind]) -> Option<Vec<Token>> {
57        self.tokens.reset_cursor();
58
59        for token_type in token_types {
60            while let Some(token) = self.tokens.peek() {
61                if token.kind == TokenKind::Newline && *self.ignoring_newline_counter.borrow() > 0 {
62                    self.tokens.advance_cursor();
63                } else {
64                    break;
65                }
66            }
67
68            match self.tokens.peek() {
69                Some(token) if token.kind == *token_type => {
70                    self.tokens.advance_cursor();
71                }
72                _ => {
73                    self.tokens.reset_cursor();
74
75                    return None;
76                }
77            }
78        }
79
80        let count = self.tokens.cursor();
81        let mut tokens = Vec::with_capacity(count);
82
83        for _ in 0..count {
84            tokens.push(self.tokens.next().cloned().unwrap());
85        }
86
87        Some(tokens)
88    }
89
90    pub fn check_sequence(&mut self, token_types: &[TokenKind]) -> bool {
91        self.tokens.reset_cursor();
92
93        for token_type in token_types {
94            while let Some(token) = self.tokens.peek() {
95                if token.kind == TokenKind::Newline && *self.ignoring_newline_counter.borrow() > 0 {
96                    self.tokens.advance_cursor();
97                } else {
98                    break;
99                }
100            }
101
102            match self.tokens.peek() {
103                Some(token) if token.kind == *token_type => {
104                    self.tokens.advance_cursor();
105                }
106                _ => {
107                    self.tokens.reset_cursor();
108
109                    return false;
110                }
111            }
112        }
113
114        self.tokens.reset_cursor();
115
116        true
117    }
118
119    pub fn is_next_token(&mut self, token_type: TokenKind) -> bool {
120        self.tokens.reset_cursor();
121
122        while let Some(token) = self.tokens.peek() {
123            if token.kind == TokenKind::Newline && *self.ignoring_newline_counter.borrow() > 0 {
124                self.tokens.advance_cursor();
125            } else {
126                break;
127            }
128        }
129
130        if let Some(token) = self.tokens.peek() {
131            if token.kind == token_type {
132                return true;
133            }
134        }
135
136        self.tokens.reset_cursor();
137
138        false
139    }
140
141    pub fn is_next_eof(&mut self) -> bool {
142        self.tokens.reset_cursor();
143
144        while let Some(token) = self.tokens.peek() {
145            if token.kind == TokenKind::Newline {
146                self.tokens.advance_cursor();
147            } else {
148                break;
149            }
150        }
151
152        let is_eof = matches!(
153            self.tokens.peek(),
154            None | Some(Token {
155                kind: TokenKind::Eof,
156                ..
157            })
158        );
159
160        self.tokens.reset_cursor();
161
162        is_eof
163    }
164
165    pub fn is_next_valid(&mut self) -> bool {
166        self.tokens.reset_cursor();
167
168        while let Some(token) = self.tokens.peek() {
169            if token.kind == TokenKind::Newline && *self.ignoring_newline_counter.borrow() > 0 {
170                self.tokens.advance_cursor();
171            } else {
172                break;
173            }
174        }
175
176        let is_next_valid = !matches!(
177            self.tokens.peek(),
178            None | Some(Token {
179                kind: TokenKind::Eof,
180                ..
181            })
182        );
183
184        self.tokens.reset_cursor();
185
186        is_next_valid
187    }
188
189    pub fn advance_while(&mut self, expected_types: &[TokenKind]) {
190        while let Some(token) = self.tokens.peek() {
191            if expected_types.contains(&token.kind) {
192                self.tokens.next();
193            } else {
194                break;
195            }
196        }
197    }
198
199    pub fn last_token(&self) -> &Token {
200        self.last_token
201    }
202
203    fn skip_ignored_newlines(&mut self) {
204        while let Some(token) = self.tokens.peek() {
205            if token.kind == TokenKind::Newline && *self.ignoring_newline_counter.borrow() > 0 {
206                self.tokens.next();
207            } else {
208                break;
209            }
210        }
211    }
212}
213
214impl<'a> Iterator for TokenIterator<'a> {
215    type Item = &'a Token;
216
217    fn next(&mut self) -> Option<Self::Item> {
218        self.skip_ignored_newlines();
219        self.tokens.next()
220    }
221}
222
223impl<'a> From<&'a [Token]> for TokenIterator<'a> {
224    fn from(value: &'a [Token]) -> Self {
225        TokenIterator {
226            tokens: value.iter().peekmore(),
227            ignoring_newline_counter: Rc::new(RefCell::new(0)),
228            last_token: value.last().expect("token list should not be empty"),
229        }
230    }
231}
232
233pub struct NewlineGuard {
234    counter: Rc<RefCell<isize>>,
235    size: isize,
236}
237
238impl NewlineGuard {
239    pub fn new(counter: Rc<RefCell<isize>>, custom_size: Option<isize>) -> Self {
240        let size = custom_size.unwrap_or(1);
241
242        *counter.borrow_mut() += size;
243
244        NewlineGuard { counter, size }
245    }
246}
247
248impl Drop for NewlineGuard {
249    fn drop(&mut self) {
250        *self.counter.borrow_mut() -= self.size;
251    }
252}
253
254#[macro_export]
255macro_rules! token_slice {
256    ($($kind:expr),*) => {
257        {
258            use tenda_scanner::TokenKind::*;
259            &[$($kind),*]
260        }
261    };
262}