1use std::cell::{RefCell, RefMut};
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::{
10 ContextArena, ContextId, EMPTY_CONTEXT, PredictionFxHasher, PredictionWorkspace,
11};
12use crate::recognizer::{Recognizer, RecognizerData};
13use crate::token::{
14 DEFAULT_CHANNEL, INVALID_TOKEN_TYPE, TokenId, TokenSink, TokenSourceError, TokenSpec,
15 TokenStoreError,
16};
17
18#[allow(clippy::disallowed_types)]
19type FxHashMap<K, V> = HashMap<K, V, BuildHasherDefault<PredictionFxHasher>>;
20
21pub const SKIP: i32 = -3;
22pub const MORE: i32 = -2;
23pub const DEFAULT_MODE: i32 = 0;
24
25#[derive(Clone, Copy, Debug, Eq, PartialEq)]
26pub struct LexerMode(pub i32);
27
28#[derive(Clone, Copy, Debug, Eq, PartialEq)]
35pub struct LexerCustomAction {
36 rule_index: i32,
37 action_index: i32,
38 position: usize,
39}
40
41impl LexerCustomAction {
42 pub const fn new(rule_index: i32, action_index: i32, position: usize) -> Self {
44 Self {
45 rule_index,
46 action_index,
47 position,
48 }
49 }
50
51 pub const fn rule_index(self) -> i32 {
53 self.rule_index
54 }
55
56 pub const fn action_index(self) -> i32 {
58 self.action_index
59 }
60
61 pub const fn position(self) -> usize {
63 self.position
64 }
65}
66
67#[derive(Clone, Copy, Debug, Eq, PartialEq)]
69pub struct LexerPredicate {
70 rule_index: usize,
71 pred_index: usize,
72 position: usize,
73}
74
75impl LexerPredicate {
76 pub const fn new(rule_index: usize, pred_index: usize, position: usize) -> Self {
78 Self {
79 rule_index,
80 pred_index,
81 position,
82 }
83 }
84
85 pub const fn rule_index(self) -> usize {
87 self.rule_index
88 }
89
90 pub const fn pred_index(self) -> usize {
92 self.pred_index
93 }
94
95 pub const fn position(self) -> usize {
97 self.position
98 }
99}
100
101#[derive(Debug)]
106enum LexerRef<'a, I>
107where
108 I: CharStream,
109{
110 Shared(&'a BaseLexer<I>),
111 Mut(&'a mut BaseLexer<I>),
112}
113
114impl<I> LexerRef<'_, I>
115where
116 I: CharStream,
117{
118 const fn get(&self) -> &BaseLexer<I> {
119 match self {
120 LexerRef::Shared(lexer) => lexer,
121 LexerRef::Mut(lexer) => lexer,
122 }
123 }
124}
125
126#[derive(Debug)]
128pub struct LexerSemCtx<'a, I>
129where
130 I: CharStream,
131{
132 lexer: LexerRef<'a, I>,
133 rule_index: usize,
134 coordinate_index: usize,
135 position: usize,
136}
137
138impl<'a, I> LexerSemCtx<'a, I>
139where
140 I: CharStream,
141{
142 pub(crate) const fn new(
143 lexer: &'a BaseLexer<I>,
144 rule_index: usize,
145 coordinate_index: usize,
146 position: usize,
147 ) -> Self {
148 Self {
149 lexer: LexerRef::Shared(lexer),
150 rule_index,
151 coordinate_index,
152 position,
153 }
154 }
155
156 pub(crate) const fn new_mut(
159 lexer: &'a mut BaseLexer<I>,
160 rule_index: usize,
161 coordinate_index: usize,
162 position: usize,
163 ) -> Self {
164 Self {
165 lexer: LexerRef::Mut(lexer),
166 rule_index,
167 coordinate_index,
168 position,
169 }
170 }
171
172 #[must_use]
174 pub const fn rule_index(&self) -> usize {
175 self.rule_index
176 }
177
178 #[must_use]
180 pub const fn coordinate_index(&self) -> usize {
181 self.coordinate_index
182 }
183
184 #[must_use]
186 pub const fn position(&self) -> usize {
187 self.position
188 }
189
190 #[must_use]
192 pub fn mode(&self) -> i32 {
193 self.lexer.get().mode()
194 }
195
196 #[must_use]
198 pub const fn column(&self) -> usize {
199 self.lexer.get().column()
200 }
201
202 #[must_use]
204 pub fn position_column(&self) -> usize {
205 self.lexer.get().column_at(self.position)
206 }
207
208 #[must_use]
210 pub const fn token_start_column(&self) -> usize {
211 self.lexer.get().token_start_column()
212 }
213
214 #[must_use]
216 pub fn text_so_far(&self) -> String {
217 self.lexer.get().token_text_until(self.position)
218 }
219
220 pub fn la(&mut self, offset: isize) -> i32 {
226 match &mut self.lexer {
227 LexerRef::Shared(lexer) => lexer.lookahead_at(self.position, offset),
228 LexerRef::Mut(lexer) => lexer.input_mut().la(offset),
229 }
230 }
231
232 #[must_use]
234 pub const fn token_start(&self) -> usize {
235 self.lexer.get().token_start()
236 }
237
238 #[must_use]
240 pub const fn token_type(&self) -> i32 {
241 self.lexer.get().token_type()
242 }
243
244 #[must_use]
246 pub const fn channel(&self) -> i32 {
247 self.lexer.get().channel()
248 }
249
250 pub const fn set_type(&mut self, token_type: i32) -> bool {
253 match &mut self.lexer {
254 LexerRef::Mut(lexer) => {
255 lexer.set_type(token_type);
256 true
257 }
258 LexerRef::Shared(_) => false,
259 }
260 }
261
262 pub const fn set_channel(&mut self, channel: i32) -> bool {
265 match &mut self.lexer {
266 LexerRef::Mut(lexer) => {
267 lexer.set_channel(channel);
268 true
269 }
270 LexerRef::Shared(_) => false,
271 }
272 }
273
274 pub fn consume(&mut self) -> bool {
277 match &mut self.lexer {
278 LexerRef::Mut(lexer) => {
279 lexer.consume_char();
280 true
281 }
282 LexerRef::Shared(_) => false,
283 }
284 }
285
286 pub const fn skip(&mut self) -> bool {
288 self.set_type(SKIP)
289 }
290
291 pub const fn more(&mut self) -> bool {
294 self.set_type(MORE)
295 }
296
297 pub fn reset_accept_position(&mut self, index: usize) -> bool {
299 match &mut self.lexer {
300 LexerRef::Mut(lexer) => {
301 lexer.reset_accept_position(index);
302 true
303 }
304 LexerRef::Shared(_) => false,
305 }
306 }
307
308 pub fn set_token_start(&mut self, index: usize) -> bool {
314 match &mut self.lexer {
315 LexerRef::Mut(lexer) => lexer.set_token_start(index),
316 LexerRef::Shared(_) => false,
317 }
318 }
319
320 pub fn enqueue_token(&mut self, token_type: i32, stop: usize) -> bool {
326 let channel = self.channel();
327 self.enqueue_token_with_channel(token_type, channel, stop)
328 }
329
330 pub fn enqueue_token_with_channel(
333 &mut self,
334 token_type: i32,
335 channel: i32,
336 stop: usize,
337 ) -> bool {
338 match &mut self.lexer {
339 LexerRef::Mut(lexer) => {
340 lexer.enqueue_token(token_type, channel, stop, None);
341 true
342 }
343 LexerRef::Shared(_) => false,
344 }
345 }
346
347 pub fn set_mode(&mut self, mode: i32) -> bool {
354 match &mut self.lexer {
355 LexerRef::Mut(lexer) => {
356 lexer.set_mode(mode);
357 true
358 }
359 LexerRef::Shared(_) => false,
360 }
361 }
362
363 pub fn push_mode(&mut self, mode: i32) -> bool {
366 match &mut self.lexer {
367 LexerRef::Mut(lexer) => {
368 lexer.push_mode(mode);
369 true
370 }
371 LexerRef::Shared(_) => false,
372 }
373 }
374
375 pub fn pop_mode(&mut self) -> Option<i32> {
379 match &mut self.lexer {
380 LexerRef::Mut(lexer) => lexer.pop_mode(),
381 LexerRef::Shared(_) => None,
382 }
383 }
384}
385
386#[derive(Debug)]
394pub struct LexerLifecycleCtx<'a, I>
395where
396 I: CharStream,
397{
398 lexer: &'a mut BaseLexer<I>,
399 accept_position: Option<usize>,
400}
401
402impl<'a, I> LexerLifecycleCtx<'a, I>
403where
404 I: CharStream,
405{
406 pub(crate) const fn new(lexer: &'a mut BaseLexer<I>, accept_position: Option<usize>) -> Self {
407 Self {
408 lexer,
409 accept_position,
410 }
411 }
412
413 #[must_use]
418 pub const fn accept_position(&self) -> Option<usize> {
419 self.accept_position
420 }
421
422 #[must_use]
424 pub fn input_position(&self) -> usize {
425 self.lexer.input().index()
426 }
427
428 #[must_use]
430 pub const fn mode(&self) -> i32 {
431 self.lexer.mode
432 }
433
434 #[must_use]
436 pub const fn line(&self) -> usize {
437 self.lexer.line()
438 }
439
440 #[must_use]
442 pub const fn column(&self) -> usize {
443 self.lexer.column()
444 }
445
446 #[must_use]
448 pub const fn token_start(&self) -> usize {
449 self.lexer.token_start()
450 }
451
452 #[must_use]
454 pub const fn token_start_line(&self) -> usize {
455 self.lexer.token_start_line()
456 }
457
458 #[must_use]
460 pub const fn token_start_column(&self) -> usize {
461 self.lexer.token_start_column()
462 }
463
464 #[must_use]
466 pub const fn token_type(&self) -> i32 {
467 self.lexer.token_type()
468 }
469
470 #[must_use]
472 pub const fn channel(&self) -> i32 {
473 self.lexer.channel()
474 }
475
476 #[must_use]
478 pub fn pending_token_count(&self) -> usize {
479 self.lexer.pending_tokens.len()
480 }
481
482 #[must_use]
484 pub fn token_text(&self) -> String {
485 self.lexer.token_text()
486 }
487
488 #[must_use]
492 pub fn accepted_text(&self) -> Option<String> {
493 self.accept_position
494 .map(|position| self.lexer.token_text_until(position))
495 }
496
497 pub fn la(&mut self, offset: isize) -> i32 {
500 self.lexer.la(offset)
501 }
502
503 pub fn consume(&mut self) {
505 self.lexer.consume_char();
506 }
507
508 pub const fn set_type(&mut self, token_type: i32) {
510 self.lexer.set_type(token_type);
511 }
512
513 pub const fn set_channel(&mut self, channel: i32) {
515 self.lexer.set_channel(channel);
516 }
517
518 pub const fn skip(&mut self) {
520 self.lexer.skip();
521 }
522
523 pub const fn more(&mut self) {
525 self.lexer.more();
526 }
527
528 pub fn reset_accept_position(&mut self, index: usize) {
530 self.lexer.reset_accept_position(index);
531 }
532
533 pub fn set_token_start(&mut self, index: usize) -> bool {
535 self.lexer.set_token_start(index)
536 }
537
538 pub fn enqueue_token(&mut self, token_type: i32, stop: usize) {
540 self.enqueue_token_with_channel(token_type, self.channel(), stop);
541 }
542
543 pub fn enqueue_token_with_channel(&mut self, token_type: i32, channel: i32, stop: usize) {
545 self.lexer.enqueue_token(token_type, channel, stop, None);
546 }
547
548 pub fn set_mode(&mut self, mode: i32) {
550 self.lexer.set_mode(mode);
551 }
552
553 pub fn push_mode(&mut self, mode: i32) {
555 self.lexer.push_mode(mode);
556 }
557
558 pub fn pop_mode(&mut self) -> Option<i32> {
560 self.lexer.pop_mode()
561 }
562}
563
564pub trait Lexer: Recognizer {
565 fn mode(&self) -> i32;
566 fn set_mode(&mut self, mode: i32);
567 fn push_mode(&mut self, mode: i32);
568 fn pop_mode(&mut self) -> Option<i32>;
569}
570
571#[derive(Clone, Debug)]
572pub struct BaseLexer<I> {
573 input: I,
574 data: RecognizerData,
575 has_source_text: bool,
576 mode: i32,
577 mode_stack: Vec<i32>,
578 token_type: i32,
579 channel: i32,
580 token_start: usize,
581 token_start_line: usize,
582 token_start_column: usize,
583 line: usize,
584 column: usize,
585 hit_eof: bool,
586 force_interpreted: bool,
587 errors: RefCell<Vec<TokenSourceError>>,
588 semantic_error_coordinates: RefCell<BTreeSet<(u8, usize, usize, usize)>>,
589 pending_tokens: VecDeque<TokenSpec>,
590 dfa_cache: Rc<RefCell<LexerDfaCache>>,
591}
592
593#[derive(Debug, Default)]
601struct LexerDfaCache {
602 prediction: LexerPredictionStore,
603 state_numbers: FxHashMap<LexerDfaKey, usize>,
604 accept_predictions: FxHashMap<usize, i32>,
605 edges: BTreeSet<LexerDfaEdge>,
609 cached_states: Vec<Option<Rc<LexerDfaCachedState>>>,
611 dense_edges: Vec<Option<Box<DenseEdgeRow>>>,
616 sparse_edges: FxHashMap<(usize, i32), LexerDfaCachedTransition>,
618 mode_starts: FxHashMap<i32, usize>,
619}
620
621#[derive(Debug, Default)]
624pub(crate) struct LexerPredictionStore {
625 pub(crate) contexts: LexerContextArena,
626 pub(crate) workspace: PredictionWorkspace,
627}
628
629#[repr(transparent)]
631#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
632pub(crate) struct LexerContextId(u32);
633
634pub(crate) const EMPTY_LEXER_CONTEXT: LexerContextId = LexerContextId(0);
635
636#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
642pub(crate) enum LexerContextNode {
643 Empty,
644 Singleton {
645 parent: LexerContextId,
646 return_state: usize,
647 },
648 Union {
649 left: LexerContextId,
650 right: LexerContextId,
651 },
652}
653
654#[derive(Clone, Copy, Debug)]
655struct LexerContextRecord {
656 node: LexerContextNode,
657 path_set: ContextId,
658}
659
660#[derive(Debug)]
662pub(crate) struct LexerContextArena {
663 records: Vec<LexerContextRecord>,
664 ids: FxHashMap<LexerContextNode, LexerContextId>,
665 path_sets: ContextArena,
666}
667
668impl LexerContextArena {
669 pub(crate) fn new() -> Self {
670 let mut ids = FxHashMap::default();
671 ids.insert(LexerContextNode::Empty, EMPTY_LEXER_CONTEXT);
672 Self {
673 records: vec![LexerContextRecord {
674 node: LexerContextNode::Empty,
675 path_set: EMPTY_CONTEXT,
676 }],
677 ids,
678 path_sets: ContextArena::new(),
679 }
680 }
681
682 pub(crate) fn singleton(
683 &mut self,
684 parent: LexerContextId,
685 return_state: usize,
686 ) -> LexerContextId {
687 self.assert_valid(parent);
688 let node = LexerContextNode::Singleton {
689 parent,
690 return_state,
691 };
692 if let Some(&context) = self.ids.get(&node) {
693 return context;
694 }
695 let path_set = self
696 .path_sets
697 .singleton(self.record(parent).path_set, return_state);
698 self.intern(node, path_set)
699 }
700
701 pub(crate) fn merge(
702 &mut self,
703 left: LexerContextId,
704 right: LexerContextId,
705 workspace: &mut PredictionWorkspace,
706 ) -> LexerContextId {
707 self.assert_valid(left);
708 self.assert_valid(right);
709 if left == right {
710 return left;
711 }
712 let left_set = self.record(left).path_set;
713 let right_set = self.record(right).path_set;
714 let path_set = self.path_sets.merge(left_set, right_set, false, workspace);
715 if path_set == left_set {
716 return left;
717 }
718 let node = LexerContextNode::Union { left, right };
719 if let Some(&context) = self.ids.get(&node) {
720 return context;
721 }
722 self.intern(node, path_set)
723 }
724
725 pub(crate) fn node(&self, context: LexerContextId) -> LexerContextNode {
726 self.record(context).node
727 }
728
729 #[cfg(test)]
730 pub(crate) const fn len(&self) -> usize {
731 self.records.len()
732 }
733
734 fn intern(&mut self, node: LexerContextNode, path_set: ContextId) -> LexerContextId {
735 let context = LexerContextId(
736 u32::try_from(self.records.len()).expect("lexer context arena must fit in u32"),
737 );
738 self.records.push(LexerContextRecord { node, path_set });
739 self.ids.insert(node, context);
740 context
741 }
742
743 fn record(&self, context: LexerContextId) -> &LexerContextRecord {
744 self.assert_valid(context);
745 &self.records[usize::try_from(context.0).expect("u32 lexer context ID fits in usize")]
746 }
747
748 fn assert_valid(&self, context: LexerContextId) {
749 assert!(
750 usize::try_from(context.0).is_ok_and(|index| index < self.records.len()),
751 "lexer context ID does not belong to this store"
752 );
753 }
754}
755
756impl Default for LexerContextArena {
757 fn default() -> Self {
758 Self::new()
759 }
760}
761
762const DENSE_EDGE_SYMBOLS: usize = 128;
764
765type DenseEdgeRow = [LexerDfaCachedTransition; DENSE_EDGE_SYMBOLS];
766
767const EMPTY_DENSE_EDGE: LexerDfaCachedTransition = LexerDfaCachedTransition {
770 target_state: usize::MAX,
771 position_delta: 0,
772};
773
774thread_local! {
775 static SHARED_LEXER_DFA_CACHES: RefCell<HashMap<usize, Rc<RefCell<LexerDfaCache>>>> =
778 RefCell::new(HashMap::new());
779}
780
781#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
783pub(crate) struct LexerDfaKey {
784 configs: Vec<LexerDfaConfigKey>,
785}
786
787impl LexerDfaKey {
788 pub(crate) fn new(mut configs: Vec<LexerDfaConfigKey>) -> Self {
789 configs.sort_unstable();
790 Self { configs }
791 }
792}
793
794#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
796pub(crate) struct LexerDfaConfigKey {
797 pub(crate) state: usize,
798 pub(crate) alt_rule_index: Option<usize>,
799 pub(crate) consumed_eof: bool,
800 pub(crate) passed_non_greedy: bool,
801 pub(crate) context: LexerContextId,
802 pub(crate) actions: Vec<LexerDfaActionKey>,
803}
804
805#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
806pub(crate) struct LexerDfaActionKey {
807 pub(crate) action_index: usize,
808 pub(crate) position_delta: usize,
809 pub(crate) rule_index: usize,
810}
811
812impl LexerDfaConfigKey {
813 pub(crate) const fn new(
814 state: usize,
815 alt_rule_index: Option<usize>,
816 consumed_eof: bool,
817 passed_non_greedy: bool,
818 context: LexerContextId,
819 actions: Vec<LexerDfaActionKey>,
820 ) -> Self {
821 Self {
822 state,
823 alt_rule_index,
824 consumed_eof,
825 passed_non_greedy,
826 context,
827 actions,
828 }
829 }
830}
831
832#[derive(Clone, Copy, Debug)]
833pub(crate) struct LexerDfaCachedTransition {
834 pub(crate) target_state: usize,
835 pub(crate) position_delta: usize,
836}
837
838#[derive(Clone, Debug)]
839pub(crate) struct LexerDfaCachedAccept {
840 pub(crate) position_delta: usize,
841 pub(crate) rule_index: usize,
842 pub(crate) consumed_eof: bool,
843 pub(crate) actions: Vec<LexerDfaActionKey>,
844}
845
846#[derive(Clone, Debug)]
847pub(crate) struct LexerDfaCachedState {
848 pub(crate) has_semantic_context: bool,
849 pub(crate) configs: Vec<LexerDfaConfigKey>,
850 pub(crate) accept: Option<LexerDfaCachedAccept>,
851}
852
853#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
856struct LexerDfaEdge {
857 from: usize,
858 symbol: i32,
859 to: usize,
860}
861
862impl<I> BaseLexer<I>
863where
864 I: CharStream,
865{
866 pub fn new(input: I, data: RecognizerData) -> Self {
867 let has_source_text = input.source_text().is_some();
868 Self {
869 input,
870 data,
871 has_source_text,
872 mode: DEFAULT_MODE,
873 mode_stack: Vec::new(),
874 token_type: INVALID_TOKEN_TYPE,
875 channel: DEFAULT_CHANNEL,
876 token_start: 0,
877 token_start_line: 1,
878 token_start_column: 0,
879 line: 1,
880 column: 0,
881 hit_eof: false,
882 force_interpreted: false,
883 errors: RefCell::new(Vec::new()),
884 semantic_error_coordinates: RefCell::new(BTreeSet::new()),
885 pending_tokens: VecDeque::new(),
886 dfa_cache: Rc::new(RefCell::new(LexerDfaCache::default())),
887 }
888 }
889
890 pub fn reset(&mut self) {
897 self.input.seek(0);
898 self.mode = DEFAULT_MODE;
899 self.mode_stack.clear();
900 self.token_type = INVALID_TOKEN_TYPE;
901 self.channel = DEFAULT_CHANNEL;
902 self.token_start = 0;
903 self.token_start_line = 1;
904 self.token_start_column = 0;
905 self.line = 1;
906 self.column = 0;
907 self.hit_eof = false;
908 self.errors.get_mut().clear();
909 self.semantic_error_coordinates.get_mut().clear();
910 self.pending_tokens.clear();
911 }
912
913 pub fn set_input_stream(&mut self, input: I) {
918 self.input = input;
919 self.has_source_text = self.input.source_text().is_some();
920 self.reset();
921 }
922
923 #[must_use]
933 pub fn with_shared_dfa(mut self, atn: &'static LexerAtn) -> Self {
934 let ptr: *const LexerAtn = atn;
935 let key = ptr as usize;
936 self.dfa_cache = SHARED_LEXER_DFA_CACHES
937 .with(|caches| Rc::clone(caches.borrow_mut().entry(key).or_insert_with(Rc::default)));
938 self
939 }
940
941 pub fn clear_dfa(&self) {
947 let mut cache = self.dfa_cache.borrow_mut();
948 let prediction = std::mem::take(&mut cache.prediction);
951 *cache = LexerDfaCache {
952 prediction,
953 ..LexerDfaCache::default()
954 };
955 }
956
957 pub const fn input(&self) -> &I {
958 &self.input
959 }
960
961 pub const fn input_mut(&mut self) -> &mut I {
962 &mut self.input
963 }
964
965 pub fn begin_token(&mut self) {
968 self.semantic_error_coordinates.get_mut().clear();
969 self.token_type = INVALID_TOKEN_TYPE;
970 self.channel = DEFAULT_CHANNEL;
971 self.token_start = self.input.index();
972 self.token_start_line = self.line;
973 self.token_start_column = self.column;
974 }
975
976 pub const fn token_start(&self) -> usize {
978 self.token_start
979 }
980
981 pub const fn token_start_line(&self) -> usize {
983 self.token_start_line
984 }
985
986 pub const fn token_start_column(&self) -> usize {
988 self.token_start_column
989 }
990
991 pub const fn token_type(&self) -> i32 {
993 self.token_type
994 }
995
996 pub const fn set_type(&mut self, token_type: i32) {
998 self.token_type = token_type;
999 }
1000
1001 pub const fn channel(&self) -> i32 {
1003 self.channel
1004 }
1005
1006 pub const fn set_channel(&mut self, channel: i32) {
1008 self.channel = channel;
1009 }
1010
1011 pub const fn skip(&mut self) {
1013 self.set_type(SKIP);
1014 }
1015
1016 pub const fn more(&mut self) {
1018 self.set_type(MORE);
1019 }
1020
1021 pub fn la(&mut self, offset: isize) -> i32 {
1024 self.input.la(offset)
1025 }
1026
1027 fn lookahead_at(&self, position: usize, offset: isize) -> i32 {
1028 if offset == 0 {
1029 return 0;
1030 }
1031 let absolute = if offset > 0 {
1032 position.checked_add((offset - 1).cast_unsigned())
1033 } else {
1034 offset
1035 .checked_neg()
1036 .and_then(|distance| usize::try_from(distance).ok())
1037 .and_then(|distance| position.checked_sub(distance))
1038 };
1039 let Some(index) = absolute.filter(|index| *index < self.input.size()) else {
1040 return EOF;
1041 };
1042 if let Some(symbol) = self.input.symbol_at(index) {
1043 return symbol;
1044 }
1045 self.input
1046 .text(TextInterval::new(index, index))
1047 .chars()
1048 .next()
1049 .map_or(EOF, |ch| u32::from(ch).cast_signed())
1050 }
1051
1052 pub fn consume_char(&mut self) {
1059 let la = self.input.la(1);
1060 if la == EOF {
1061 return;
1062 }
1063 self.input.consume();
1064 if char::from_u32(la.cast_unsigned()) == Some('\n') {
1065 self.line += 1;
1066 self.column = 0;
1067 } else {
1068 self.column += 1;
1069 }
1070 }
1071
1072 pub(crate) fn commit_position(&mut self, start: usize, target: usize) {
1075 self.reposition_from(start, self.line, self.column, target);
1076 }
1077
1078 fn reposition_from(&mut self, start: usize, line: usize, column: usize, target: usize) {
1079 let start = start.min(self.input.size());
1080 let target = target.max(start).min(self.input.size());
1081 if let Some(summary) = self.input.position_summary(start, target) {
1082 self.input.seek(target);
1083 (self.line, self.column) = summary.apply(line, column);
1084 #[cfg(feature = "perf-counters")]
1085 crate::perf::record_lexer_bulk_commit(target - start);
1086 return;
1087 }
1088
1089 self.input.seek(start);
1090 self.line = line;
1091 self.column = column;
1092 #[cfg(feature = "perf-counters")]
1093 let before = self.input.index();
1094 while self.input.index() < target && self.input.la(1) != EOF {
1095 self.consume_char();
1096 }
1097 #[cfg(feature = "perf-counters")]
1098 crate::perf::record_lexer_scalar_replay(self.input.index().saturating_sub(before));
1099 }
1100
1101 pub fn reset_accept_position(&mut self, index: usize) {
1108 let target = index.max(self.token_start);
1109 self.reposition_from(
1110 self.token_start,
1111 self.token_start_line,
1112 self.token_start_column,
1113 target,
1114 );
1115 }
1116
1117 pub fn set_token_start(&mut self, index: usize) -> bool {
1123 if index < self.token_start || index > self.input.index() {
1124 return false;
1125 }
1126 let (line, column) = self.position_at(index);
1127 self.token_start = index;
1128 self.token_start_line = line;
1129 self.token_start_column = column;
1130 true
1131 }
1132
1133 pub fn emit(
1141 &self,
1142 sink: &mut TokenSink<'_>,
1143 token_type: i32,
1144 channel: i32,
1145 text: Option<String>,
1146 ) -> Result<TokenId, TokenStoreError> {
1147 let stop = self.input.index().checked_sub(1).unwrap_or(usize::MAX);
1148 self.emit_with_stop(sink, token_type, channel, stop, text)
1149 }
1150
1151 pub fn emit_with_stop(
1157 &self,
1158 sink: &mut TokenSink<'_>,
1159 token_type: i32,
1160 channel: i32,
1161 stop: usize,
1162 text: Option<String>,
1163 ) -> Result<TokenId, TokenStoreError> {
1164 sink.push(self.token_spec_with_stop(token_type, channel, stop, text))
1165 }
1166
1167 fn token_spec_with_stop(
1168 &self,
1169 token_type: i32,
1170 channel: i32,
1171 stop: usize,
1172 text: Option<String>,
1173 ) -> TokenSpec {
1174 let text = text.or_else(|| {
1175 if stop == usize::MAX {
1176 Some("<EOF>".to_owned())
1177 } else {
1178 None
1179 }
1180 });
1181 let source_interval = if self.has_source_text
1182 && text.is_none()
1183 && stop != usize::MAX
1184 && self.token_start <= stop
1185 {
1186 self.input
1187 .byte_interval(TextInterval::new(self.token_start, stop))
1188 } else {
1189 None
1190 };
1191 let text = text.or_else(|| {
1192 source_interval
1193 .is_none()
1194 .then(|| self.input.text(TextInterval::new(self.token_start, stop)))
1195 });
1196 let (start_byte, stop_byte) = source_interval
1197 .or_else(|| self.token_byte_span(stop))
1198 .unwrap_or((self.token_start, self.token_start));
1199 TokenSpec {
1200 token_type,
1201 channel,
1202 start: self.token_start,
1203 stop,
1204 start_byte,
1205 stop_byte,
1206 line: self.token_start_line,
1207 column: self.token_start_column,
1208 text,
1209 source_backed: source_interval.is_some(),
1210 }
1211 }
1212
1213 pub fn enqueue_token(
1219 &mut self,
1220 token_type: i32,
1221 channel: i32,
1222 stop: usize,
1223 text: Option<String>,
1224 ) {
1225 let token = self.token_spec_with_stop(token_type, channel, stop, text);
1226 self.pending_tokens.push_back(token);
1227 }
1228
1229 pub(crate) fn emit_pending_token(
1230 &mut self,
1231 sink: &mut TokenSink<'_>,
1232 ) -> Result<Option<TokenId>, TokenStoreError> {
1233 self.pending_tokens
1234 .pop_front()
1235 .map(|token| sink.push(token))
1236 .transpose()
1237 }
1238
1239 pub(crate) fn emit_or_enqueue_with_stop(
1240 &mut self,
1241 sink: &mut TokenSink<'_>,
1242 stop: usize,
1243 text: Option<String>,
1244 ) -> Result<TokenId, TokenStoreError> {
1245 let token = self.token_spec_with_stop(self.token_type, self.channel, stop, text);
1246 self.emit_or_enqueue(sink, token)
1247 }
1248
1249 fn emit_or_enqueue(
1250 &mut self,
1251 sink: &mut TokenSink<'_>,
1252 token: TokenSpec,
1253 ) -> Result<TokenId, TokenStoreError> {
1254 if self.pending_tokens.is_empty() {
1255 return sink.push(token);
1256 }
1257 self.pending_tokens.push_back(token);
1258 self.emit_pending_token(sink)?
1259 .ok_or_else(|| unreachable!("the pending-token queue was just populated"))
1260 }
1261
1262 pub fn token_text(&self) -> String {
1265 self.token_text_until(self.input.index())
1266 }
1267
1268 pub fn token_text_until(&self, stop_exclusive: usize) -> String {
1276 if stop_exclusive <= self.token_start {
1277 return String::new();
1278 }
1279 self.input
1280 .text(TextInterval::new(self.token_start, stop_exclusive - 1))
1281 }
1282
1283 pub fn column_at(&self, position: usize) -> usize {
1286 self.position_at(position).1
1287 }
1288
1289 fn position_at(&self, position: usize) -> (usize, usize) {
1290 let mut line = self.token_start_line;
1291 let mut column = self.token_start_column;
1292 if position <= self.token_start {
1293 return (line, column);
1294 }
1295 if let Some(summary) = self.input.position_summary(self.token_start, position) {
1296 return summary.apply(line, column);
1297 }
1298 for ch in self
1299 .input
1300 .text(TextInterval::new(self.token_start, position - 1))
1301 .chars()
1302 {
1303 if ch == '\n' {
1304 line += 1;
1305 column = 0;
1306 } else {
1307 column += 1;
1308 }
1309 }
1310 (line, column)
1311 }
1312
1313 pub fn eof_token(&self, sink: &mut TokenSink<'_>) -> Result<TokenId, TokenStoreError> {
1315 sink.push(self.eof_token_spec())
1316 }
1317
1318 pub(crate) fn emit_eof_or_pending(
1319 &mut self,
1320 sink: &mut TokenSink<'_>,
1321 ) -> Result<TokenId, TokenStoreError> {
1322 let token = self.eof_token_spec();
1323 self.emit_or_enqueue(sink, token)
1324 }
1325
1326 fn eof_token_spec(&self) -> TokenSpec {
1327 let byte_offset = self.eof_byte_offset().unwrap_or_else(|| self.input.index());
1328 TokenSpec::eof(self.input.index(), byte_offset, self.line, self.column)
1329 }
1330
1331 fn eof_byte_offset(&self) -> Option<usize> {
1332 self.byte_offset_at(self.input.index())
1333 }
1334
1335 fn token_byte_span(&self, stop: usize) -> Option<(usize, usize)> {
1336 if stop != usize::MAX && self.token_start <= stop {
1337 let (start_byte, stop_byte) = self
1338 .input
1339 .byte_interval(TextInterval::new(self.token_start, stop))?;
1340 return Some((start_byte, stop_byte));
1341 }
1342 let byte_offset = self.byte_offset_at(self.token_start)?;
1343 Some((byte_offset, byte_offset))
1344 }
1345
1346 fn byte_offset_at(&self, index: usize) -> Option<usize> {
1347 let byte_offset = if index == 0 {
1348 0
1349 } else {
1350 let previous = TextInterval::new(index - 1, index - 1);
1351 self.input.byte_interval(previous)?.1
1352 };
1353 Some(byte_offset)
1354 }
1355}
1356
1357impl<I> Recognizer for BaseLexer<I>
1358where
1359 I: CharStream,
1360{
1361 fn data(&self) -> &RecognizerData {
1362 &self.data
1363 }
1364
1365 fn data_mut(&mut self) -> &mut RecognizerData {
1366 &mut self.data
1367 }
1368}
1369
1370impl<I> Lexer for BaseLexer<I>
1371where
1372 I: CharStream,
1373{
1374 fn mode(&self) -> i32 {
1375 self.mode
1376 }
1377
1378 fn set_mode(&mut self, mode: i32) {
1379 self.mode = mode;
1380 }
1381
1382 fn push_mode(&mut self, mode: i32) {
1383 self.mode_stack.push(self.mode);
1384 self.mode = mode;
1385 }
1386
1387 fn pop_mode(&mut self) -> Option<i32> {
1388 let mode = self.mode_stack.pop()?;
1389 self.mode = mode;
1390 Some(mode)
1391 }
1392}
1393
1394impl<I> BaseLexer<I>
1395where
1396 I: CharStream,
1397{
1398 pub const fn line(&self) -> usize {
1399 self.line
1400 }
1401
1402 pub const fn column(&self) -> usize {
1403 self.column
1404 }
1405
1406 pub fn source_name(&self) -> &str {
1407 self.input.source_name()
1408 }
1409
1410 pub fn source_text(&self) -> Option<Rc<str>> {
1411 self.input.source_text()
1412 }
1413
1414 pub const fn hit_eof(&self) -> bool {
1415 self.hit_eof
1416 }
1417
1418 pub const fn set_hit_eof(&mut self, hit_eof: bool) {
1419 self.hit_eof = hit_eof;
1420 }
1421
1422 pub const fn set_force_interpreted(&mut self, force_interpreted: bool) {
1430 self.force_interpreted = force_interpreted;
1431 }
1432
1433 pub const fn force_interpreted(&self) -> bool {
1435 self.force_interpreted
1436 }
1437
1438 pub fn record_error(&self, line: usize, column: usize, message: impl Into<String>) {
1441 self.errors
1442 .borrow_mut()
1443 .push(TokenSourceError::new(line, column, message));
1444 }
1445
1446 pub fn record_semantic_error(&self, action: bool, rule_index: usize, coordinate_index: usize) {
1448 let kind = u8::from(action);
1449 if !self.semantic_error_coordinates.borrow_mut().insert((
1450 kind,
1451 rule_index,
1452 coordinate_index,
1453 self.token_start,
1454 )) {
1455 return;
1456 }
1457 let label = if action { "action" } else { "predicate" };
1458 self.record_error(
1459 self.token_start_line,
1460 self.token_start_column,
1461 format!("unhandled lexer semantic {label}: rule={rule_index} index={coordinate_index}"),
1462 );
1463 }
1464
1465 pub fn drain_errors(&mut self) -> Vec<TokenSourceError> {
1467 std::mem::take(self.errors.get_mut())
1468 }
1469
1470 pub(crate) fn lexer_prediction_store(&self) -> RefMut<'_, LexerPredictionStore> {
1473 RefMut::map(self.dfa_cache.borrow_mut(), |cache| &mut cache.prediction)
1474 }
1475
1476 pub(crate) fn reset_lexer_prediction_workspace(&self) {
1479 self.dfa_cache.borrow_mut().prediction.workspace.reset();
1480 }
1481
1482 #[cfg(test)]
1483 pub(crate) fn lexer_dfa_cache_shape(&self) -> (usize, usize, usize, usize) {
1484 let cache = self.dfa_cache.borrow();
1485 let cached_states = cache.cached_states.iter().flatten().count();
1486 let cached_transitions = cache
1487 .dense_edges
1488 .iter()
1489 .flatten()
1490 .map(|row| {
1491 row.iter()
1492 .filter(|transition| transition.target_state != usize::MAX)
1493 .count()
1494 })
1495 .sum::<usize>()
1496 + cache.sparse_edges.len();
1497 let max_configs = cache
1498 .cached_states
1499 .iter()
1500 .flatten()
1501 .map(|state| state.configs.len())
1502 .max()
1503 .unwrap_or(0);
1504 let contexts = cache.prediction.contexts.len();
1505 (cached_states, cached_transitions, max_configs, contexts)
1506 }
1507
1508 pub(crate) fn lexer_dfa_state(
1511 &self,
1512 key: LexerDfaKey,
1513 accept_prediction: Option<i32>,
1514 ) -> usize {
1515 let mut cache = self.dfa_cache.borrow_mut();
1516 let next = cache.state_numbers.len();
1517 let state = *cache.state_numbers.entry(key).or_insert(next);
1518 if let Some(prediction) = accept_prediction {
1519 cache.accept_predictions.insert(state, prediction);
1520 }
1521 state
1522 }
1523
1524 pub fn record_lexer_dfa_edge(&self, from: usize, symbol: i32, to: usize) {
1526 self.dfa_cache
1527 .borrow_mut()
1528 .edges
1529 .insert(LexerDfaEdge { from, symbol, to });
1530 }
1531
1532 pub(crate) fn cached_lexer_dfa_transition(
1533 &self,
1534 state: usize,
1535 symbol: i32,
1536 ) -> Option<LexerDfaCachedTransition> {
1537 let cache = self.dfa_cache.borrow();
1538 if let Ok(sym) = usize::try_from(symbol)
1539 && sym < DENSE_EDGE_SYMBOLS
1540 {
1541 let transition = cache.dense_edges.get(state)?.as_ref()?[sym];
1542 return (transition.target_state != usize::MAX).then_some(transition);
1543 }
1544 cache.sparse_edges.get(&(state, symbol)).copied()
1545 }
1546
1547 pub(crate) fn cache_lexer_dfa_transition(
1548 &self,
1549 state: usize,
1550 symbol: i32,
1551 transition: LexerDfaCachedTransition,
1552 ) {
1553 let mut cache = self.dfa_cache.borrow_mut();
1554 if let Ok(sym) = usize::try_from(symbol)
1555 && sym < DENSE_EDGE_SYMBOLS
1556 {
1557 if cache.dense_edges.len() <= state {
1558 cache.dense_edges.resize_with(state + 1, || None);
1559 }
1560 let row = cache.dense_edges[state]
1561 .get_or_insert_with(|| Box::new([EMPTY_DENSE_EDGE; DENSE_EDGE_SYMBOLS]));
1562 if row[sym].target_state == usize::MAX {
1564 row[sym] = transition;
1565 }
1566 return;
1567 }
1568 cache
1569 .sparse_edges
1570 .entry((state, symbol))
1571 .or_insert(transition);
1572 }
1573
1574 pub(crate) fn cached_lexer_dfa_state(&self, state: usize) -> Option<Rc<LexerDfaCachedState>> {
1575 self.dfa_cache
1576 .borrow()
1577 .cached_states
1578 .get(state)
1579 .cloned()
1580 .flatten()
1581 }
1582
1583 pub(crate) fn cache_lexer_dfa_state(&self, state: usize, cached_state: LexerDfaCachedState) {
1584 let mut cache = self.dfa_cache.borrow_mut();
1585 if cache.cached_states.len() <= state {
1586 cache.cached_states.resize_with(state + 1, || None);
1587 }
1588 cache.cached_states[state].get_or_insert_with(|| Rc::new(cached_state));
1589 }
1590
1591 pub(crate) fn cached_lexer_mode_start(&self, mode: i32) -> Option<usize> {
1592 self.dfa_cache.borrow().mode_starts.get(&mode).copied()
1593 }
1594
1595 pub(crate) fn cache_lexer_mode_start(&self, mode: i32, state: usize) {
1596 self.dfa_cache
1597 .borrow_mut()
1598 .mode_starts
1599 .entry(mode)
1600 .or_insert(state);
1601 }
1602
1603 pub fn lexer_dfa_string(&self) -> String {
1605 let mut out = String::new();
1606 let cache = self.dfa_cache.borrow();
1607 for edge in &cache.edges {
1608 let Some(label) = lexer_dfa_edge_label(edge.symbol) else {
1609 continue;
1610 };
1611 out.push_str(&self.lexer_dfa_state_string(edge.from));
1612 out.push('-');
1613 out.push_str(&label);
1614 out.push_str("->");
1615 out.push_str(&self.lexer_dfa_state_string(edge.to));
1616 out.push('\n');
1617 }
1618 out
1619 }
1620
1621 fn lexer_dfa_state_string(&self, state: usize) -> String {
1622 self.dfa_cache
1623 .borrow()
1624 .accept_predictions
1625 .get(&state)
1626 .map_or_else(
1627 || format!("s{state}"),
1628 |prediction| format!(":s{state}=>{prediction}"),
1629 )
1630 }
1631}
1632
1633fn lexer_dfa_edge_label(symbol: i32) -> Option<String> {
1634 char::from_u32(symbol.cast_unsigned()).map(|ch| format!("'{ch}'"))
1635}
1636
1637#[cfg(test)]
1638mod tests {
1639 use super::*;
1640 use crate::char_stream::InputStream;
1641 use crate::int_stream::IntStream;
1642 use crate::recognizer::RecognizerData;
1643 use crate::token::{DEFAULT_CHANNEL, Token, TokenStore};
1644 use crate::vocabulary::Vocabulary;
1645
1646 #[derive(Clone, Debug)]
1647 struct UnsharedInput(InputStream);
1648
1649 impl IntStream for UnsharedInput {
1650 fn consume(&mut self) {
1651 self.0.consume();
1652 }
1653
1654 fn la(&mut self, offset: isize) -> i32 {
1655 self.0.la(offset)
1656 }
1657
1658 fn index(&self) -> usize {
1659 self.0.index()
1660 }
1661
1662 fn seek(&mut self, index: usize) {
1663 self.0.seek(index);
1664 }
1665
1666 fn size(&self) -> usize {
1667 self.0.size()
1668 }
1669
1670 fn source_name(&self) -> &str {
1671 self.0.source_name()
1672 }
1673 }
1674
1675 impl CharStream for UnsharedInput {
1676 fn text(&self, interval: TextInterval) -> String {
1677 self.0.text(interval)
1678 }
1679
1680 fn byte_interval(&self, interval: TextInterval) -> Option<(usize, usize)> {
1681 self.0.byte_interval(interval)
1682 }
1683 }
1684
1685 #[test]
1686 fn eof_token_uses_utf8_byte_offset_after_non_ascii_input() {
1687 let data = RecognizerData::new(
1688 "T",
1689 Vocabulary::new(
1690 std::iter::empty::<Option<&str>>(),
1691 std::iter::empty::<Option<&str>>(),
1692 std::iter::empty::<Option<&str>>(),
1693 ),
1694 );
1695 let mut lexer = BaseLexer::new(InputStream::new("β"), data);
1696 lexer.consume_char();
1697
1698 let mut store = TokenStore::new(lexer.source_text(), lexer.source_name());
1699 let mut sink = TokenSink::new(&mut store);
1700 let id = lexer.eof_token(&mut sink).expect("test token should fit");
1701 let token = sink.view(id).expect("emitted token should exist");
1702
1703 assert_eq!(token.start(), 1);
1704 assert_eq!(token.stop(), 0);
1705 assert_eq!(token.text(), "<EOF>");
1706 assert_eq!(token.byte_span(), 2..2);
1707 }
1708
1709 #[test]
1710 fn eof_rule_token_uses_utf8_byte_offset_after_non_ascii_input() {
1711 let data = RecognizerData::new(
1712 "T",
1713 Vocabulary::new(
1714 std::iter::empty::<Option<&str>>(),
1715 std::iter::empty::<Option<&str>>(),
1716 std::iter::empty::<Option<&str>>(),
1717 ),
1718 );
1719 let mut lexer = BaseLexer::new(InputStream::new("β"), data);
1720 lexer.consume_char();
1721 lexer.begin_token();
1722
1723 let mut store = TokenStore::new(lexer.source_text(), lexer.source_name());
1724 let mut sink = TokenSink::new(&mut store);
1725 let id = lexer
1726 .emit_with_stop(&mut sink, 1, DEFAULT_CHANNEL, 0, Some("<EOF>".to_owned()))
1727 .expect("test token should fit");
1728 let token = sink.view(id).expect("emitted token should exist");
1729
1730 assert_eq!(token.start(), 1);
1731 assert_eq!(token.stop(), 0);
1732 assert_eq!(token.text(), "<EOF>");
1733 assert_eq!(token.byte_span(), 2..2);
1734 }
1735
1736 #[test]
1737 fn emit_implicit_text_uses_utf8_byte_span_for_non_ascii_input() {
1738 let data = RecognizerData::new(
1739 "T",
1740 Vocabulary::new(
1741 std::iter::empty::<Option<&str>>(),
1742 std::iter::empty::<Option<&str>>(),
1743 std::iter::empty::<Option<&str>>(),
1744 ),
1745 );
1746 let mut lexer = BaseLexer::new(InputStream::new("β"), data);
1747 lexer.begin_token();
1748 lexer.consume_char();
1749
1750 let mut store = TokenStore::new(lexer.source_text(), lexer.source_name());
1751 let mut sink = TokenSink::new(&mut store);
1752 let id = lexer
1753 .emit(&mut sink, 1, DEFAULT_CHANNEL, None)
1754 .expect("test token should fit");
1755 let token = sink.view(id).expect("emitted token should exist");
1756
1757 assert_eq!(token.start(), 0);
1758 assert_eq!(token.stop(), 0);
1759 assert_eq!(token.text(), "β");
1760 assert_eq!(token.byte_span(), 0..2);
1761 }
1762
1763 #[test]
1764 fn emit_falls_back_to_explicit_text_without_shareable_source() {
1765 let data = RecognizerData::new(
1766 "T",
1767 Vocabulary::new(
1768 std::iter::empty::<Option<&str>>(),
1769 std::iter::empty::<Option<&str>>(),
1770 std::iter::empty::<Option<&str>>(),
1771 ),
1772 );
1773 let mut lexer = BaseLexer::new(UnsharedInput(InputStream::new("β")), data);
1774 lexer.begin_token();
1775 lexer.consume_char();
1776
1777 let mut store = TokenStore::new(lexer.source_text(), lexer.source_name());
1778 let mut sink = TokenSink::new(&mut store);
1779 let id = lexer
1780 .emit(&mut sink, 1, DEFAULT_CHANNEL, None)
1781 .expect("unshared input should emit explicit token text");
1782 let token = sink.view(id).expect("emitted token should exist");
1783
1784 assert_eq!(token.text(), "β");
1785 assert_eq!(token.byte_span(), 0..2);
1786 }
1787
1788 #[test]
1789 fn position_commits_and_rewinds_preserve_line_and_column() {
1790 let data = RecognizerData::new(
1791 "T",
1792 Vocabulary::new(
1793 std::iter::empty::<Option<&str>>(),
1794 std::iter::empty::<Option<&str>>(),
1795 std::iter::empty::<Option<&str>>(),
1796 ),
1797 );
1798 let mut lexer = BaseLexer::new(InputStream::new("ab\nγd"), data);
1799 lexer.begin_token();
1800
1801 lexer.commit_position(0, 5);
1802 assert_eq!(lexer.input().index(), 5);
1803 assert_eq!((lexer.line(), lexer.column()), (2, 2));
1804 assert_eq!(lexer.column_at(2), 2);
1805 assert_eq!(lexer.column_at(4), 1);
1806
1807 lexer.reset_accept_position(3);
1808 assert_eq!(lexer.input().index(), 3);
1809 assert_eq!((lexer.line(), lexer.column()), (2, 0));
1810 }
1811
1812 #[test]
1813 fn custom_stream_position_commit_replays_without_fast_path_methods() {
1814 let data = RecognizerData::new(
1815 "T",
1816 Vocabulary::new(
1817 std::iter::empty::<Option<&str>>(),
1818 std::iter::empty::<Option<&str>>(),
1819 std::iter::empty::<Option<&str>>(),
1820 ),
1821 );
1822 let mut lexer = BaseLexer::new(UnsharedInput(InputStream::new("a\nb")), data);
1823 lexer.begin_token();
1824
1825 lexer.commit_position(0, 3);
1826 assert_eq!(lexer.input().index(), 3);
1827 assert_eq!((lexer.line(), lexer.column()), (2, 1));
1828 }
1829
1830 #[test]
1831 fn semantic_hook_errors_are_deduplicated_per_token_coordinate() {
1832 let data = RecognizerData::new(
1833 "T",
1834 Vocabulary::new(
1835 std::iter::empty::<Option<&str>>(),
1836 std::iter::empty::<Option<&str>>(),
1837 std::iter::empty::<Option<&str>>(),
1838 ),
1839 );
1840 let mut lexer = BaseLexer::new(InputStream::new("a"), data);
1841 lexer.begin_token();
1842 lexer.record_semantic_error(false, 3, 7);
1843 lexer.record_semantic_error(false, 3, 7);
1844
1845 let errors = lexer.drain_errors();
1846 assert_eq!(errors.len(), 1);
1847 assert_eq!(
1848 errors[0].message,
1849 "unhandled lexer semantic predicate: rule=3 index=7"
1850 );
1851
1852 lexer.begin_token();
1853 lexer.record_semantic_error(false, 3, 7);
1854 assert_eq!(
1855 lexer.drain_errors().len(),
1856 1,
1857 "deduplication resets at every token boundary, even after rewinding"
1858 );
1859 }
1860
1861 #[test]
1862 fn set_input_stream_replaces_input_and_resets_transient_state() {
1863 let data = RecognizerData::new(
1864 "T",
1865 Vocabulary::new(
1866 std::iter::empty::<Option<&str>>(),
1867 std::iter::empty::<Option<&str>>(),
1868 std::iter::empty::<Option<&str>>(),
1869 ),
1870 );
1871 let mut lexer = BaseLexer::new(InputStream::new("old"), data);
1872 lexer.consume_char();
1873 lexer.set_mode(7);
1874 lexer.push_mode(9);
1875 lexer.set_type(3);
1876 lexer.record_error(1, 0, "stale");
1877
1878 lexer.set_input_stream(InputStream::with_source_name("new", "replacement"));
1879
1880 assert_eq!(lexer.input().index(), 0);
1881 assert_eq!(lexer.input().size(), 3);
1882 assert_eq!(lexer.source_name(), "replacement");
1883 assert_eq!(lexer.source_text().as_deref(), Some("new"));
1884 assert_eq!(lexer.mode(), DEFAULT_MODE);
1885 assert_eq!(lexer.token_type(), INVALID_TOKEN_TYPE);
1886 assert_eq!((lexer.line(), lexer.column()), (1, 0));
1887 assert!(!lexer.hit_eof());
1888 assert!(lexer.drain_errors().is_empty());
1889 assert!(lexer.pop_mode().is_none());
1890 }
1891
1892 #[test]
1893 fn clear_dfa_invalidates_all_lexers_sharing_the_cache() {
1894 let atn = Box::leak(Box::new(LexerAtn::new(1)));
1895 let data = || {
1896 RecognizerData::new(
1897 "T",
1898 Vocabulary::new(
1899 std::iter::empty::<Option<&str>>(),
1900 std::iter::empty::<Option<&str>>(),
1901 std::iter::empty::<Option<&str>>(),
1902 ),
1903 )
1904 };
1905 let first = BaseLexer::new(InputStream::new("a"), data()).with_shared_dfa(atn);
1906 let second = BaseLexer::new(InputStream::new("a"), data()).with_shared_dfa(atn);
1907 let state = first.lexer_dfa_state(LexerDfaKey::new(Vec::new()), Some(1));
1908 first.record_lexer_dfa_edge(state, i32::from(b'a'), state);
1909
1910 assert!(!second.lexer_dfa_string().is_empty());
1911 first.clear_dfa();
1912 assert!(first.lexer_dfa_string().is_empty());
1913 assert!(second.lexer_dfa_string().is_empty());
1914 }
1915}