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