Skip to main content

antlr4_runtime/
token_stream.rs

1// SPDX-License-Identifier: BSD-3-Clause
2// Copyright (c) 2026 Konstantin Vyatkin
3use crate::int_stream::{EOF, IntStream, UNKNOWN_SOURCE_NAME};
4use std::cell::Cell;
5
6pub use crate::token::TokenIter;
7use crate::token::{
8    DEFAULT_CHANNEL, TOKEN_EOF, Token, TokenId, TokenSink, TokenSource, TokenSourceError,
9    TokenSpec, TokenStore, TokenStoreError, TokenView,
10};
11
12#[derive(Debug)]
13struct BufferedSourceError {
14    token_index: usize,
15    error: TokenSourceError,
16}
17
18#[derive(Debug)]
19pub struct CommonTokenStream<S> {
20    source: S,
21    store: TokenStore,
22    source_token_count: usize,
23    source_error_count: usize,
24    next_visible_after: Vec<usize>,
25    cursor: usize,
26    channel: i32,
27    requested_token_count: Cell<usize>,
28    source_errors: Vec<BufferedSourceError>,
29}
30
31const UNKNOWN_NEXT_VISIBLE: usize = usize::MAX;
32
33fn buffer_token_source<S>(
34    source: &mut S,
35) -> Result<(TokenStore, Vec<BufferedSourceError>), TokenStoreError>
36where
37    S: TokenSource,
38{
39    let source_name = source.source_name().to_owned();
40    let mut store = TokenStore::new(source.source_text(), source_name);
41    let mut source_errors = Vec::new();
42    loop {
43        let expected_id = store.len();
44        let mut sink = TokenSink::new(&mut store);
45        let id = source.next_token(&mut sink)?;
46        let appended = sink.token_count().saturating_sub(expected_id);
47        if appended != 1 || id.index() != expected_id {
48            return Err(TokenStoreError::invalid_source_output(
49                expected_id,
50                id.index(),
51                appended,
52            ));
53        }
54        source_errors.extend(
55            source
56                .drain_errors()
57                .into_iter()
58                .map(|error| BufferedSourceError {
59                    token_index: id.index(),
60                    error,
61                }),
62        );
63        let token = sink
64            .view(id)
65            .expect("token source returned an ID it did not emit");
66        if token.token_type() == TOKEN_EOF {
67            break;
68        }
69    }
70    Ok((store, source_errors))
71}
72
73impl<S> CommonTokenStream<S>
74where
75    S: TokenSource,
76{
77    /// Creates and fills a token stream that filters lookahead to the default
78    /// channel.
79    ///
80    /// Use [`Self::try_new`] when token/source limit errors should be handled
81    /// instead of reported as a construction panic.
82    pub fn new(source: S) -> Self {
83        Self::try_new(source).unwrap_or_else(|error| panic!("failed to buffer tokens: {error}"))
84    }
85
86    pub fn try_new(source: S) -> Result<Self, TokenStoreError> {
87        Self::try_with_channel(source, DEFAULT_CHANNEL)
88    }
89
90    /// Creates and fills a token stream whose `LT/LA` operations see only
91    /// `channel`.
92    pub fn with_channel(source: S, channel: i32) -> Self {
93        Self::try_with_channel(source, channel)
94            .unwrap_or_else(|error| panic!("failed to buffer tokens: {error}"))
95    }
96
97    pub fn try_with_channel(mut source: S, channel: i32) -> Result<Self, TokenStoreError> {
98        let (store, source_errors) = buffer_token_source(&mut source)?;
99        let source_token_count = store.len();
100        let source_error_count = source_errors.len();
101        let mut stream = Self {
102            source,
103            store,
104            source_token_count,
105            source_error_count,
106            next_visible_after: vec![UNKNOWN_NEXT_VISIBLE; source_token_count],
107            cursor: 0,
108            channel,
109            requested_token_count: Cell::new(0),
110            source_errors,
111        };
112        stream.cursor = stream.adjust_seek_index(0);
113        stream.requested_token_count.set(0);
114        Ok(stream)
115    }
116
117    /// Replaces the token source and eagerly buffers it through EOF.
118    ///
119    /// The configured channel is retained; cursor, token storage, requested
120    /// lookahead, and buffered source errors are reset.
121    pub fn set_token_source(&mut self, source: S) {
122        self.try_set_token_source(source)
123            .unwrap_or_else(|error| panic!("failed to buffer tokens: {error}"));
124    }
125
126    /// Fallible form of [`Self::set_token_source`].
127    pub fn try_set_token_source(&mut self, source: S) -> Result<(), TokenStoreError> {
128        let replacement = Self::try_with_channel(source, self.channel)?;
129        *self = replacement;
130        Ok(())
131    }
132
133    /// Rebuffers the current token source after it has been reset or re-fed.
134    ///
135    /// This supports fully owned recognizer stacks: mutate the nested source
136    /// through [`Self::token_source_mut`], then call `refill` without moving the
137    /// lexer out of the stream.
138    pub fn refill(&mut self) {
139        self.try_refill()
140            .unwrap_or_else(|error| panic!("failed to buffer tokens: {error}"));
141    }
142
143    /// Fallible form of [`Self::refill`].
144    pub fn try_refill(&mut self) -> Result<(), TokenStoreError> {
145        let (store, source_errors) = buffer_token_source(&mut self.source)?;
146        self.store = store;
147        self.source_token_count = self.store.len();
148        self.source_error_count = source_errors.len();
149        self.next_visible_after = vec![UNKNOWN_NEXT_VISIBLE; self.source_token_count];
150        self.cursor = self.adjust_seek_index(0);
151        self.requested_token_count.set(0);
152        self.source_errors = source_errors;
153        Ok(())
154    }
155
156    /// Idempotent eager-buffering operation. Construction already buffers
157    /// through EOF so the store can be shared with CST nodes.
158    pub fn fill(&mut self) {
159        self.note_requested_count(self.source_token_count);
160        self.cursor = self.adjust_seek_index(self.cursor);
161    }
162
163    /// Returns a borrowing view of the token at an absolute buffered index.
164    pub fn get(&self, index: usize) -> Option<TokenView<'_>> {
165        self.get_id(index).and_then(|id| self.store.view(id))
166    }
167
168    /// Returns the compact ID at an absolute buffered index.
169    pub fn get_id(&self, index: usize) -> Option<TokenId> {
170        self.note_requested_count(index.saturating_add(1));
171        (index < self.source_token_count)
172            .then(|| TokenId::try_from(index).ok())
173            .flatten()
174    }
175
176    /// Returns the token at one-based lookahead/lookbehind offset, skipping
177    /// tokens outside the configured channel for positive offsets.
178    pub fn lt(&self, offset: isize) -> Option<TokenView<'_>> {
179        self.lt_id(offset).and_then(|id| self.store.view(id))
180    }
181
182    /// Returns the compact token ID at one-based lookahead/lookbehind offset.
183    pub fn lt_id(&self, offset: isize) -> Option<TokenId> {
184        if offset == 0 {
185            return None;
186        }
187        if offset < 0 {
188            return offset
189                .checked_neg()
190                .map(isize::cast_unsigned)
191                .and_then(|offset| self.lb_id(offset));
192        }
193
194        let mut index = self.next_token_on_channel(self.cursor, self.channel);
195        let mut remaining = offset;
196        while remaining > 1 {
197            index = self.next_token_on_channel(index + 1, self.channel);
198            remaining -= 1;
199        }
200        self.get_id(index)
201    }
202
203    pub fn lb(&self, offset: usize) -> Option<TokenView<'_>> {
204        self.lb_id(offset).and_then(|id| self.store.view(id))
205    }
206
207    fn lb_id(&self, offset: usize) -> Option<TokenId> {
208        if offset == 0 || self.cursor == 0 {
209            return None;
210        }
211        let mut index = self.cursor;
212        let mut remaining = offset;
213        while remaining > 0 {
214            index = self.previous_token_on_channel(index, self.channel)?;
215            remaining -= 1;
216        }
217        self.get_id(index)
218    }
219
220    pub const fn token_source(&self) -> &S {
221        &self.source
222    }
223
224    /// Returns the current source for in-place lexer re-feeding.
225    pub const fn token_source_mut(&mut self) -> &mut S {
226        &mut self.source
227    }
228
229    /// Iterates borrowing views of the original buffered token sequence.
230    pub fn tokens(&self) -> TokenIter<'_> {
231        self.note_requested_count(self.source_token_count);
232        self.store.iter_prefix(self.source_token_count)
233    }
234
235    pub const fn token_count(&self) -> usize {
236        self.source_token_count
237    }
238
239    /// Returns the total number of diagnostics emitted while buffering the
240    /// current token source, including diagnostics already delivered through
241    /// [`Self::drain_source_errors`].
242    pub const fn number_of_source_errors(&self) -> usize {
243        self.source_error_count
244    }
245
246    /// Returns the canonical token store owned by this stream.
247    #[must_use]
248    pub const fn token_store(&self) -> &TokenStore {
249        &self.store
250    }
251
252    /// Consumes the stream and returns its canonical token store.
253    #[must_use]
254    pub fn into_token_store(self) -> TokenStore {
255        self.store
256    }
257
258    pub(crate) fn token_view(&self, id: TokenId) -> Option<TokenView<'_>> {
259        self.store.view(id)
260    }
261
262    pub(crate) fn insert(&mut self, spec: TokenSpec) -> Result<TokenId, TokenStoreError> {
263        self.store.push(spec)
264    }
265
266    fn note_requested_count(&self, count: usize) {
267        self.requested_token_count.set(
268            self.requested_token_count
269                .get()
270                .max(count.min(self.source_token_count)),
271        );
272    }
273
274    /// Moves a raw token index to the next token visible on this stream's
275    /// channel.
276    fn adjust_seek_index(&self, index: usize) -> usize {
277        self.next_token_on_channel(index, self.channel)
278    }
279
280    /// Finds the next buffered token on `channel`.
281    fn next_token_on_channel(&self, mut index: usize, channel: i32) -> usize {
282        while let Some(id) = self.get_id(index) {
283            if self.store.token_type(id) == Some(TOKEN_EOF)
284                || self.store.channel(id) == Some(channel)
285            {
286                return index;
287            }
288            index += 1;
289        }
290        index
291    }
292
293    /// Finds the previous buffered token on `channel`.
294    fn previous_token_on_channel(&self, mut index: usize, channel: i32) -> Option<usize> {
295        while index > 0 {
296            index -= 1;
297            let id = self.get_id(index)?;
298            if self.store.token_type(id) == Some(TOKEN_EOF)
299                || self.store.channel(id) == Some(channel)
300            {
301                return Some(index);
302            }
303        }
304        None
305    }
306
307    /// Finds the previous buffered token visible to this stream before
308    /// `index`.
309    pub fn previous_visible_token_index(&self, index: usize) -> Option<usize> {
310        self.previous_token_on_channel(index, self.channel)
311    }
312}
313
314impl<S> IntStream for CommonTokenStream<S>
315where
316    S: TokenSource,
317{
318    fn consume(&mut self) {
319        if self.la(1) == EOF {
320            return;
321        }
322        let current = self.next_token_on_channel(self.cursor, self.channel);
323        self.cursor = self.adjust_seek_index(current + 1);
324    }
325
326    fn la(&mut self, offset: isize) -> i32 {
327        self.la_token(offset)
328    }
329
330    fn index(&self) -> usize {
331        self.cursor
332    }
333
334    fn seek(&mut self, index: usize) {
335        self.cursor = self.adjust_seek_index(index);
336    }
337
338    fn size(&self) -> usize {
339        self.source_token_count
340    }
341
342    fn source_name(&self) -> &str {
343        let source_name = self.source.source_name();
344        if source_name.is_empty() {
345            UNKNOWN_SOURCE_NAME
346        } else {
347            source_name
348        }
349    }
350}
351
352impl<S> CommonTokenStream<S>
353where
354    S: TokenSource,
355{
356    pub fn la_token(&self, offset: isize) -> i32 {
357        self.lt_id(offset)
358            .and_then(|id| self.store.token_type(id))
359            .unwrap_or(TOKEN_EOF)
360    }
361
362    /// Returns the token type at a buffered absolute index. Past-EOF reads are
363    /// reported as `TOKEN_EOF`.
364    pub fn token_type_at_index(&self, index: usize) -> i32 {
365        self.get_id(index)
366            .and_then(|id| self.store.token_type(id))
367            .unwrap_or(TOKEN_EOF)
368    }
369
370    /// Returns the token channel visible to `LT/LA` operations.
371    pub const fn channel(&self) -> i32 {
372        self.channel
373    }
374
375    /// Returns the next parser-visible token index after consuming the token
376    /// at `index`, skipping hidden-channel tokens.
377    pub fn next_visible_after(&mut self, index: usize) -> usize {
378        if let Some(cached) = self
379            .next_visible_after
380            .get(index)
381            .copied()
382            .filter(|cached| *cached != UNKNOWN_NEXT_VISIBLE)
383        {
384            return cached;
385        }
386
387        let mut next = index + 1;
388        let found = loop {
389            match self.get_id(next) {
390                Some(id)
391                    if self.store.token_type(id) != Some(TOKEN_EOF)
392                        && self.store.channel(id) != Some(self.channel) =>
393                {
394                    next += 1;
395                    continue;
396                }
397                _ => break next,
398            }
399        };
400        if let Some(slot) = self.next_visible_after.get_mut(index) {
401            *slot = found;
402        }
403        found
404    }
405
406    pub fn text(&self, start: usize, stop: usize) -> String {
407        if start > stop || start >= self.source_token_count {
408            return String::new();
409        }
410        (start..=stop.min(self.source_token_count.saturating_sub(1)))
411            .filter_map(|index| self.get(index))
412            .take_while(|token| token.token_type() != TOKEN_EOF)
413            .map(|token| token.text_or_empty())
414            .collect()
415    }
416
417    /// Concatenated text of every buffered token except EOF.
418    pub fn text_all(&self) -> String {
419        self.tokens()
420            .filter(|token| token.token_type() != TOKEN_EOF)
421            .map(|token| token.text_or_empty())
422            .collect()
423    }
424
425    /// Returns and clears diagnostics emitted while producing requested tokens.
426    pub fn drain_source_errors(&mut self) -> Vec<TokenSourceError> {
427        let requested = self.requested_token_count.get();
428        let ready = self
429            .source_errors
430            .partition_point(|buffered| buffered.token_index < requested);
431        self.source_errors
432            .drain(..ready)
433            .map(|buffered| buffered.error)
434            .collect()
435    }
436
437    pub const fn is_filled(&self) -> bool {
438        true
439    }
440}
441
442#[cfg(test)]
443mod tests {
444    use super::*;
445    use crate::token::HIDDEN_CHANNEL;
446    use std::collections::VecDeque;
447
448    #[derive(Debug)]
449    struct VecTokenSource {
450        tokens: VecDeque<TokenSpec>,
451        index: usize,
452    }
453
454    impl TokenSource for VecTokenSource {
455        fn next_token(&mut self, sink: &mut TokenSink<'_>) -> Result<TokenId, TokenStoreError> {
456            let spec = self
457                .tokens
458                .pop_front()
459                .unwrap_or_else(|| TokenSpec::eof(self.index, self.index, 1, self.index));
460            self.index += 1;
461            sink.push(spec)
462        }
463
464        fn line(&self) -> usize {
465            1
466        }
467
468        fn column(&self) -> usize {
469            self.index
470        }
471
472        fn source_name(&self) -> &'static str {
473            "vec"
474        }
475    }
476
477    #[derive(Debug)]
478    struct ErrorTokenSource {
479        tokens: VecDeque<(TokenSpec, Vec<TokenSourceError>)>,
480        pending_errors: Vec<TokenSourceError>,
481        index: usize,
482    }
483
484    impl TokenSource for ErrorTokenSource {
485        fn next_token(&mut self, sink: &mut TokenSink<'_>) -> Result<TokenId, TokenStoreError> {
486            let (spec, errors) = self.tokens.pop_front().unwrap_or_else(|| {
487                (
488                    TokenSpec::eof(self.index, self.index, 1, self.index),
489                    Vec::new(),
490                )
491            });
492            self.index += 1;
493            self.pending_errors = errors;
494            sink.push(spec)
495        }
496
497        fn line(&self) -> usize {
498            1
499        }
500
501        fn column(&self) -> usize {
502            self.index
503        }
504
505        fn source_name(&self) -> &'static str {
506            "errors"
507        }
508
509        fn drain_errors(&mut self) -> Vec<TokenSourceError> {
510            std::mem::take(&mut self.pending_errors)
511        }
512    }
513
514    #[derive(Debug, Default)]
515    struct StaleIdTokenSource {
516        previous: Option<TokenId>,
517    }
518
519    impl TokenSource for StaleIdTokenSource {
520        fn next_token(&mut self, sink: &mut TokenSink<'_>) -> Result<TokenId, TokenStoreError> {
521            let emitted = sink.push(TokenSpec::explicit(1, "x"))?;
522            Ok(self.previous.replace(emitted).unwrap_or(emitted))
523        }
524
525        fn line(&self) -> usize {
526            1
527        }
528
529        fn column(&self) -> usize {
530            0
531        }
532
533        fn source_name(&self) -> &'static str {
534            "stale-id"
535        }
536    }
537
538    fn source(tokens: Vec<TokenSpec>) -> VecTokenSource {
539        VecTokenSource {
540            tokens: tokens.into(),
541            index: 0,
542        }
543    }
544
545    #[test]
546    fn stream_skips_hidden_channel_for_lookahead() {
547        let mut stream = CommonTokenStream::new(source(vec![
548            TokenSpec::explicit(1, "a"),
549            TokenSpec::explicit(2, " ").with_channel(HIDDEN_CHANNEL),
550            TokenSpec::explicit(3, "b"),
551            TokenSpec::eof(3, 3, 1, 3),
552        ]));
553        assert_eq!(stream.la_token(1), 1);
554        stream.consume();
555        assert_eq!(stream.la_token(1), 3);
556        assert_eq!(
557            stream
558                .lt(-1)
559                .expect("look-behind token should be buffered")
560                .token_type(),
561            1
562        );
563    }
564
565    #[test]
566    fn text_returns_empty_when_start_is_past_buffer() {
567        let stream = CommonTokenStream::new(source(vec![
568            TokenSpec::explicit(1, "a"),
569            TokenSpec::eof(1, 1, 1, 1),
570        ]));
571        assert_eq!(stream.text(10, 12), "");
572    }
573
574    #[test]
575    fn text_concatenates_borrowed_token_text() {
576        let stream = CommonTokenStream::new(source(vec![
577            TokenSpec::explicit(1, "a"),
578            TokenSpec::explicit(2, "b"),
579            TokenSpec::eof(2, 2, 1, 2),
580        ]));
581        assert_eq!(stream.text(0, 1), "ab");
582        assert_eq!(stream.text_all(), "ab");
583    }
584
585    #[test]
586    fn construction_rejects_stale_non_eof_token_id() {
587        let error = CommonTokenStream::try_new(StaleIdTokenSource::default())
588            .expect_err("a stale token ID must terminate buffering with an error");
589
590        assert!(error.to_string().contains("return ID 1"));
591        assert!(error.to_string().contains("returned ID 0"));
592    }
593
594    #[test]
595    fn source_errors_remain_hidden_until_their_token_is_requested() {
596        let suffix_error = TokenSourceError::new(1, 4, "token recognition error at: '@'");
597        let mut stream = CommonTokenStream::new(ErrorTokenSource {
598            tokens: [
599                (TokenSpec::explicit(1, "x"), Vec::new()),
600                (TokenSpec::explicit(2, "y"), Vec::new()),
601                (TokenSpec::eof(3, 3, 1, 3), vec![suffix_error.clone()]),
602            ]
603            .into(),
604            pending_errors: Vec::new(),
605            index: 0,
606        });
607
608        assert_eq!(stream.number_of_source_errors(), 1);
609        assert!(stream.drain_source_errors().is_empty());
610        assert_eq!(stream.token_type_at_index(1), 2);
611        assert!(stream.drain_source_errors().is_empty());
612
613        assert_eq!(stream.token_type_at_index(2), TOKEN_EOF);
614        assert_eq!(stream.drain_source_errors(), vec![suffix_error]);
615        assert_eq!(stream.number_of_source_errors(), 1);
616
617        stream.refill();
618        assert_eq!(stream.number_of_source_errors(), 0);
619    }
620
621    #[test]
622    fn tokens_returns_borrowing_views() {
623        let stream = CommonTokenStream::new(source(vec![
624            TokenSpec::explicit(1, "a"),
625            TokenSpec::explicit(2, "b"),
626            TokenSpec::eof(2, 2, 1, 2),
627        ]));
628        assert_eq!(stream.tokens().len(), 3);
629        assert_eq!(
630            stream.tokens().next().map(|token| token.token_type()),
631            Some(1)
632        );
633        assert_eq!(
634            stream.tokens().next_back().map(|token| token.token_type()),
635            Some(TOKEN_EOF)
636        );
637    }
638
639    #[test]
640    fn stream_tokens_exclude_parser_insertions_but_store_iterates_them() {
641        let mut stream = CommonTokenStream::new(source(vec![
642            TokenSpec::explicit(1, "a"),
643            TokenSpec::eof(1, 1, 1, 1),
644        ]));
645        stream
646            .insert(TokenSpec::explicit(2, "<missing token>"))
647            .expect("synthetic token should fit");
648
649        assert_eq!(stream.tokens().len(), 2);
650        assert_eq!(stream.token_store().iter().len(), 3);
651        assert_eq!(
652            stream
653                .token_store()
654                .iter()
655                .next_back()
656                .and_then(|token| token.text()),
657            Some("<missing token>")
658        );
659    }
660
661    #[test]
662    fn set_token_source_replaces_buffer_and_preserves_channel() {
663        let mut stream = CommonTokenStream::with_channel(
664            source(vec![
665                TokenSpec::explicit(1, "old").with_channel(2),
666                TokenSpec::eof(3, 3, 1, 3),
667            ]),
668            2,
669        );
670
671        stream.set_token_source(source(vec![
672            TokenSpec::explicit(2, "new").with_channel(2),
673            TokenSpec::eof(3, 3, 1, 3),
674        ]));
675
676        assert_eq!(stream.channel(), 2);
677        assert_eq!(stream.index(), 0);
678        assert_eq!(stream.number_of_source_errors(), 0);
679        assert_eq!(stream.la_token(1), 2);
680        assert_eq!(stream.text_all(), "new");
681    }
682
683    #[test]
684    fn refill_reuses_mutated_token_source_in_place() {
685        let mut stream = CommonTokenStream::new(source(vec![
686            TokenSpec::explicit(1, "old"),
687            TokenSpec::eof(3, 3, 1, 3),
688        ]));
689        let source = stream.token_source_mut();
690        source.tokens = vec![TokenSpec::explicit(2, "new"), TokenSpec::eof(3, 3, 1, 3)].into();
691        source.index = 0;
692
693        stream.refill();
694
695        assert_eq!(stream.index(), 0);
696        assert_eq!(stream.number_of_source_errors(), 0);
697        assert_eq!(stream.la_token(1), 2);
698        assert_eq!(stream.text_all(), "new");
699    }
700}