1use std::cell::RefCell;
2use std::collections::{BTreeSet, HashMap};
3use std::hash::BuildHasherDefault;
4use std::rc::Rc;
5
6use crate::atn::Atn;
7use crate::char_stream::{CharStream, TextInterval};
8use crate::int_stream::EOF;
9use crate::prediction::PredictionFxHasher;
10use crate::recognizer::{Recognizer, RecognizerData};
11use crate::token::{CommonToken, CommonTokenFactory, TokenFactory, TokenSourceError, TokenSpec};
12
13#[allow(clippy::disallowed_types)]
14type FxHashMap<K, V> = HashMap<K, V, BuildHasherDefault<PredictionFxHasher>>;
15
16pub const SKIP: i32 = -3;
17pub const MORE: i32 = -2;
18pub const DEFAULT_MODE: i32 = 0;
19
20#[derive(Clone, Copy, Debug, Eq, PartialEq)]
21pub struct LexerMode(pub i32);
22
23#[derive(Clone, Copy, Debug, Eq, PartialEq)]
30pub struct LexerCustomAction {
31 rule_index: i32,
32 action_index: i32,
33 position: usize,
34}
35
36impl LexerCustomAction {
37 pub const fn new(rule_index: i32, action_index: i32, position: usize) -> Self {
39 Self {
40 rule_index,
41 action_index,
42 position,
43 }
44 }
45
46 pub const fn rule_index(self) -> i32 {
48 self.rule_index
49 }
50
51 pub const fn action_index(self) -> i32 {
53 self.action_index
54 }
55
56 pub const fn position(self) -> usize {
58 self.position
59 }
60}
61
62#[derive(Clone, Copy, Debug, Eq, PartialEq)]
64pub struct LexerPredicate {
65 rule_index: usize,
66 pred_index: usize,
67 position: usize,
68}
69
70impl LexerPredicate {
71 pub const fn new(rule_index: usize, pred_index: usize, position: usize) -> Self {
73 Self {
74 rule_index,
75 pred_index,
76 position,
77 }
78 }
79
80 pub const fn rule_index(self) -> usize {
82 self.rule_index
83 }
84
85 pub const fn pred_index(self) -> usize {
87 self.pred_index
88 }
89
90 pub const fn position(self) -> usize {
92 self.position
93 }
94}
95
96#[derive(Debug)]
101enum LexerRef<'a, I, F>
102where
103 I: CharStream,
104 F: TokenFactory,
105{
106 Shared(&'a BaseLexer<I, F>),
107 Mut(&'a mut BaseLexer<I, F>),
108}
109
110impl<I, F> LexerRef<'_, I, F>
111where
112 I: CharStream,
113 F: TokenFactory,
114{
115 const fn get(&self) -> &BaseLexer<I, F> {
116 match self {
117 LexerRef::Shared(lexer) => lexer,
118 LexerRef::Mut(lexer) => lexer,
119 }
120 }
121}
122
123#[derive(Debug)]
125pub struct LexerSemCtx<'a, I, F = CommonTokenFactory>
126where
127 I: CharStream,
128 F: TokenFactory,
129{
130 lexer: LexerRef<'a, I, F>,
131 rule_index: usize,
132 coordinate_index: usize,
133 position: usize,
134}
135
136impl<'a, I, F> LexerSemCtx<'a, I, F>
137where
138 I: CharStream,
139 F: TokenFactory,
140{
141 pub(crate) const fn new(
142 lexer: &'a BaseLexer<I, F>,
143 rule_index: usize,
144 coordinate_index: usize,
145 position: usize,
146 ) -> Self {
147 Self {
148 lexer: LexerRef::Shared(lexer),
149 rule_index,
150 coordinate_index,
151 position,
152 }
153 }
154
155 pub(crate) const fn new_mut(
158 lexer: &'a mut BaseLexer<I, F>,
159 rule_index: usize,
160 coordinate_index: usize,
161 position: usize,
162 ) -> Self {
163 Self {
164 lexer: LexerRef::Mut(lexer),
165 rule_index,
166 coordinate_index,
167 position,
168 }
169 }
170
171 #[must_use]
173 pub const fn rule_index(&self) -> usize {
174 self.rule_index
175 }
176
177 #[must_use]
179 pub const fn coordinate_index(&self) -> usize {
180 self.coordinate_index
181 }
182
183 #[must_use]
185 pub const fn position(&self) -> usize {
186 self.position
187 }
188
189 #[must_use]
191 pub fn mode(&self) -> i32 {
192 self.lexer.get().mode()
193 }
194
195 #[must_use]
197 pub const fn column(&self) -> usize {
198 self.lexer.get().column()
199 }
200
201 #[must_use]
203 pub fn position_column(&self) -> usize {
204 self.lexer.get().column_at(self.position)
205 }
206
207 #[must_use]
209 pub const fn token_start_column(&self) -> usize {
210 self.lexer.get().token_start_column()
211 }
212
213 #[must_use]
215 pub fn text_so_far(&self) -> String {
216 self.lexer.get().token_text_until(self.position)
217 }
218
219 pub fn set_mode(&mut self, mode: i32) -> bool {
226 match &mut self.lexer {
227 LexerRef::Mut(lexer) => {
228 lexer.set_mode(mode);
229 true
230 }
231 LexerRef::Shared(_) => false,
232 }
233 }
234
235 pub fn push_mode(&mut self, mode: i32) -> bool {
238 match &mut self.lexer {
239 LexerRef::Mut(lexer) => {
240 lexer.push_mode(mode);
241 true
242 }
243 LexerRef::Shared(_) => false,
244 }
245 }
246
247 pub fn pop_mode(&mut self) -> Option<i32> {
251 match &mut self.lexer {
252 LexerRef::Mut(lexer) => lexer.pop_mode(),
253 LexerRef::Shared(_) => None,
254 }
255 }
256}
257
258pub trait Lexer: Recognizer {
259 fn mode(&self) -> i32;
260 fn set_mode(&mut self, mode: i32);
261 fn push_mode(&mut self, mode: i32);
262 fn pop_mode(&mut self) -> Option<i32>;
263}
264
265#[derive(Clone, Debug)]
266pub struct BaseLexer<I, F = CommonTokenFactory> {
267 input: I,
268 data: RecognizerData,
269 factory: F,
270 mode: i32,
271 mode_stack: Vec<i32>,
272 token_start: usize,
273 token_start_line: usize,
274 token_start_column: usize,
275 line: usize,
276 column: usize,
277 hit_eof: bool,
278 force_interpreted: bool,
279 errors: Vec<TokenSourceError>,
280 dfa_cache: Rc<RefCell<LexerDfaCache>>,
281}
282
283#[derive(Clone, Debug, Default)]
291struct LexerDfaCache {
292 state_numbers: FxHashMap<LexerDfaKey, usize>,
293 accept_predictions: FxHashMap<usize, i32>,
294 edges: BTreeSet<LexerDfaEdge>,
298 cached_states: Vec<Option<Rc<LexerDfaCachedState>>>,
300 dense_edges: Vec<Option<Box<DenseEdgeRow>>>,
305 sparse_edges: FxHashMap<(usize, i32), LexerDfaCachedTransition>,
307 mode_starts: FxHashMap<i32, usize>,
308}
309
310const DENSE_EDGE_SYMBOLS: usize = 128;
312
313type DenseEdgeRow = [LexerDfaCachedTransition; DENSE_EDGE_SYMBOLS];
314
315const EMPTY_DENSE_EDGE: LexerDfaCachedTransition = LexerDfaCachedTransition {
318 target_state: usize::MAX,
319 position_delta: 0,
320};
321
322thread_local! {
323 static SHARED_LEXER_DFA_CACHES: RefCell<HashMap<usize, Rc<RefCell<LexerDfaCache>>>> =
326 RefCell::new(HashMap::new());
327}
328
329#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
331pub(crate) struct LexerDfaKey {
332 configs: Vec<LexerDfaConfigKey>,
333}
334
335impl LexerDfaKey {
336 pub(crate) fn new(mut configs: Vec<LexerDfaConfigKey>) -> Self {
337 configs.sort_unstable();
338 Self { configs }
339 }
340}
341
342#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
344pub(crate) struct LexerDfaConfigKey {
345 pub(crate) state: usize,
346 pub(crate) alt_rule_index: Option<usize>,
347 pub(crate) consumed_eof: bool,
348 pub(crate) passed_non_greedy: bool,
349 pub(crate) stack: Vec<usize>,
350 pub(crate) actions: Vec<LexerDfaActionKey>,
351}
352
353#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
354pub(crate) struct LexerDfaActionKey {
355 pub(crate) action_index: usize,
356 pub(crate) position_delta: usize,
357 pub(crate) rule_index: usize,
358}
359
360impl LexerDfaConfigKey {
361 pub(crate) const fn new(
362 state: usize,
363 alt_rule_index: Option<usize>,
364 consumed_eof: bool,
365 passed_non_greedy: bool,
366 stack: Vec<usize>,
367 actions: Vec<LexerDfaActionKey>,
368 ) -> Self {
369 Self {
370 state,
371 alt_rule_index,
372 consumed_eof,
373 passed_non_greedy,
374 stack,
375 actions,
376 }
377 }
378}
379
380#[derive(Clone, Copy, Debug)]
381pub(crate) struct LexerDfaCachedTransition {
382 pub(crate) target_state: usize,
383 pub(crate) position_delta: usize,
384}
385
386#[derive(Clone, Debug)]
387pub(crate) struct LexerDfaCachedAccept {
388 pub(crate) position_delta: usize,
389 pub(crate) rule_index: usize,
390 pub(crate) consumed_eof: bool,
391 pub(crate) actions: Vec<LexerDfaActionKey>,
392}
393
394#[derive(Clone, Debug)]
395pub(crate) struct LexerDfaCachedState {
396 pub(crate) has_semantic_context: bool,
397 pub(crate) configs: Vec<LexerDfaConfigKey>,
398 pub(crate) accept: Option<LexerDfaCachedAccept>,
399}
400
401#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
404struct LexerDfaEdge {
405 from: usize,
406 symbol: i32,
407 to: usize,
408}
409
410impl<I> BaseLexer<I>
411where
412 I: CharStream,
413{
414 pub fn new(input: I, data: RecognizerData) -> Self {
416 Self::with_factory(input, data, CommonTokenFactory)
417 }
418}
419
420impl<I, F> BaseLexer<I, F>
421where
422 I: CharStream,
423 F: TokenFactory,
424{
425 pub fn with_factory(input: I, data: RecognizerData, factory: F) -> Self {
427 Self {
428 input,
429 data,
430 factory,
431 mode: DEFAULT_MODE,
432 mode_stack: Vec::new(),
433 token_start: 0,
434 token_start_line: 1,
435 token_start_column: 0,
436 line: 1,
437 column: 0,
438 hit_eof: false,
439 force_interpreted: false,
440 errors: Vec::new(),
441 dfa_cache: Rc::new(RefCell::new(LexerDfaCache::default())),
442 }
443 }
444
445 #[must_use]
455 pub fn with_shared_dfa(mut self, atn: &'static Atn) -> Self {
456 let ptr: *const Atn = atn;
457 let key = ptr as usize;
458 self.dfa_cache = SHARED_LEXER_DFA_CACHES
459 .with(|caches| Rc::clone(caches.borrow_mut().entry(key).or_insert_with(Rc::default)));
460 self
461 }
462
463 pub const fn input(&self) -> &I {
464 &self.input
465 }
466
467 pub const fn input_mut(&mut self) -> &mut I {
468 &mut self.input
469 }
470
471 pub fn begin_token(&mut self) {
474 self.token_start = self.input.index();
475 self.token_start_line = self.line;
476 self.token_start_column = self.column;
477 }
478
479 pub const fn token_start(&self) -> usize {
481 self.token_start
482 }
483
484 pub const fn token_start_line(&self) -> usize {
486 self.token_start_line
487 }
488
489 pub const fn token_start_column(&self) -> usize {
491 self.token_start_column
492 }
493
494 pub fn consume_char(&mut self) {
501 let la = self.input.la(1);
502 if la == EOF {
503 return;
504 }
505 self.input.consume();
506 if char::from_u32(la.cast_unsigned()) == Some('\n') {
507 self.line += 1;
508 self.column = 0;
509 } else {
510 self.column += 1;
511 }
512 }
513
514 pub fn reset_accept_position(&mut self, index: usize) {
521 let target = index.max(self.token_start);
522 self.input.seek(self.token_start);
523 self.line = self.token_start_line;
524 self.column = self.token_start_column;
525 while self.input.index() < target && self.input.la(1) != EOF {
526 self.consume_char();
527 }
528 }
529
530 pub fn emit(&self, token_type: i32, channel: i32, text: Option<String>) -> CommonToken {
538 let stop = self.input.index().checked_sub(1).unwrap_or(usize::MAX);
539 self.emit_with_stop(token_type, channel, stop, text)
540 }
541
542 pub fn emit_with_stop(
548 &self,
549 token_type: i32,
550 channel: i32,
551 stop: usize,
552 text: Option<String>,
553 ) -> CommonToken {
554 let text = text.or_else(|| {
555 if stop == usize::MAX {
556 Some("<EOF>".to_owned())
557 } else {
558 None
559 }
560 });
561 let source_interval = if text.is_none() && stop != usize::MAX && self.token_start <= stop {
562 self.input
563 .text_source_interval(TextInterval::new(self.token_start, stop))
564 } else {
565 None
566 };
567 let source_text = source_interval
568 .as_ref()
569 .and_then(|(input, start_byte, stop_byte)| {
570 Some(crate::token::TokenSourceText {
571 input: Rc::clone(input),
572 start_byte: u32::try_from(*start_byte).ok()?,
573 stop_byte: u32::try_from(*stop_byte).ok()?,
574 })
575 });
576 let source_byte_span = source_text
577 .as_ref()
578 .map(|source_text| (source_text.start_byte, source_text.stop_byte));
579 let text = text.or_else(|| {
580 source_text
581 .is_none()
582 .then(|| self.input.text(TextInterval::new(self.token_start, stop)))
583 });
584 let mut token = self.factory.create(TokenSpec {
585 token_type,
586 channel,
587 start: self.token_start,
588 stop,
589 line: self.token_start_line,
590 column: self.token_start_column,
591 text,
592 source_text,
593 source_name: self.input.source_name(),
594 });
595 if let Some((start_byte, stop_byte)) =
596 source_byte_span.or_else(|| self.token_byte_span(stop))
597 {
598 token = token.with_byte_span(start_byte, stop_byte);
599 }
600 token
601 }
602
603 pub fn token_text(&self) -> String {
606 self.token_text_until(self.input.index())
607 }
608
609 pub fn token_text_until(&self, stop_exclusive: usize) -> String {
617 if stop_exclusive <= self.token_start {
618 return String::new();
619 }
620 self.input
621 .text(TextInterval::new(self.token_start, stop_exclusive - 1))
622 }
623
624 pub fn column_at(&self, position: usize) -> usize {
627 let mut column = self.token_start_column;
628 if position <= self.token_start {
629 return column;
630 }
631 for ch in self
632 .input
633 .text(TextInterval::new(self.token_start, position - 1))
634 .chars()
635 {
636 if ch == '\n' {
637 column = 0;
638 } else {
639 column += 1;
640 }
641 }
642 column
643 }
644
645 pub fn eof_token(&self) -> CommonToken {
647 let token = CommonToken::eof(
648 self.input.source_name(),
649 self.input.index(),
650 self.line,
651 self.column,
652 );
653 match self.eof_byte_offset() {
654 Some(byte_offset) => token.with_byte_span(byte_offset, byte_offset),
655 None => token,
656 }
657 }
658
659 fn eof_byte_offset(&self) -> Option<u32> {
660 self.byte_offset_at(self.input.index())
661 }
662
663 fn token_byte_span(&self, stop: usize) -> Option<(u32, u32)> {
664 if stop != usize::MAX && self.token_start <= stop {
665 let (_, start_byte, stop_byte) = self
666 .input
667 .text_source_interval(TextInterval::new(self.token_start, stop))?;
668 return Some((
669 u32::try_from(start_byte).ok()?,
670 u32::try_from(stop_byte).ok()?,
671 ));
672 }
673 let byte_offset = self.byte_offset_at(self.token_start)?;
674 Some((byte_offset, byte_offset))
675 }
676
677 fn byte_offset_at(&self, index: usize) -> Option<u32> {
678 let byte_offset = if index == 0 {
679 0
680 } else {
681 let previous = TextInterval::new(index - 1, index - 1);
682 self.input.text_source_interval(previous)?.2
683 };
684 u32::try_from(byte_offset).ok()
685 }
686}
687
688impl<I, F> Recognizer for BaseLexer<I, F>
689where
690 I: CharStream,
691 F: TokenFactory,
692{
693 fn data(&self) -> &RecognizerData {
694 &self.data
695 }
696
697 fn data_mut(&mut self) -> &mut RecognizerData {
698 &mut self.data
699 }
700}
701
702impl<I, F> Lexer for BaseLexer<I, F>
703where
704 I: CharStream,
705 F: TokenFactory,
706{
707 fn mode(&self) -> i32 {
708 self.mode
709 }
710
711 fn set_mode(&mut self, mode: i32) {
712 self.mode = mode;
713 }
714
715 fn push_mode(&mut self, mode: i32) {
716 self.mode_stack.push(self.mode);
717 self.mode = mode;
718 }
719
720 fn pop_mode(&mut self) -> Option<i32> {
721 let mode = self.mode_stack.pop()?;
722 self.mode = mode;
723 Some(mode)
724 }
725}
726
727impl<I, F> BaseLexer<I, F>
728where
729 I: CharStream,
730 F: TokenFactory,
731{
732 pub const fn line(&self) -> usize {
733 self.line
734 }
735
736 pub const fn column(&self) -> usize {
737 self.column
738 }
739
740 pub fn source_name(&self) -> &str {
741 self.input.source_name()
742 }
743
744 pub const fn hit_eof(&self) -> bool {
745 self.hit_eof
746 }
747
748 pub const fn set_hit_eof(&mut self, hit_eof: bool) {
749 self.hit_eof = hit_eof;
750 }
751
752 pub const fn set_force_interpreted(&mut self, force_interpreted: bool) {
760 self.force_interpreted = force_interpreted;
761 }
762
763 pub const fn force_interpreted(&self) -> bool {
765 self.force_interpreted
766 }
767
768 pub fn record_error(&mut self, line: usize, column: usize, message: impl Into<String>) {
771 self.errors
772 .push(TokenSourceError::new(line, column, message));
773 }
774
775 pub fn drain_errors(&mut self) -> Vec<TokenSourceError> {
777 std::mem::take(&mut self.errors)
778 }
779
780 pub(crate) fn lexer_dfa_state(
783 &self,
784 key: LexerDfaKey,
785 accept_prediction: Option<i32>,
786 ) -> usize {
787 let mut cache = self.dfa_cache.borrow_mut();
788 let next = cache.state_numbers.len();
789 let state = *cache.state_numbers.entry(key).or_insert(next);
790 if let Some(prediction) = accept_prediction {
791 cache.accept_predictions.insert(state, prediction);
792 }
793 state
794 }
795
796 pub fn record_lexer_dfa_edge(&self, from: usize, symbol: i32, to: usize) {
798 self.dfa_cache
799 .borrow_mut()
800 .edges
801 .insert(LexerDfaEdge { from, symbol, to });
802 }
803
804 pub(crate) fn cached_lexer_dfa_transition(
805 &self,
806 state: usize,
807 symbol: i32,
808 ) -> Option<LexerDfaCachedTransition> {
809 let cache = self.dfa_cache.borrow();
810 if let Ok(sym) = usize::try_from(symbol)
811 && sym < DENSE_EDGE_SYMBOLS
812 {
813 let transition = cache.dense_edges.get(state)?.as_ref()?[sym];
814 return (transition.target_state != usize::MAX).then_some(transition);
815 }
816 cache.sparse_edges.get(&(state, symbol)).copied()
817 }
818
819 pub(crate) fn cache_lexer_dfa_transition(
820 &self,
821 state: usize,
822 symbol: i32,
823 transition: LexerDfaCachedTransition,
824 ) {
825 let mut cache = self.dfa_cache.borrow_mut();
826 if let Ok(sym) = usize::try_from(symbol)
827 && sym < DENSE_EDGE_SYMBOLS
828 {
829 if cache.dense_edges.len() <= state {
830 cache.dense_edges.resize_with(state + 1, || None);
831 }
832 let row = cache.dense_edges[state]
833 .get_or_insert_with(|| Box::new([EMPTY_DENSE_EDGE; DENSE_EDGE_SYMBOLS]));
834 if row[sym].target_state == usize::MAX {
836 row[sym] = transition;
837 }
838 return;
839 }
840 cache
841 .sparse_edges
842 .entry((state, symbol))
843 .or_insert(transition);
844 }
845
846 pub(crate) fn cached_lexer_dfa_state(&self, state: usize) -> Option<Rc<LexerDfaCachedState>> {
847 self.dfa_cache
848 .borrow()
849 .cached_states
850 .get(state)
851 .cloned()
852 .flatten()
853 }
854
855 pub(crate) fn cache_lexer_dfa_state(&self, state: usize, cached_state: LexerDfaCachedState) {
856 let mut cache = self.dfa_cache.borrow_mut();
857 if cache.cached_states.len() <= state {
858 cache.cached_states.resize_with(state + 1, || None);
859 }
860 cache.cached_states[state].get_or_insert_with(|| Rc::new(cached_state));
861 }
862
863 pub(crate) fn cached_lexer_mode_start(&self, mode: i32) -> Option<usize> {
864 self.dfa_cache.borrow().mode_starts.get(&mode).copied()
865 }
866
867 pub(crate) fn cache_lexer_mode_start(&self, mode: i32, state: usize) {
868 self.dfa_cache
869 .borrow_mut()
870 .mode_starts
871 .entry(mode)
872 .or_insert(state);
873 }
874
875 pub fn lexer_dfa_string(&self) -> String {
877 let mut out = String::new();
878 let cache = self.dfa_cache.borrow();
879 for edge in &cache.edges {
880 let Some(label) = lexer_dfa_edge_label(edge.symbol) else {
881 continue;
882 };
883 out.push_str(&self.lexer_dfa_state_string(edge.from));
884 out.push('-');
885 out.push_str(&label);
886 out.push_str("->");
887 out.push_str(&self.lexer_dfa_state_string(edge.to));
888 out.push('\n');
889 }
890 out
891 }
892
893 fn lexer_dfa_state_string(&self, state: usize) -> String {
894 self.dfa_cache
895 .borrow()
896 .accept_predictions
897 .get(&state)
898 .map_or_else(
899 || format!("s{state}"),
900 |prediction| format!(":s{state}=>{prediction}"),
901 )
902 }
903}
904
905fn lexer_dfa_edge_label(symbol: i32) -> Option<String> {
906 char::from_u32(symbol.cast_unsigned()).map(|ch| format!("'{ch}'"))
907}
908
909#[cfg(test)]
910mod tests {
911 use super::*;
912 use crate::char_stream::InputStream;
913 use crate::recognizer::RecognizerData;
914 use crate::token::{DEFAULT_CHANNEL, Token};
915 use crate::vocabulary::Vocabulary;
916
917 #[test]
918 fn eof_token_uses_utf8_byte_offset_after_non_ascii_input() {
919 let data = RecognizerData::new(
920 "T",
921 Vocabulary::new(
922 std::iter::empty::<Option<&str>>(),
923 std::iter::empty::<Option<&str>>(),
924 std::iter::empty::<Option<&str>>(),
925 ),
926 );
927 let mut lexer = BaseLexer::new(InputStream::new("β"), data);
928 lexer.consume_char();
929
930 let token = lexer.eof_token();
931
932 assert_eq!(token.start(), 1);
933 assert_eq!(token.stop(), 0);
934 assert_eq!(token.text(), "<EOF>");
935 assert_eq!(token.byte_span(), 2..2);
936 }
937
938 #[test]
939 fn eof_rule_token_uses_utf8_byte_offset_after_non_ascii_input() {
940 let data = RecognizerData::new(
941 "T",
942 Vocabulary::new(
943 std::iter::empty::<Option<&str>>(),
944 std::iter::empty::<Option<&str>>(),
945 std::iter::empty::<Option<&str>>(),
946 ),
947 );
948 let mut lexer = BaseLexer::new(InputStream::new("β"), data);
949 lexer.consume_char();
950 lexer.begin_token();
951
952 let token = lexer.emit_with_stop(1, DEFAULT_CHANNEL, 0, Some("<EOF>".to_owned()));
953
954 assert_eq!(token.start(), 1);
955 assert_eq!(token.stop(), 0);
956 assert_eq!(token.text(), "<EOF>");
957 assert_eq!(token.byte_span(), 2..2);
958 }
959
960 #[test]
961 fn emit_implicit_text_uses_utf8_byte_span_for_non_ascii_input() {
962 let data = RecognizerData::new(
963 "T",
964 Vocabulary::new(
965 std::iter::empty::<Option<&str>>(),
966 std::iter::empty::<Option<&str>>(),
967 std::iter::empty::<Option<&str>>(),
968 ),
969 );
970 let mut lexer = BaseLexer::new(InputStream::new("β"), data);
971 lexer.begin_token();
972 lexer.consume_char();
973
974 let token = lexer.emit(1, DEFAULT_CHANNEL, None);
975
976 assert_eq!(token.start(), 0);
977 assert_eq!(token.stop(), 0);
978 assert_eq!(token.text(), "β");
979 assert_eq!(token.byte_span(), 0..2);
980 }
981}