1use std::cell::RefCell;
2use std::collections::{BTreeSet, HashMap, VecDeque};
3use std::hash::BuildHasherDefault;
4use std::rc::Rc;
5
6use crate::atn::LexerAtn;
7use crate::char_stream::{CharStream, TextInterval};
8use crate::int_stream::EOF;
9use crate::prediction::PredictionFxHasher;
10use crate::recognizer::{Recognizer, RecognizerData};
11use crate::token::{
12 DEFAULT_CHANNEL, INVALID_TOKEN_TYPE, TokenId, TokenSink, TokenSourceError, TokenSpec,
13 TokenStoreError,
14};
15
16#[allow(clippy::disallowed_types)]
17type FxHashMap<K, V> = HashMap<K, V, BuildHasherDefault<PredictionFxHasher>>;
18
19pub const SKIP: i32 = -3;
20pub const MORE: i32 = -2;
21pub const DEFAULT_MODE: i32 = 0;
22
23#[derive(Clone, Copy, Debug, Eq, PartialEq)]
24pub struct LexerMode(pub i32);
25
26#[derive(Clone, Copy, Debug, Eq, PartialEq)]
33pub struct LexerCustomAction {
34 rule_index: i32,
35 action_index: i32,
36 position: usize,
37}
38
39impl LexerCustomAction {
40 pub const fn new(rule_index: i32, action_index: i32, position: usize) -> Self {
42 Self {
43 rule_index,
44 action_index,
45 position,
46 }
47 }
48
49 pub const fn rule_index(self) -> i32 {
51 self.rule_index
52 }
53
54 pub const fn action_index(self) -> i32 {
56 self.action_index
57 }
58
59 pub const fn position(self) -> usize {
61 self.position
62 }
63}
64
65#[derive(Clone, Copy, Debug, Eq, PartialEq)]
67pub struct LexerPredicate {
68 rule_index: usize,
69 pred_index: usize,
70 position: usize,
71}
72
73impl LexerPredicate {
74 pub const fn new(rule_index: usize, pred_index: usize, position: usize) -> Self {
76 Self {
77 rule_index,
78 pred_index,
79 position,
80 }
81 }
82
83 pub const fn rule_index(self) -> usize {
85 self.rule_index
86 }
87
88 pub const fn pred_index(self) -> usize {
90 self.pred_index
91 }
92
93 pub const fn position(self) -> usize {
95 self.position
96 }
97}
98
99#[derive(Debug)]
104enum LexerRef<'a, I>
105where
106 I: CharStream,
107{
108 Shared(&'a BaseLexer<I>),
109 Mut(&'a mut BaseLexer<I>),
110}
111
112impl<I> LexerRef<'_, I>
113where
114 I: CharStream,
115{
116 const fn get(&self) -> &BaseLexer<I> {
117 match self {
118 LexerRef::Shared(lexer) => lexer,
119 LexerRef::Mut(lexer) => lexer,
120 }
121 }
122}
123
124#[derive(Debug)]
126pub struct LexerSemCtx<'a, I>
127where
128 I: CharStream,
129{
130 lexer: LexerRef<'a, I>,
131 rule_index: usize,
132 coordinate_index: usize,
133 position: usize,
134}
135
136impl<'a, I> LexerSemCtx<'a, I>
137where
138 I: CharStream,
139{
140 pub(crate) const fn new(
141 lexer: &'a BaseLexer<I>,
142 rule_index: usize,
143 coordinate_index: usize,
144 position: usize,
145 ) -> Self {
146 Self {
147 lexer: LexerRef::Shared(lexer),
148 rule_index,
149 coordinate_index,
150 position,
151 }
152 }
153
154 pub(crate) const fn new_mut(
157 lexer: &'a mut BaseLexer<I>,
158 rule_index: usize,
159 coordinate_index: usize,
160 position: usize,
161 ) -> Self {
162 Self {
163 lexer: LexerRef::Mut(lexer),
164 rule_index,
165 coordinate_index,
166 position,
167 }
168 }
169
170 #[must_use]
172 pub const fn rule_index(&self) -> usize {
173 self.rule_index
174 }
175
176 #[must_use]
178 pub const fn coordinate_index(&self) -> usize {
179 self.coordinate_index
180 }
181
182 #[must_use]
184 pub const fn position(&self) -> usize {
185 self.position
186 }
187
188 #[must_use]
190 pub fn mode(&self) -> i32 {
191 self.lexer.get().mode()
192 }
193
194 #[must_use]
196 pub const fn column(&self) -> usize {
197 self.lexer.get().column()
198 }
199
200 #[must_use]
202 pub fn position_column(&self) -> usize {
203 self.lexer.get().column_at(self.position)
204 }
205
206 #[must_use]
208 pub const fn token_start_column(&self) -> usize {
209 self.lexer.get().token_start_column()
210 }
211
212 #[must_use]
214 pub fn text_so_far(&self) -> String {
215 self.lexer.get().token_text_until(self.position)
216 }
217
218 pub fn la(&mut self, offset: isize) -> i32 {
224 match &mut self.lexer {
225 LexerRef::Shared(lexer) => lexer.lookahead_at(self.position, offset),
226 LexerRef::Mut(lexer) => lexer.input_mut().la(offset),
227 }
228 }
229
230 #[must_use]
232 pub const fn token_start(&self) -> usize {
233 self.lexer.get().token_start()
234 }
235
236 #[must_use]
238 pub const fn token_type(&self) -> i32 {
239 self.lexer.get().token_type()
240 }
241
242 #[must_use]
244 pub const fn channel(&self) -> i32 {
245 self.lexer.get().channel()
246 }
247
248 pub const fn set_type(&mut self, token_type: i32) -> bool {
251 match &mut self.lexer {
252 LexerRef::Mut(lexer) => {
253 lexer.set_type(token_type);
254 true
255 }
256 LexerRef::Shared(_) => false,
257 }
258 }
259
260 pub const fn set_channel(&mut self, channel: i32) -> bool {
263 match &mut self.lexer {
264 LexerRef::Mut(lexer) => {
265 lexer.set_channel(channel);
266 true
267 }
268 LexerRef::Shared(_) => false,
269 }
270 }
271
272 pub fn consume(&mut self) -> bool {
275 match &mut self.lexer {
276 LexerRef::Mut(lexer) => {
277 lexer.consume_char();
278 true
279 }
280 LexerRef::Shared(_) => false,
281 }
282 }
283
284 pub const fn skip(&mut self) -> bool {
286 self.set_type(SKIP)
287 }
288
289 pub const fn more(&mut self) -> bool {
292 self.set_type(MORE)
293 }
294
295 pub fn reset_accept_position(&mut self, index: usize) -> bool {
297 match &mut self.lexer {
298 LexerRef::Mut(lexer) => {
299 lexer.reset_accept_position(index);
300 true
301 }
302 LexerRef::Shared(_) => false,
303 }
304 }
305
306 pub fn set_token_start(&mut self, index: usize) -> bool {
312 match &mut self.lexer {
313 LexerRef::Mut(lexer) => lexer.set_token_start(index),
314 LexerRef::Shared(_) => false,
315 }
316 }
317
318 pub fn enqueue_token(&mut self, token_type: i32, stop: usize) -> bool {
324 let channel = self.channel();
325 self.enqueue_token_with_channel(token_type, channel, stop)
326 }
327
328 pub fn enqueue_token_with_channel(
331 &mut self,
332 token_type: i32,
333 channel: i32,
334 stop: usize,
335 ) -> bool {
336 match &mut self.lexer {
337 LexerRef::Mut(lexer) => {
338 lexer.enqueue_token(token_type, channel, stop, None);
339 true
340 }
341 LexerRef::Shared(_) => false,
342 }
343 }
344
345 pub fn set_mode(&mut self, mode: i32) -> bool {
352 match &mut self.lexer {
353 LexerRef::Mut(lexer) => {
354 lexer.set_mode(mode);
355 true
356 }
357 LexerRef::Shared(_) => false,
358 }
359 }
360
361 pub fn push_mode(&mut self, mode: i32) -> bool {
364 match &mut self.lexer {
365 LexerRef::Mut(lexer) => {
366 lexer.push_mode(mode);
367 true
368 }
369 LexerRef::Shared(_) => false,
370 }
371 }
372
373 pub fn pop_mode(&mut self) -> Option<i32> {
377 match &mut self.lexer {
378 LexerRef::Mut(lexer) => lexer.pop_mode(),
379 LexerRef::Shared(_) => None,
380 }
381 }
382}
383
384#[derive(Debug)]
392pub struct LexerLifecycleCtx<'a, I>
393where
394 I: CharStream,
395{
396 lexer: &'a mut BaseLexer<I>,
397 accept_position: Option<usize>,
398}
399
400impl<'a, I> LexerLifecycleCtx<'a, I>
401where
402 I: CharStream,
403{
404 pub(crate) const fn new(lexer: &'a mut BaseLexer<I>, accept_position: Option<usize>) -> Self {
405 Self {
406 lexer,
407 accept_position,
408 }
409 }
410
411 #[must_use]
416 pub const fn accept_position(&self) -> Option<usize> {
417 self.accept_position
418 }
419
420 #[must_use]
422 pub fn input_position(&self) -> usize {
423 self.lexer.input().index()
424 }
425
426 #[must_use]
428 pub const fn mode(&self) -> i32 {
429 self.lexer.mode
430 }
431
432 #[must_use]
434 pub const fn line(&self) -> usize {
435 self.lexer.line()
436 }
437
438 #[must_use]
440 pub const fn column(&self) -> usize {
441 self.lexer.column()
442 }
443
444 #[must_use]
446 pub const fn token_start(&self) -> usize {
447 self.lexer.token_start()
448 }
449
450 #[must_use]
452 pub const fn token_start_line(&self) -> usize {
453 self.lexer.token_start_line()
454 }
455
456 #[must_use]
458 pub const fn token_start_column(&self) -> usize {
459 self.lexer.token_start_column()
460 }
461
462 #[must_use]
464 pub const fn token_type(&self) -> i32 {
465 self.lexer.token_type()
466 }
467
468 #[must_use]
470 pub const fn channel(&self) -> i32 {
471 self.lexer.channel()
472 }
473
474 #[must_use]
476 pub fn pending_token_count(&self) -> usize {
477 self.lexer.pending_tokens.len()
478 }
479
480 #[must_use]
482 pub fn token_text(&self) -> String {
483 self.lexer.token_text()
484 }
485
486 #[must_use]
490 pub fn accepted_text(&self) -> Option<String> {
491 self.accept_position
492 .map(|position| self.lexer.token_text_until(position))
493 }
494
495 pub fn la(&mut self, offset: isize) -> i32 {
498 self.lexer.la(offset)
499 }
500
501 pub fn consume(&mut self) {
503 self.lexer.consume_char();
504 }
505
506 pub const fn set_type(&mut self, token_type: i32) {
508 self.lexer.set_type(token_type);
509 }
510
511 pub const fn set_channel(&mut self, channel: i32) {
513 self.lexer.set_channel(channel);
514 }
515
516 pub const fn skip(&mut self) {
518 self.lexer.skip();
519 }
520
521 pub const fn more(&mut self) {
523 self.lexer.more();
524 }
525
526 pub fn reset_accept_position(&mut self, index: usize) {
528 self.lexer.reset_accept_position(index);
529 }
530
531 pub fn set_token_start(&mut self, index: usize) -> bool {
533 self.lexer.set_token_start(index)
534 }
535
536 pub fn enqueue_token(&mut self, token_type: i32, stop: usize) {
538 self.enqueue_token_with_channel(token_type, self.channel(), stop);
539 }
540
541 pub fn enqueue_token_with_channel(&mut self, token_type: i32, channel: i32, stop: usize) {
543 self.lexer.enqueue_token(token_type, channel, stop, None);
544 }
545
546 pub fn set_mode(&mut self, mode: i32) {
548 self.lexer.set_mode(mode);
549 }
550
551 pub fn push_mode(&mut self, mode: i32) {
553 self.lexer.push_mode(mode);
554 }
555
556 pub fn pop_mode(&mut self) -> Option<i32> {
558 self.lexer.pop_mode()
559 }
560}
561
562pub trait Lexer: Recognizer {
563 fn mode(&self) -> i32;
564 fn set_mode(&mut self, mode: i32);
565 fn push_mode(&mut self, mode: i32);
566 fn pop_mode(&mut self) -> Option<i32>;
567}
568
569#[derive(Clone, Debug)]
570pub struct BaseLexer<I> {
571 input: I,
572 data: RecognizerData,
573 has_source_text: bool,
574 mode: i32,
575 mode_stack: Vec<i32>,
576 token_type: i32,
577 channel: i32,
578 token_start: usize,
579 token_start_line: usize,
580 token_start_column: usize,
581 line: usize,
582 column: usize,
583 hit_eof: bool,
584 force_interpreted: bool,
585 errors: RefCell<Vec<TokenSourceError>>,
586 semantic_error_coordinates: RefCell<BTreeSet<(u8, usize, usize, usize)>>,
587 pending_tokens: VecDeque<TokenSpec>,
588 dfa_cache: Rc<RefCell<LexerDfaCache>>,
589}
590
591#[derive(Clone, Debug, Default)]
599struct LexerDfaCache {
600 state_numbers: FxHashMap<LexerDfaKey, usize>,
601 accept_predictions: FxHashMap<usize, i32>,
602 edges: BTreeSet<LexerDfaEdge>,
606 cached_states: Vec<Option<Rc<LexerDfaCachedState>>>,
608 dense_edges: Vec<Option<Box<DenseEdgeRow>>>,
613 sparse_edges: FxHashMap<(usize, i32), LexerDfaCachedTransition>,
615 mode_starts: FxHashMap<i32, usize>,
616}
617
618const DENSE_EDGE_SYMBOLS: usize = 128;
620
621type DenseEdgeRow = [LexerDfaCachedTransition; DENSE_EDGE_SYMBOLS];
622
623const EMPTY_DENSE_EDGE: LexerDfaCachedTransition = LexerDfaCachedTransition {
626 target_state: usize::MAX,
627 position_delta: 0,
628};
629
630thread_local! {
631 static SHARED_LEXER_DFA_CACHES: RefCell<HashMap<usize, Rc<RefCell<LexerDfaCache>>>> =
634 RefCell::new(HashMap::new());
635}
636
637#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
639pub(crate) struct LexerDfaKey {
640 configs: Vec<LexerDfaConfigKey>,
641}
642
643impl LexerDfaKey {
644 pub(crate) fn new(mut configs: Vec<LexerDfaConfigKey>) -> Self {
645 configs.sort_unstable();
646 Self { configs }
647 }
648}
649
650#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
652pub(crate) struct LexerDfaConfigKey {
653 pub(crate) state: usize,
654 pub(crate) alt_rule_index: Option<usize>,
655 pub(crate) consumed_eof: bool,
656 pub(crate) passed_non_greedy: bool,
657 pub(crate) stack: Vec<usize>,
658 pub(crate) actions: Vec<LexerDfaActionKey>,
659}
660
661#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
662pub(crate) struct LexerDfaActionKey {
663 pub(crate) action_index: usize,
664 pub(crate) position_delta: usize,
665 pub(crate) rule_index: usize,
666}
667
668impl LexerDfaConfigKey {
669 pub(crate) const fn new(
670 state: usize,
671 alt_rule_index: Option<usize>,
672 consumed_eof: bool,
673 passed_non_greedy: bool,
674 stack: Vec<usize>,
675 actions: Vec<LexerDfaActionKey>,
676 ) -> Self {
677 Self {
678 state,
679 alt_rule_index,
680 consumed_eof,
681 passed_non_greedy,
682 stack,
683 actions,
684 }
685 }
686}
687
688#[derive(Clone, Copy, Debug)]
689pub(crate) struct LexerDfaCachedTransition {
690 pub(crate) target_state: usize,
691 pub(crate) position_delta: usize,
692}
693
694#[derive(Clone, Debug)]
695pub(crate) struct LexerDfaCachedAccept {
696 pub(crate) position_delta: usize,
697 pub(crate) rule_index: usize,
698 pub(crate) consumed_eof: bool,
699 pub(crate) actions: Vec<LexerDfaActionKey>,
700}
701
702#[derive(Clone, Debug)]
703pub(crate) struct LexerDfaCachedState {
704 pub(crate) has_semantic_context: bool,
705 pub(crate) configs: Vec<LexerDfaConfigKey>,
706 pub(crate) accept: Option<LexerDfaCachedAccept>,
707}
708
709#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
712struct LexerDfaEdge {
713 from: usize,
714 symbol: i32,
715 to: usize,
716}
717
718impl<I> BaseLexer<I>
719where
720 I: CharStream,
721{
722 pub fn new(input: I, data: RecognizerData) -> Self {
723 let has_source_text = input.source_text().is_some();
724 Self {
725 input,
726 data,
727 has_source_text,
728 mode: DEFAULT_MODE,
729 mode_stack: Vec::new(),
730 token_type: INVALID_TOKEN_TYPE,
731 channel: DEFAULT_CHANNEL,
732 token_start: 0,
733 token_start_line: 1,
734 token_start_column: 0,
735 line: 1,
736 column: 0,
737 hit_eof: false,
738 force_interpreted: false,
739 errors: RefCell::new(Vec::new()),
740 semantic_error_coordinates: RefCell::new(BTreeSet::new()),
741 pending_tokens: VecDeque::new(),
742 dfa_cache: Rc::new(RefCell::new(LexerDfaCache::default())),
743 }
744 }
745
746 pub fn reset(&mut self) {
753 self.input.seek(0);
754 self.mode = DEFAULT_MODE;
755 self.mode_stack.clear();
756 self.token_type = INVALID_TOKEN_TYPE;
757 self.channel = DEFAULT_CHANNEL;
758 self.token_start = 0;
759 self.token_start_line = 1;
760 self.token_start_column = 0;
761 self.line = 1;
762 self.column = 0;
763 self.hit_eof = false;
764 self.errors.get_mut().clear();
765 self.semantic_error_coordinates.get_mut().clear();
766 self.pending_tokens.clear();
767 }
768
769 pub fn set_input_stream(&mut self, input: I) {
774 self.input = input;
775 self.has_source_text = self.input.source_text().is_some();
776 self.reset();
777 }
778
779 #[must_use]
789 pub fn with_shared_dfa(mut self, atn: &'static LexerAtn) -> Self {
790 let ptr: *const LexerAtn = atn;
791 let key = ptr as usize;
792 self.dfa_cache = SHARED_LEXER_DFA_CACHES
793 .with(|caches| Rc::clone(caches.borrow_mut().entry(key).or_insert_with(Rc::default)));
794 self
795 }
796
797 pub fn clear_dfa(&self) {
803 *self.dfa_cache.borrow_mut() = LexerDfaCache::default();
804 }
805
806 pub const fn input(&self) -> &I {
807 &self.input
808 }
809
810 pub const fn input_mut(&mut self) -> &mut I {
811 &mut self.input
812 }
813
814 pub fn begin_token(&mut self) {
817 self.semantic_error_coordinates.get_mut().clear();
818 self.token_type = INVALID_TOKEN_TYPE;
819 self.channel = DEFAULT_CHANNEL;
820 self.token_start = self.input.index();
821 self.token_start_line = self.line;
822 self.token_start_column = self.column;
823 }
824
825 pub const fn token_start(&self) -> usize {
827 self.token_start
828 }
829
830 pub const fn token_start_line(&self) -> usize {
832 self.token_start_line
833 }
834
835 pub const fn token_start_column(&self) -> usize {
837 self.token_start_column
838 }
839
840 pub const fn token_type(&self) -> i32 {
842 self.token_type
843 }
844
845 pub const fn set_type(&mut self, token_type: i32) {
847 self.token_type = token_type;
848 }
849
850 pub const fn channel(&self) -> i32 {
852 self.channel
853 }
854
855 pub const fn set_channel(&mut self, channel: i32) {
857 self.channel = channel;
858 }
859
860 pub const fn skip(&mut self) {
862 self.set_type(SKIP);
863 }
864
865 pub const fn more(&mut self) {
867 self.set_type(MORE);
868 }
869
870 pub fn la(&mut self, offset: isize) -> i32 {
873 self.input.la(offset)
874 }
875
876 fn lookahead_at(&self, position: usize, offset: isize) -> i32 {
877 if offset == 0 {
878 return 0;
879 }
880 let absolute = if offset > 0 {
881 position.checked_add((offset - 1).cast_unsigned())
882 } else {
883 offset
884 .checked_neg()
885 .and_then(|distance| usize::try_from(distance).ok())
886 .and_then(|distance| position.checked_sub(distance))
887 };
888 let Some(index) = absolute.filter(|index| *index < self.input.size()) else {
889 return EOF;
890 };
891 if let Some(symbol) = self.input.symbol_at(index) {
892 return symbol;
893 }
894 self.input
895 .text(TextInterval::new(index, index))
896 .chars()
897 .next()
898 .map_or(EOF, |ch| u32::from(ch).cast_signed())
899 }
900
901 pub fn consume_char(&mut self) {
908 let la = self.input.la(1);
909 if la == EOF {
910 return;
911 }
912 self.input.consume();
913 if char::from_u32(la.cast_unsigned()) == Some('\n') {
914 self.line += 1;
915 self.column = 0;
916 } else {
917 self.column += 1;
918 }
919 }
920
921 pub(crate) fn commit_position(&mut self, start: usize, target: usize) {
924 self.reposition_from(start, self.line, self.column, target);
925 }
926
927 fn reposition_from(&mut self, start: usize, line: usize, column: usize, target: usize) {
928 let start = start.min(self.input.size());
929 let target = target.max(start).min(self.input.size());
930 if let Some(summary) = self.input.position_summary(start, target) {
931 self.input.seek(target);
932 (self.line, self.column) = summary.apply(line, column);
933 #[cfg(feature = "perf-counters")]
934 crate::perf::record_lexer_bulk_commit(target - start);
935 return;
936 }
937
938 self.input.seek(start);
939 self.line = line;
940 self.column = column;
941 #[cfg(feature = "perf-counters")]
942 let before = self.input.index();
943 while self.input.index() < target && self.input.la(1) != EOF {
944 self.consume_char();
945 }
946 #[cfg(feature = "perf-counters")]
947 crate::perf::record_lexer_scalar_replay(self.input.index().saturating_sub(before));
948 }
949
950 pub fn reset_accept_position(&mut self, index: usize) {
957 let target = index.max(self.token_start);
958 self.reposition_from(
959 self.token_start,
960 self.token_start_line,
961 self.token_start_column,
962 target,
963 );
964 }
965
966 pub fn set_token_start(&mut self, index: usize) -> bool {
972 if index < self.token_start || index > self.input.index() {
973 return false;
974 }
975 let (line, column) = self.position_at(index);
976 self.token_start = index;
977 self.token_start_line = line;
978 self.token_start_column = column;
979 true
980 }
981
982 pub fn emit(
990 &self,
991 sink: &mut TokenSink<'_>,
992 token_type: i32,
993 channel: i32,
994 text: Option<String>,
995 ) -> Result<TokenId, TokenStoreError> {
996 let stop = self.input.index().checked_sub(1).unwrap_or(usize::MAX);
997 self.emit_with_stop(sink, token_type, channel, stop, text)
998 }
999
1000 pub fn emit_with_stop(
1006 &self,
1007 sink: &mut TokenSink<'_>,
1008 token_type: i32,
1009 channel: i32,
1010 stop: usize,
1011 text: Option<String>,
1012 ) -> Result<TokenId, TokenStoreError> {
1013 sink.push(self.token_spec_with_stop(token_type, channel, stop, text))
1014 }
1015
1016 fn token_spec_with_stop(
1017 &self,
1018 token_type: i32,
1019 channel: i32,
1020 stop: usize,
1021 text: Option<String>,
1022 ) -> TokenSpec {
1023 let text = text.or_else(|| {
1024 if stop == usize::MAX {
1025 Some("<EOF>".to_owned())
1026 } else {
1027 None
1028 }
1029 });
1030 let source_interval = if self.has_source_text
1031 && text.is_none()
1032 && stop != usize::MAX
1033 && self.token_start <= stop
1034 {
1035 self.input
1036 .byte_interval(TextInterval::new(self.token_start, stop))
1037 } else {
1038 None
1039 };
1040 let text = text.or_else(|| {
1041 source_interval
1042 .is_none()
1043 .then(|| self.input.text(TextInterval::new(self.token_start, stop)))
1044 });
1045 let (start_byte, stop_byte) = source_interval
1046 .or_else(|| self.token_byte_span(stop))
1047 .unwrap_or((self.token_start, self.token_start));
1048 TokenSpec {
1049 token_type,
1050 channel,
1051 start: self.token_start,
1052 stop,
1053 start_byte,
1054 stop_byte,
1055 line: self.token_start_line,
1056 column: self.token_start_column,
1057 text,
1058 source_backed: source_interval.is_some(),
1059 }
1060 }
1061
1062 pub fn enqueue_token(
1068 &mut self,
1069 token_type: i32,
1070 channel: i32,
1071 stop: usize,
1072 text: Option<String>,
1073 ) {
1074 let token = self.token_spec_with_stop(token_type, channel, stop, text);
1075 self.pending_tokens.push_back(token);
1076 }
1077
1078 pub(crate) fn emit_pending_token(
1079 &mut self,
1080 sink: &mut TokenSink<'_>,
1081 ) -> Result<Option<TokenId>, TokenStoreError> {
1082 self.pending_tokens
1083 .pop_front()
1084 .map(|token| sink.push(token))
1085 .transpose()
1086 }
1087
1088 pub(crate) fn emit_or_enqueue_with_stop(
1089 &mut self,
1090 sink: &mut TokenSink<'_>,
1091 stop: usize,
1092 text: Option<String>,
1093 ) -> Result<TokenId, TokenStoreError> {
1094 let token = self.token_spec_with_stop(self.token_type, self.channel, stop, text);
1095 self.emit_or_enqueue(sink, token)
1096 }
1097
1098 fn emit_or_enqueue(
1099 &mut self,
1100 sink: &mut TokenSink<'_>,
1101 token: TokenSpec,
1102 ) -> Result<TokenId, TokenStoreError> {
1103 if self.pending_tokens.is_empty() {
1104 return sink.push(token);
1105 }
1106 self.pending_tokens.push_back(token);
1107 self.emit_pending_token(sink)?
1108 .ok_or_else(|| unreachable!("the pending-token queue was just populated"))
1109 }
1110
1111 pub fn token_text(&self) -> String {
1114 self.token_text_until(self.input.index())
1115 }
1116
1117 pub fn token_text_until(&self, stop_exclusive: usize) -> String {
1125 if stop_exclusive <= self.token_start {
1126 return String::new();
1127 }
1128 self.input
1129 .text(TextInterval::new(self.token_start, stop_exclusive - 1))
1130 }
1131
1132 pub fn column_at(&self, position: usize) -> usize {
1135 self.position_at(position).1
1136 }
1137
1138 fn position_at(&self, position: usize) -> (usize, usize) {
1139 let mut line = self.token_start_line;
1140 let mut column = self.token_start_column;
1141 if position <= self.token_start {
1142 return (line, column);
1143 }
1144 if let Some(summary) = self.input.position_summary(self.token_start, position) {
1145 return summary.apply(line, column);
1146 }
1147 for ch in self
1148 .input
1149 .text(TextInterval::new(self.token_start, position - 1))
1150 .chars()
1151 {
1152 if ch == '\n' {
1153 line += 1;
1154 column = 0;
1155 } else {
1156 column += 1;
1157 }
1158 }
1159 (line, column)
1160 }
1161
1162 pub fn eof_token(&self, sink: &mut TokenSink<'_>) -> Result<TokenId, TokenStoreError> {
1164 sink.push(self.eof_token_spec())
1165 }
1166
1167 pub(crate) fn emit_eof_or_pending(
1168 &mut self,
1169 sink: &mut TokenSink<'_>,
1170 ) -> Result<TokenId, TokenStoreError> {
1171 let token = self.eof_token_spec();
1172 self.emit_or_enqueue(sink, token)
1173 }
1174
1175 fn eof_token_spec(&self) -> TokenSpec {
1176 let byte_offset = self.eof_byte_offset().unwrap_or_else(|| self.input.index());
1177 TokenSpec::eof(self.input.index(), byte_offset, self.line, self.column)
1178 }
1179
1180 fn eof_byte_offset(&self) -> Option<usize> {
1181 self.byte_offset_at(self.input.index())
1182 }
1183
1184 fn token_byte_span(&self, stop: usize) -> Option<(usize, usize)> {
1185 if stop != usize::MAX && self.token_start <= stop {
1186 let (start_byte, stop_byte) = self
1187 .input
1188 .byte_interval(TextInterval::new(self.token_start, stop))?;
1189 return Some((start_byte, stop_byte));
1190 }
1191 let byte_offset = self.byte_offset_at(self.token_start)?;
1192 Some((byte_offset, byte_offset))
1193 }
1194
1195 fn byte_offset_at(&self, index: usize) -> Option<usize> {
1196 let byte_offset = if index == 0 {
1197 0
1198 } else {
1199 let previous = TextInterval::new(index - 1, index - 1);
1200 self.input.byte_interval(previous)?.1
1201 };
1202 Some(byte_offset)
1203 }
1204}
1205
1206impl<I> Recognizer for BaseLexer<I>
1207where
1208 I: CharStream,
1209{
1210 fn data(&self) -> &RecognizerData {
1211 &self.data
1212 }
1213
1214 fn data_mut(&mut self) -> &mut RecognizerData {
1215 &mut self.data
1216 }
1217}
1218
1219impl<I> Lexer for BaseLexer<I>
1220where
1221 I: CharStream,
1222{
1223 fn mode(&self) -> i32 {
1224 self.mode
1225 }
1226
1227 fn set_mode(&mut self, mode: i32) {
1228 self.mode = mode;
1229 }
1230
1231 fn push_mode(&mut self, mode: i32) {
1232 self.mode_stack.push(self.mode);
1233 self.mode = mode;
1234 }
1235
1236 fn pop_mode(&mut self) -> Option<i32> {
1237 let mode = self.mode_stack.pop()?;
1238 self.mode = mode;
1239 Some(mode)
1240 }
1241}
1242
1243impl<I> BaseLexer<I>
1244where
1245 I: CharStream,
1246{
1247 pub const fn line(&self) -> usize {
1248 self.line
1249 }
1250
1251 pub const fn column(&self) -> usize {
1252 self.column
1253 }
1254
1255 pub fn source_name(&self) -> &str {
1256 self.input.source_name()
1257 }
1258
1259 pub fn source_text(&self) -> Option<Rc<str>> {
1260 self.input.source_text()
1261 }
1262
1263 pub const fn hit_eof(&self) -> bool {
1264 self.hit_eof
1265 }
1266
1267 pub const fn set_hit_eof(&mut self, hit_eof: bool) {
1268 self.hit_eof = hit_eof;
1269 }
1270
1271 pub const fn set_force_interpreted(&mut self, force_interpreted: bool) {
1279 self.force_interpreted = force_interpreted;
1280 }
1281
1282 pub const fn force_interpreted(&self) -> bool {
1284 self.force_interpreted
1285 }
1286
1287 pub fn record_error(&self, line: usize, column: usize, message: impl Into<String>) {
1290 self.errors
1291 .borrow_mut()
1292 .push(TokenSourceError::new(line, column, message));
1293 }
1294
1295 pub fn record_semantic_error(&self, action: bool, rule_index: usize, coordinate_index: usize) {
1297 let kind = u8::from(action);
1298 if !self.semantic_error_coordinates.borrow_mut().insert((
1299 kind,
1300 rule_index,
1301 coordinate_index,
1302 self.token_start,
1303 )) {
1304 return;
1305 }
1306 let label = if action { "action" } else { "predicate" };
1307 self.record_error(
1308 self.token_start_line,
1309 self.token_start_column,
1310 format!("unhandled lexer semantic {label}: rule={rule_index} index={coordinate_index}"),
1311 );
1312 }
1313
1314 pub fn drain_errors(&mut self) -> Vec<TokenSourceError> {
1316 std::mem::take(self.errors.get_mut())
1317 }
1318
1319 pub(crate) fn lexer_dfa_state(
1322 &self,
1323 key: LexerDfaKey,
1324 accept_prediction: Option<i32>,
1325 ) -> usize {
1326 let mut cache = self.dfa_cache.borrow_mut();
1327 let next = cache.state_numbers.len();
1328 let state = *cache.state_numbers.entry(key).or_insert(next);
1329 if let Some(prediction) = accept_prediction {
1330 cache.accept_predictions.insert(state, prediction);
1331 }
1332 state
1333 }
1334
1335 pub fn record_lexer_dfa_edge(&self, from: usize, symbol: i32, to: usize) {
1337 self.dfa_cache
1338 .borrow_mut()
1339 .edges
1340 .insert(LexerDfaEdge { from, symbol, to });
1341 }
1342
1343 pub(crate) fn cached_lexer_dfa_transition(
1344 &self,
1345 state: usize,
1346 symbol: i32,
1347 ) -> Option<LexerDfaCachedTransition> {
1348 let cache = self.dfa_cache.borrow();
1349 if let Ok(sym) = usize::try_from(symbol)
1350 && sym < DENSE_EDGE_SYMBOLS
1351 {
1352 let transition = cache.dense_edges.get(state)?.as_ref()?[sym];
1353 return (transition.target_state != usize::MAX).then_some(transition);
1354 }
1355 cache.sparse_edges.get(&(state, symbol)).copied()
1356 }
1357
1358 pub(crate) fn cache_lexer_dfa_transition(
1359 &self,
1360 state: usize,
1361 symbol: i32,
1362 transition: LexerDfaCachedTransition,
1363 ) {
1364 let mut cache = self.dfa_cache.borrow_mut();
1365 if let Ok(sym) = usize::try_from(symbol)
1366 && sym < DENSE_EDGE_SYMBOLS
1367 {
1368 if cache.dense_edges.len() <= state {
1369 cache.dense_edges.resize_with(state + 1, || None);
1370 }
1371 let row = cache.dense_edges[state]
1372 .get_or_insert_with(|| Box::new([EMPTY_DENSE_EDGE; DENSE_EDGE_SYMBOLS]));
1373 if row[sym].target_state == usize::MAX {
1375 row[sym] = transition;
1376 }
1377 return;
1378 }
1379 cache
1380 .sparse_edges
1381 .entry((state, symbol))
1382 .or_insert(transition);
1383 }
1384
1385 pub(crate) fn cached_lexer_dfa_state(&self, state: usize) -> Option<Rc<LexerDfaCachedState>> {
1386 self.dfa_cache
1387 .borrow()
1388 .cached_states
1389 .get(state)
1390 .cloned()
1391 .flatten()
1392 }
1393
1394 pub(crate) fn cache_lexer_dfa_state(&self, state: usize, cached_state: LexerDfaCachedState) {
1395 let mut cache = self.dfa_cache.borrow_mut();
1396 if cache.cached_states.len() <= state {
1397 cache.cached_states.resize_with(state + 1, || None);
1398 }
1399 cache.cached_states[state].get_or_insert_with(|| Rc::new(cached_state));
1400 }
1401
1402 pub(crate) fn cached_lexer_mode_start(&self, mode: i32) -> Option<usize> {
1403 self.dfa_cache.borrow().mode_starts.get(&mode).copied()
1404 }
1405
1406 pub(crate) fn cache_lexer_mode_start(&self, mode: i32, state: usize) {
1407 self.dfa_cache
1408 .borrow_mut()
1409 .mode_starts
1410 .entry(mode)
1411 .or_insert(state);
1412 }
1413
1414 pub fn lexer_dfa_string(&self) -> String {
1416 let mut out = String::new();
1417 let cache = self.dfa_cache.borrow();
1418 for edge in &cache.edges {
1419 let Some(label) = lexer_dfa_edge_label(edge.symbol) else {
1420 continue;
1421 };
1422 out.push_str(&self.lexer_dfa_state_string(edge.from));
1423 out.push('-');
1424 out.push_str(&label);
1425 out.push_str("->");
1426 out.push_str(&self.lexer_dfa_state_string(edge.to));
1427 out.push('\n');
1428 }
1429 out
1430 }
1431
1432 fn lexer_dfa_state_string(&self, state: usize) -> String {
1433 self.dfa_cache
1434 .borrow()
1435 .accept_predictions
1436 .get(&state)
1437 .map_or_else(
1438 || format!("s{state}"),
1439 |prediction| format!(":s{state}=>{prediction}"),
1440 )
1441 }
1442}
1443
1444fn lexer_dfa_edge_label(symbol: i32) -> Option<String> {
1445 char::from_u32(symbol.cast_unsigned()).map(|ch| format!("'{ch}'"))
1446}
1447
1448#[cfg(test)]
1449mod tests {
1450 use super::*;
1451 use crate::char_stream::InputStream;
1452 use crate::int_stream::IntStream;
1453 use crate::recognizer::RecognizerData;
1454 use crate::token::{DEFAULT_CHANNEL, Token, TokenStore};
1455 use crate::vocabulary::Vocabulary;
1456
1457 #[derive(Clone, Debug)]
1458 struct UnsharedInput(InputStream);
1459
1460 impl IntStream for UnsharedInput {
1461 fn consume(&mut self) {
1462 self.0.consume();
1463 }
1464
1465 fn la(&mut self, offset: isize) -> i32 {
1466 self.0.la(offset)
1467 }
1468
1469 fn index(&self) -> usize {
1470 self.0.index()
1471 }
1472
1473 fn seek(&mut self, index: usize) {
1474 self.0.seek(index);
1475 }
1476
1477 fn size(&self) -> usize {
1478 self.0.size()
1479 }
1480
1481 fn source_name(&self) -> &str {
1482 self.0.source_name()
1483 }
1484 }
1485
1486 impl CharStream for UnsharedInput {
1487 fn text(&self, interval: TextInterval) -> String {
1488 self.0.text(interval)
1489 }
1490
1491 fn byte_interval(&self, interval: TextInterval) -> Option<(usize, usize)> {
1492 self.0.byte_interval(interval)
1493 }
1494 }
1495
1496 #[test]
1497 fn eof_token_uses_utf8_byte_offset_after_non_ascii_input() {
1498 let data = RecognizerData::new(
1499 "T",
1500 Vocabulary::new(
1501 std::iter::empty::<Option<&str>>(),
1502 std::iter::empty::<Option<&str>>(),
1503 std::iter::empty::<Option<&str>>(),
1504 ),
1505 );
1506 let mut lexer = BaseLexer::new(InputStream::new("β"), data);
1507 lexer.consume_char();
1508
1509 let mut store = TokenStore::new(lexer.source_text(), lexer.source_name());
1510 let mut sink = TokenSink::new(&mut store);
1511 let id = lexer.eof_token(&mut sink).expect("test token should fit");
1512 let token = sink.view(id).expect("emitted token should exist");
1513
1514 assert_eq!(token.start(), 1);
1515 assert_eq!(token.stop(), 0);
1516 assert_eq!(token.text(), "<EOF>");
1517 assert_eq!(token.byte_span(), 2..2);
1518 }
1519
1520 #[test]
1521 fn eof_rule_token_uses_utf8_byte_offset_after_non_ascii_input() {
1522 let data = RecognizerData::new(
1523 "T",
1524 Vocabulary::new(
1525 std::iter::empty::<Option<&str>>(),
1526 std::iter::empty::<Option<&str>>(),
1527 std::iter::empty::<Option<&str>>(),
1528 ),
1529 );
1530 let mut lexer = BaseLexer::new(InputStream::new("β"), data);
1531 lexer.consume_char();
1532 lexer.begin_token();
1533
1534 let mut store = TokenStore::new(lexer.source_text(), lexer.source_name());
1535 let mut sink = TokenSink::new(&mut store);
1536 let id = lexer
1537 .emit_with_stop(&mut sink, 1, DEFAULT_CHANNEL, 0, Some("<EOF>".to_owned()))
1538 .expect("test token should fit");
1539 let token = sink.view(id).expect("emitted token should exist");
1540
1541 assert_eq!(token.start(), 1);
1542 assert_eq!(token.stop(), 0);
1543 assert_eq!(token.text(), "<EOF>");
1544 assert_eq!(token.byte_span(), 2..2);
1545 }
1546
1547 #[test]
1548 fn emit_implicit_text_uses_utf8_byte_span_for_non_ascii_input() {
1549 let data = RecognizerData::new(
1550 "T",
1551 Vocabulary::new(
1552 std::iter::empty::<Option<&str>>(),
1553 std::iter::empty::<Option<&str>>(),
1554 std::iter::empty::<Option<&str>>(),
1555 ),
1556 );
1557 let mut lexer = BaseLexer::new(InputStream::new("β"), data);
1558 lexer.begin_token();
1559 lexer.consume_char();
1560
1561 let mut store = TokenStore::new(lexer.source_text(), lexer.source_name());
1562 let mut sink = TokenSink::new(&mut store);
1563 let id = lexer
1564 .emit(&mut sink, 1, DEFAULT_CHANNEL, None)
1565 .expect("test token should fit");
1566 let token = sink.view(id).expect("emitted token should exist");
1567
1568 assert_eq!(token.start(), 0);
1569 assert_eq!(token.stop(), 0);
1570 assert_eq!(token.text(), "β");
1571 assert_eq!(token.byte_span(), 0..2);
1572 }
1573
1574 #[test]
1575 fn emit_falls_back_to_explicit_text_without_shareable_source() {
1576 let data = RecognizerData::new(
1577 "T",
1578 Vocabulary::new(
1579 std::iter::empty::<Option<&str>>(),
1580 std::iter::empty::<Option<&str>>(),
1581 std::iter::empty::<Option<&str>>(),
1582 ),
1583 );
1584 let mut lexer = BaseLexer::new(UnsharedInput(InputStream::new("β")), data);
1585 lexer.begin_token();
1586 lexer.consume_char();
1587
1588 let mut store = TokenStore::new(lexer.source_text(), lexer.source_name());
1589 let mut sink = TokenSink::new(&mut store);
1590 let id = lexer
1591 .emit(&mut sink, 1, DEFAULT_CHANNEL, None)
1592 .expect("unshared input should emit explicit token text");
1593 let token = sink.view(id).expect("emitted token should exist");
1594
1595 assert_eq!(token.text(), "β");
1596 assert_eq!(token.byte_span(), 0..2);
1597 }
1598
1599 #[test]
1600 fn position_commits_and_rewinds_preserve_line_and_column() {
1601 let data = RecognizerData::new(
1602 "T",
1603 Vocabulary::new(
1604 std::iter::empty::<Option<&str>>(),
1605 std::iter::empty::<Option<&str>>(),
1606 std::iter::empty::<Option<&str>>(),
1607 ),
1608 );
1609 let mut lexer = BaseLexer::new(InputStream::new("ab\nγd"), data);
1610 lexer.begin_token();
1611
1612 lexer.commit_position(0, 5);
1613 assert_eq!(lexer.input().index(), 5);
1614 assert_eq!((lexer.line(), lexer.column()), (2, 2));
1615 assert_eq!(lexer.column_at(2), 2);
1616 assert_eq!(lexer.column_at(4), 1);
1617
1618 lexer.reset_accept_position(3);
1619 assert_eq!(lexer.input().index(), 3);
1620 assert_eq!((lexer.line(), lexer.column()), (2, 0));
1621 }
1622
1623 #[test]
1624 fn custom_stream_position_commit_replays_without_fast_path_methods() {
1625 let data = RecognizerData::new(
1626 "T",
1627 Vocabulary::new(
1628 std::iter::empty::<Option<&str>>(),
1629 std::iter::empty::<Option<&str>>(),
1630 std::iter::empty::<Option<&str>>(),
1631 ),
1632 );
1633 let mut lexer = BaseLexer::new(UnsharedInput(InputStream::new("a\nb")), data);
1634 lexer.begin_token();
1635
1636 lexer.commit_position(0, 3);
1637 assert_eq!(lexer.input().index(), 3);
1638 assert_eq!((lexer.line(), lexer.column()), (2, 1));
1639 }
1640
1641 #[test]
1642 fn semantic_hook_errors_are_deduplicated_per_token_coordinate() {
1643 let data = RecognizerData::new(
1644 "T",
1645 Vocabulary::new(
1646 std::iter::empty::<Option<&str>>(),
1647 std::iter::empty::<Option<&str>>(),
1648 std::iter::empty::<Option<&str>>(),
1649 ),
1650 );
1651 let mut lexer = BaseLexer::new(InputStream::new("a"), data);
1652 lexer.begin_token();
1653 lexer.record_semantic_error(false, 3, 7);
1654 lexer.record_semantic_error(false, 3, 7);
1655
1656 let errors = lexer.drain_errors();
1657 assert_eq!(errors.len(), 1);
1658 assert_eq!(
1659 errors[0].message,
1660 "unhandled lexer semantic predicate: rule=3 index=7"
1661 );
1662
1663 lexer.begin_token();
1664 lexer.record_semantic_error(false, 3, 7);
1665 assert_eq!(
1666 lexer.drain_errors().len(),
1667 1,
1668 "deduplication resets at every token boundary, even after rewinding"
1669 );
1670 }
1671
1672 #[test]
1673 fn set_input_stream_replaces_input_and_resets_transient_state() {
1674 let data = RecognizerData::new(
1675 "T",
1676 Vocabulary::new(
1677 std::iter::empty::<Option<&str>>(),
1678 std::iter::empty::<Option<&str>>(),
1679 std::iter::empty::<Option<&str>>(),
1680 ),
1681 );
1682 let mut lexer = BaseLexer::new(InputStream::new("old"), data);
1683 lexer.consume_char();
1684 lexer.set_mode(7);
1685 lexer.push_mode(9);
1686 lexer.set_type(3);
1687 lexer.record_error(1, 0, "stale");
1688
1689 lexer.set_input_stream(InputStream::with_source_name("new", "replacement"));
1690
1691 assert_eq!(lexer.input().index(), 0);
1692 assert_eq!(lexer.input().size(), 3);
1693 assert_eq!(lexer.source_name(), "replacement");
1694 assert_eq!(lexer.source_text().as_deref(), Some("new"));
1695 assert_eq!(lexer.mode(), DEFAULT_MODE);
1696 assert_eq!(lexer.token_type(), INVALID_TOKEN_TYPE);
1697 assert_eq!((lexer.line(), lexer.column()), (1, 0));
1698 assert!(!lexer.hit_eof());
1699 assert!(lexer.drain_errors().is_empty());
1700 assert!(lexer.pop_mode().is_none());
1701 }
1702
1703 #[test]
1704 fn clear_dfa_invalidates_all_lexers_sharing_the_cache() {
1705 let atn = Box::leak(Box::new(LexerAtn::new(1)));
1706 let data = || {
1707 RecognizerData::new(
1708 "T",
1709 Vocabulary::new(
1710 std::iter::empty::<Option<&str>>(),
1711 std::iter::empty::<Option<&str>>(),
1712 std::iter::empty::<Option<&str>>(),
1713 ),
1714 )
1715 };
1716 let first = BaseLexer::new(InputStream::new("a"), data()).with_shared_dfa(atn);
1717 let second = BaseLexer::new(InputStream::new("a"), data()).with_shared_dfa(atn);
1718 let state = first.lexer_dfa_state(LexerDfaKey::new(Vec::new()), Some(1));
1719 first.record_lexer_dfa_edge(state, i32::from(b'a'), state);
1720
1721 assert!(!second.lexer_dfa_string().is_empty());
1722 first.clear_dfa();
1723 assert!(first.lexer_dfa_string().is_empty());
1724 assert!(second.lexer_dfa_string().is_empty());
1725 }
1726}