Skip to main content

antlr4_runtime/
token_stream.rs

1use crate::int_stream::{EOF, IntStream, UNKNOWN_SOURCE_NAME};
2use std::rc::Rc;
3
4use crate::token::{
5    CommonToken, DEFAULT_CHANNEL, TOKEN_EOF, Token, TokenRef, TokenSource, TokenSourceError,
6};
7
8#[derive(Debug)]
9pub struct CommonTokenStream<S> {
10    source: S,
11    tokens: Vec<TokenRef>,
12    public_tokens: Vec<CommonToken>,
13    next_visible_after: Vec<usize>,
14    cursor: usize,
15    fetched_eof: bool,
16    channel: i32,
17    source_errors: Vec<TokenSourceError>,
18}
19
20const UNKNOWN_NEXT_VISIBLE: usize = usize::MAX;
21
22impl<S> CommonTokenStream<S>
23where
24    S: TokenSource,
25{
26    /// Creates a token stream that filters lookahead to the default channel.
27    pub const fn new(source: S) -> Self {
28        Self::with_channel(source, DEFAULT_CHANNEL)
29    }
30
31    /// Creates a token stream whose `LT/LA` operations see only `channel`.
32    pub const fn with_channel(source: S, channel: i32) -> Self {
33        Self {
34            source,
35            tokens: Vec::new(),
36            public_tokens: Vec::new(),
37            next_visible_after: Vec::new(),
38            cursor: 0,
39            fetched_eof: false,
40            channel,
41            source_errors: Vec::new(),
42        }
43    }
44
45    /// Reads tokens from the source until EOF is buffered.
46    pub fn fill(&mut self) {
47        while !self.fetched_eof {
48            self.fetch_one();
49        }
50        self.cursor = self.adjust_seek_index(self.cursor);
51    }
52
53    /// Returns the token at an absolute buffered index, fetching from the source
54    /// as needed.
55    pub fn get(&mut self, index: usize) -> Option<&CommonToken> {
56        self.sync(index);
57        self.tokens.get(index).map(Rc::as_ref)
58    }
59
60    /// Returns a shared reference-counted token at an absolute buffered index.
61    pub fn get_ref(&mut self, index: usize) -> Option<TokenRef> {
62        self.sync(index);
63        self.tokens.get(index).map(Rc::clone)
64    }
65
66    /// Returns the token at one-based lookahead/lookbehind offset, skipping
67    /// tokens outside the configured channel for positive offsets.
68    pub fn lt(&mut self, offset: isize) -> Option<&CommonToken> {
69        if offset == 0 {
70            return None;
71        }
72        if offset < 0 {
73            return offset
74                .checked_neg()
75                .map(isize::cast_unsigned)
76                .and_then(|offset| self.lb(offset));
77        }
78
79        let mut index = self.next_token_on_channel(self.cursor, self.channel);
80        let mut remaining = offset;
81        while remaining > 1 {
82            index = self.next_token_on_channel(index + 1, self.channel);
83            remaining -= 1;
84        }
85        self.sync(index);
86        self.tokens.get(index).map(Rc::as_ref)
87    }
88
89    /// Returns the token at one-based lookahead/lookbehind offset as a shared
90    /// reference-counted token.
91    pub fn lt_ref(&mut self, offset: isize) -> Option<TokenRef> {
92        if offset == 0 {
93            return None;
94        }
95        if offset < 0 {
96            return offset
97                .checked_neg()
98                .map(isize::cast_unsigned)
99                .and_then(|offset| self.lb_ref(offset));
100        }
101
102        let mut index = self.next_token_on_channel(self.cursor, self.channel);
103        let mut remaining = offset;
104        while remaining > 1 {
105            index = self.next_token_on_channel(index + 1, self.channel);
106            remaining -= 1;
107        }
108        self.sync(index);
109        self.tokens.get(index).map(Rc::clone)
110    }
111
112    pub fn lb(&self, offset: usize) -> Option<&CommonToken> {
113        if offset == 0 || self.cursor == 0 {
114            return None;
115        }
116        let mut index = self.cursor;
117        let mut remaining = offset;
118        while remaining > 0 {
119            index = self.previous_token_on_channel(index, self.channel)?;
120            remaining -= 1;
121        }
122        self.tokens.get(index).map(Rc::as_ref)
123    }
124
125    fn lb_ref(&self, offset: usize) -> Option<TokenRef> {
126        if offset == 0 || self.cursor == 0 {
127            return None;
128        }
129        let mut index = self.cursor;
130        let mut remaining = offset;
131        while remaining > 0 {
132            index = self.previous_token_on_channel(index, self.channel)?;
133            remaining -= 1;
134        }
135        self.tokens.get(index).map(Rc::clone)
136    }
137
138    pub const fn token_source(&self) -> &S {
139        &self.source
140    }
141
142    pub fn tokens(&self) -> &[CommonToken] {
143        &self.public_tokens
144    }
145
146    /// Ensures the buffer contains `index`, unless EOF has already been fetched.
147    fn sync(&mut self, index: usize) -> bool {
148        if index < self.tokens.len() {
149            return true;
150        }
151        let needed = index + 1 - self.tokens.len();
152        self.fetch(needed) >= needed
153    }
154
155    /// Fetches up to `count` more tokens, stopping early at EOF.
156    fn fetch(&mut self, count: usize) -> usize {
157        let mut fetched = 0;
158        while fetched < count && !self.fetched_eof {
159            self.fetch_one();
160            fetched += 1;
161        }
162        fetched
163    }
164
165    fn fetch_one(&mut self) {
166        let mut token = self.source.next_token();
167        self.source_errors.extend(self.source.drain_errors());
168        let token_index = isize::try_from(self.tokens.len()).unwrap_or(isize::MAX);
169        token.set_token_index(token_index);
170        self.fetched_eof = token.token_type() == TOKEN_EOF;
171        self.tokens.push(Rc::new(token.clone()));
172        self.public_tokens.push(token);
173        self.next_visible_after.push(UNKNOWN_NEXT_VISIBLE);
174    }
175
176    /// Moves a raw token index to the next token visible on this stream's
177    /// channel.
178    fn adjust_seek_index(&mut self, index: usize) -> usize {
179        self.next_token_on_channel(index, self.channel)
180    }
181
182    /// Finds the next buffered token on `channel`, fetching as needed.
183    fn next_token_on_channel(&mut self, mut index: usize, channel: i32) -> usize {
184        self.sync(index);
185        while let Some(token) = self.tokens.get(index) {
186            if token.token_type() == TOKEN_EOF || token.channel() == channel {
187                return index;
188            }
189            index += 1;
190            self.sync(index);
191        }
192        index
193    }
194
195    /// Finds the previous buffered token on `channel`.
196    fn previous_token_on_channel(&self, mut index: usize, channel: i32) -> Option<usize> {
197        while index > 0 {
198            index -= 1;
199            let token = self.tokens.get(index)?;
200            if token.token_type() == TOKEN_EOF || token.channel() == channel {
201                return Some(index);
202            }
203        }
204        None
205    }
206
207    /// Finds the previous buffered token visible to this stream before
208    /// `index`.
209    ///
210    /// Parser rule intervals and `$text` actions are defined in terms of
211    /// visible tokens, but their rendered source text still includes hidden
212    /// tokens between the visible start and stop. Returning the previous token
213    /// on the stream channel avoids accidentally using trailing hidden
214    /// whitespace as the stop token.
215    pub fn previous_visible_token_index(&mut self, index: usize) -> Option<usize> {
216        if index > 0 {
217            self.sync(index - 1);
218        }
219        self.previous_token_on_channel(index, self.channel)
220    }
221}
222
223impl<S> IntStream for CommonTokenStream<S>
224where
225    S: TokenSource,
226{
227    fn consume(&mut self) {
228        if self.la(1) == EOF {
229            return;
230        }
231        let current = self.next_token_on_channel(self.cursor, self.channel);
232        self.cursor = self.adjust_seek_index(current + 1);
233    }
234
235    fn la(&mut self, offset: isize) -> i32 {
236        self.la_token(offset)
237    }
238
239    fn index(&self) -> usize {
240        self.cursor
241    }
242
243    fn seek(&mut self, index: usize) {
244        self.cursor = self.adjust_seek_index(index);
245    }
246
247    fn size(&self) -> usize {
248        self.tokens.len()
249    }
250
251    fn source_name(&self) -> &str {
252        let source_name = self.source.source_name();
253        if source_name.is_empty() {
254            UNKNOWN_SOURCE_NAME
255        } else {
256            source_name
257        }
258    }
259}
260
261impl<S> CommonTokenStream<S>
262where
263    S: TokenSource,
264{
265    pub fn la_token(&mut self, offset: isize) -> i32 {
266        self.lt(offset).map_or(TOKEN_EOF, Token::token_type)
267    }
268
269    /// Returns the token type at a buffered absolute index, fetching from the
270    /// source on demand. Past-EOF reads are reported as `TOKEN_EOF` so the
271    /// caller does not need to special-case the buffer's stop. The cursor is
272    /// not modified, which lets hot speculative loops avoid the seek
273    /// round-trip when they only need lookahead types.
274    pub fn token_type_at_index(&mut self, index: usize) -> i32 {
275        self.sync(index);
276        self.tokens
277            .get(index)
278            .map_or(TOKEN_EOF, |token| token.token_type())
279    }
280
281    /// Returns the token channel visible to `LT/LA` operations.
282    pub const fn channel(&self) -> i32 {
283        self.channel
284    }
285
286    /// Returns the next parser-visible token index after consuming the token
287    /// at `index`, skipping hidden-channel tokens. The parser's stream cursor
288    /// is not modified. Used by speculative recognition that simulates token
289    /// consumption thousands of times without committing it.
290    pub fn next_visible_after(&mut self, index: usize) -> usize {
291        self.sync(index);
292        if let Some(cached) = self
293            .next_visible_after
294            .get(index)
295            .copied()
296            .filter(|cached| *cached != UNKNOWN_NEXT_VISIBLE)
297        {
298            return cached;
299        }
300
301        let mut next = index + 1;
302        let found = loop {
303            self.sync(next);
304            match self.tokens.get(next) {
305                Some(token)
306                    if token.token_type() != TOKEN_EOF && token.channel() != self.channel =>
307                {
308                    next += 1;
309                    continue;
310                }
311                _ => break next,
312            }
313        };
314        if let Some(slot) = self.next_visible_after.get_mut(index) {
315            *slot = found;
316        }
317        found
318    }
319
320    pub fn text(&mut self, start: usize, stop: usize) -> String {
321        self.sync(stop);
322        if start > stop || start >= self.tokens.len() {
323            return String::new();
324        }
325        // Java's `BufferedTokenStream.getText(Interval)` stops at the first
326        // EOF token, so an interval whose stop index lands on EOF renders
327        // without a trailing `<EOF>` (diagnostics rely on this).
328        self.tokens[start..=stop.min(self.tokens.len().saturating_sub(1))]
329            .iter()
330            .take_while(|token| token.token_type() != TOKEN_EOF)
331            .map(|token| token.text())
332            .collect::<Vec<_>>()
333            .join("")
334    }
335
336    /// Concatenated text of every buffered token except EOF — ANTLR's
337    /// `TokenStream.getText()`, the shape generated test actions read through
338    /// `self.input().text()`.
339    pub fn text_all(&mut self) -> String {
340        self.fill();
341        self.tokens
342            .iter()
343            .filter(|token| token.token_type() != TOKEN_EOF)
344            .map(|token| token.text())
345            .collect()
346    }
347
348    /// Returns and clears diagnostics emitted by the underlying token source
349    /// while this stream was fetching tokens.
350    pub fn drain_source_errors(&mut self) -> Vec<TokenSourceError> {
351        std::mem::take(&mut self.source_errors)
352    }
353
354    pub const fn is_filled(&self) -> bool {
355        self.fetched_eof
356    }
357}
358
359#[cfg(test)]
360mod tests {
361    use super::*;
362    use crate::token::{CommonToken, HIDDEN_CHANNEL};
363
364    #[derive(Debug)]
365    struct VecTokenSource {
366        tokens: Vec<CommonToken>,
367        index: usize,
368    }
369
370    impl TokenSource for VecTokenSource {
371        fn next_token(&mut self) -> CommonToken {
372            let token = self
373                .tokens
374                .get(self.index)
375                .cloned()
376                .unwrap_or_else(|| CommonToken::eof("vec", self.index, 1, self.index));
377            self.index += 1;
378            token
379        }
380
381        fn line(&self) -> usize {
382            1
383        }
384
385        fn column(&self) -> usize {
386            self.index
387        }
388
389        fn source_name(&self) -> &'static str {
390            "vec"
391        }
392    }
393
394    #[test]
395    fn stream_skips_hidden_channel_for_lookahead() {
396        let source = VecTokenSource {
397            tokens: vec![
398                CommonToken::new(1).with_text("a"),
399                CommonToken::new(2)
400                    .with_text(" ")
401                    .with_channel(HIDDEN_CHANNEL),
402                CommonToken::new(3).with_text("b"),
403                CommonToken::eof("vec", 3, 1, 3),
404            ],
405            index: 0,
406        };
407        let mut stream = CommonTokenStream::new(source);
408        assert_eq!(stream.la_token(1), 1);
409        stream.consume();
410        assert_eq!(stream.la_token(1), 3);
411        assert_eq!(
412            stream
413                .lt(-1)
414                .expect("look-behind token should be buffered")
415                .token_type(),
416            1
417        );
418    }
419
420    #[test]
421    fn lookahead_skips_hidden_token_at_initial_cursor() {
422        let source = VecTokenSource {
423            tokens: vec![
424                CommonToken::new(2)
425                    .with_text(" ")
426                    .with_channel(HIDDEN_CHANNEL),
427                CommonToken::new(1).with_text("a"),
428                CommonToken::eof("vec", 2, 1, 2),
429            ],
430            index: 0,
431        };
432        let mut stream = CommonTokenStream::new(source);
433
434        assert_eq!(stream.la_token(1), 1);
435        assert_eq!(stream.lt(1).and_then(Token::text), Some("a"));
436        stream.consume();
437        assert_eq!(stream.la_token(1), TOKEN_EOF);
438    }
439
440    #[test]
441    fn text_returns_empty_when_start_is_past_buffer() {
442        let source = VecTokenSource {
443            tokens: vec![
444                CommonToken::new(1).with_text("a"),
445                CommonToken::eof("vec", 1, 1, 1),
446            ],
447            index: 0,
448        };
449        let mut stream = CommonTokenStream::new(source);
450
451        assert_eq!(stream.text(10, 12), "");
452    }
453
454    #[test]
455    fn tokens_returns_public_slice() {
456        let source = VecTokenSource {
457            tokens: vec![
458                CommonToken::new(1).with_text("a"),
459                CommonToken::new(2).with_text("b"),
460                CommonToken::eof("vec", 2, 1, 2),
461            ],
462            index: 0,
463        };
464        let mut stream = CommonTokenStream::new(source);
465        stream.fill();
466
467        fn token_count(tokens: &[CommonToken]) -> usize {
468            tokens.len()
469        }
470
471        let tokens = stream.tokens();
472        assert_eq!(token_count(tokens), 3);
473        assert_eq!(tokens[0].token_type(), 1);
474        assert_eq!(tokens.first().map(Token::token_type), Some(1));
475        assert_eq!(
476            tokens.iter().next_back().map(Token::token_type),
477            Some(TOKEN_EOF)
478        );
479    }
480}