Skip to main content

antlr4_runtime/
token_stream.rs

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