1use crate::int_stream::{EOF, IntStream, UNKNOWN_SOURCE_NAME};
2use crate::token::{CommonToken, DEFAULT_CHANNEL, TOKEN_EOF, Token, TokenSource, TokenSourceError};
3
4#[derive(Debug)]
5pub struct CommonTokenStream<S> {
6 source: S,
7 tokens: Vec<CommonToken>,
8 next_visible_after: Vec<usize>,
9 cursor: usize,
10 fetched_eof: bool,
11 channel: i32,
12 source_errors: Vec<TokenSourceError>,
13}
14
15const UNKNOWN_NEXT_VISIBLE: usize = usize::MAX;
16
17impl<S> CommonTokenStream<S>
18where
19 S: TokenSource,
20{
21 pub const fn new(source: S) -> Self {
23 Self::with_channel(source, DEFAULT_CHANNEL)
24 }
25
26 pub const fn with_channel(source: S, channel: i32) -> Self {
28 Self {
29 source,
30 tokens: Vec::new(),
31 next_visible_after: Vec::new(),
32 cursor: 0,
33 fetched_eof: false,
34 channel,
35 source_errors: Vec::new(),
36 }
37 }
38
39 pub fn fill(&mut self) {
41 while !self.fetched_eof {
42 self.fetch_one();
43 }
44 self.cursor = self.adjust_seek_index(self.cursor);
45 }
46
47 pub fn get(&mut self, index: usize) -> Option<&CommonToken> {
50 self.sync(index);
51 self.tokens.get(index)
52 }
53
54 pub fn lt(&mut self, offset: isize) -> Option<&CommonToken> {
57 if offset == 0 {
58 return None;
59 }
60 if offset < 0 {
61 return offset
62 .checked_neg()
63 .map(isize::cast_unsigned)
64 .and_then(|offset| self.lb(offset));
65 }
66
67 let mut index = self.next_token_on_channel(self.cursor, self.channel);
68 let mut remaining = offset;
69 while remaining > 1 {
70 index = self.next_token_on_channel(index + 1, self.channel);
71 remaining -= 1;
72 }
73 self.sync(index);
74 self.tokens.get(index)
75 }
76
77 pub fn lb(&self, offset: usize) -> Option<&CommonToken> {
78 if offset == 0 || self.cursor == 0 {
79 return None;
80 }
81 let mut index = self.cursor;
82 let mut remaining = offset;
83 while remaining > 0 {
84 index = self.previous_token_on_channel(index, self.channel)?;
85 remaining -= 1;
86 }
87 self.tokens.get(index)
88 }
89
90 pub const fn token_source(&self) -> &S {
91 &self.source
92 }
93
94 pub fn tokens(&self) -> &[CommonToken] {
95 &self.tokens
96 }
97
98 fn sync(&mut self, index: usize) -> bool {
100 if index < self.tokens.len() {
101 return true;
102 }
103 let needed = index + 1 - self.tokens.len();
104 self.fetch(needed) >= needed
105 }
106
107 fn fetch(&mut self, count: usize) -> usize {
109 let mut fetched = 0;
110 while fetched < count && !self.fetched_eof {
111 self.fetch_one();
112 fetched += 1;
113 }
114 fetched
115 }
116
117 fn fetch_one(&mut self) {
118 let mut token = self.source.next_token();
119 self.source_errors.extend(self.source.drain_errors());
120 let token_index = isize::try_from(self.tokens.len()).unwrap_or(isize::MAX);
121 token.set_token_index(token_index);
122 self.fetched_eof = token.token_type() == TOKEN_EOF;
123 self.tokens.push(token);
124 self.next_visible_after.push(UNKNOWN_NEXT_VISIBLE);
125 }
126
127 fn adjust_seek_index(&mut self, index: usize) -> usize {
130 self.next_token_on_channel(index, self.channel)
131 }
132
133 fn next_token_on_channel(&mut self, mut index: usize, channel: i32) -> usize {
135 self.sync(index);
136 while let Some(token) = self.tokens.get(index) {
137 if token.token_type() == TOKEN_EOF || token.channel() == channel {
138 return index;
139 }
140 index += 1;
141 self.sync(index);
142 }
143 index
144 }
145
146 fn previous_token_on_channel(&self, mut index: usize, channel: i32) -> Option<usize> {
148 while index > 0 {
149 index -= 1;
150 let token = self.tokens.get(index)?;
151 if token.token_type() == TOKEN_EOF || token.channel() == channel {
152 return Some(index);
153 }
154 }
155 None
156 }
157
158 pub fn previous_visible_token_index(&mut self, index: usize) -> Option<usize> {
167 if index > 0 {
168 self.sync(index - 1);
169 }
170 self.previous_token_on_channel(index, self.channel)
171 }
172}
173
174impl<S> IntStream for CommonTokenStream<S>
175where
176 S: TokenSource,
177{
178 fn consume(&mut self) {
179 if self.la(1) == EOF {
180 return;
181 }
182 let current = self.next_token_on_channel(self.cursor, self.channel);
183 self.cursor = self.adjust_seek_index(current + 1);
184 }
185
186 fn la(&mut self, offset: isize) -> i32 {
187 self.la_token(offset)
188 }
189
190 fn index(&self) -> usize {
191 self.cursor
192 }
193
194 fn seek(&mut self, index: usize) {
195 self.cursor = self.adjust_seek_index(index);
196 }
197
198 fn size(&self) -> usize {
199 self.tokens.len()
200 }
201
202 fn source_name(&self) -> &str {
203 let source_name = self.source.source_name();
204 if source_name.is_empty() {
205 UNKNOWN_SOURCE_NAME
206 } else {
207 source_name
208 }
209 }
210}
211
212impl<S> CommonTokenStream<S>
213where
214 S: TokenSource,
215{
216 pub fn la_token(&mut self, offset: isize) -> i32 {
217 self.lt(offset).map_or(TOKEN_EOF, Token::token_type)
218 }
219
220 pub fn token_type_at_index(&mut self, index: usize) -> i32 {
226 self.sync(index);
227 self.tokens.get(index).map_or(TOKEN_EOF, Token::token_type)
228 }
229
230 pub fn next_visible_after(&mut self, index: usize) -> usize {
235 self.sync(index);
236 if let Some(cached) = self
237 .next_visible_after
238 .get(index)
239 .copied()
240 .filter(|cached| *cached != UNKNOWN_NEXT_VISIBLE)
241 {
242 return cached;
243 }
244
245 let mut next = index + 1;
246 let found = loop {
247 self.sync(next);
248 match self.tokens.get(next) {
249 Some(token)
250 if token.token_type() != TOKEN_EOF && token.channel() != self.channel =>
251 {
252 next += 1;
253 continue;
254 }
255 _ => break next,
256 }
257 };
258 if let Some(slot) = self.next_visible_after.get_mut(index) {
259 *slot = found;
260 }
261 found
262 }
263
264 pub fn text(&mut self, start: usize, stop: usize) -> String {
265 self.sync(stop);
266 if start > stop || start >= self.tokens.len() {
267 return String::new();
268 }
269 self.tokens[start..=stop.min(self.tokens.len().saturating_sub(1))]
270 .iter()
271 .filter_map(Token::text)
272 .collect::<Vec<_>>()
273 .join("")
274 }
275
276 pub fn drain_source_errors(&mut self) -> Vec<TokenSourceError> {
279 std::mem::take(&mut self.source_errors)
280 }
281
282 pub const fn is_filled(&self) -> bool {
283 self.fetched_eof
284 }
285}
286
287#[cfg(test)]
288mod tests {
289 use super::*;
290 use crate::token::{CommonToken, HIDDEN_CHANNEL};
291
292 #[derive(Debug)]
293 struct VecTokenSource {
294 tokens: Vec<CommonToken>,
295 index: usize,
296 }
297
298 impl TokenSource for VecTokenSource {
299 fn next_token(&mut self) -> CommonToken {
300 let token = self
301 .tokens
302 .get(self.index)
303 .cloned()
304 .unwrap_or_else(|| CommonToken::eof("vec", self.index, 1, self.index));
305 self.index += 1;
306 token
307 }
308
309 fn line(&self) -> usize {
310 1
311 }
312
313 fn column(&self) -> usize {
314 self.index
315 }
316
317 fn source_name(&self) -> &'static str {
318 "vec"
319 }
320 }
321
322 #[test]
323 fn stream_skips_hidden_channel_for_lookahead() {
324 let source = VecTokenSource {
325 tokens: vec![
326 CommonToken::new(1).with_text("a"),
327 CommonToken::new(2)
328 .with_text(" ")
329 .with_channel(HIDDEN_CHANNEL),
330 CommonToken::new(3).with_text("b"),
331 CommonToken::eof("vec", 3, 1, 3),
332 ],
333 index: 0,
334 };
335 let mut stream = CommonTokenStream::new(source);
336 assert_eq!(stream.la_token(1), 1);
337 stream.consume();
338 assert_eq!(stream.la_token(1), 3);
339 assert_eq!(
340 stream
341 .lt(-1)
342 .expect("look-behind token should be buffered")
343 .token_type(),
344 1
345 );
346 }
347
348 #[test]
349 fn lookahead_skips_hidden_token_at_initial_cursor() {
350 let source = VecTokenSource {
351 tokens: vec![
352 CommonToken::new(2)
353 .with_text(" ")
354 .with_channel(HIDDEN_CHANNEL),
355 CommonToken::new(1).with_text("a"),
356 CommonToken::eof("vec", 2, 1, 2),
357 ],
358 index: 0,
359 };
360 let mut stream = CommonTokenStream::new(source);
361
362 assert_eq!(stream.la_token(1), 1);
363 assert_eq!(stream.lt(1).and_then(Token::text), Some("a"));
364 stream.consume();
365 assert_eq!(stream.la_token(1), TOKEN_EOF);
366 }
367
368 #[test]
369 fn text_returns_empty_when_start_is_past_buffer() {
370 let source = VecTokenSource {
371 tokens: vec![
372 CommonToken::new(1).with_text("a"),
373 CommonToken::eof("vec", 1, 1, 1),
374 ],
375 index: 0,
376 };
377 let mut stream = CommonTokenStream::new(source);
378
379 assert_eq!(stream.text(10, 12), "");
380 }
381}