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 #[must_use]
779 pub fn with_shared_dfa(mut self, atn: &'static LexerAtn) -> Self {
780 let ptr: *const LexerAtn = atn;
781 let key = ptr as usize;
782 self.dfa_cache = SHARED_LEXER_DFA_CACHES
783 .with(|caches| Rc::clone(caches.borrow_mut().entry(key).or_insert_with(Rc::default)));
784 self
785 }
786
787 pub const fn input(&self) -> &I {
788 &self.input
789 }
790
791 pub const fn input_mut(&mut self) -> &mut I {
792 &mut self.input
793 }
794
795 pub fn begin_token(&mut self) {
798 self.semantic_error_coordinates.get_mut().clear();
799 self.token_type = INVALID_TOKEN_TYPE;
800 self.channel = DEFAULT_CHANNEL;
801 self.token_start = self.input.index();
802 self.token_start_line = self.line;
803 self.token_start_column = self.column;
804 }
805
806 pub const fn token_start(&self) -> usize {
808 self.token_start
809 }
810
811 pub const fn token_start_line(&self) -> usize {
813 self.token_start_line
814 }
815
816 pub const fn token_start_column(&self) -> usize {
818 self.token_start_column
819 }
820
821 pub const fn token_type(&self) -> i32 {
823 self.token_type
824 }
825
826 pub const fn set_type(&mut self, token_type: i32) {
828 self.token_type = token_type;
829 }
830
831 pub const fn channel(&self) -> i32 {
833 self.channel
834 }
835
836 pub const fn set_channel(&mut self, channel: i32) {
838 self.channel = channel;
839 }
840
841 pub const fn skip(&mut self) {
843 self.set_type(SKIP);
844 }
845
846 pub const fn more(&mut self) {
848 self.set_type(MORE);
849 }
850
851 pub fn la(&mut self, offset: isize) -> i32 {
854 self.input.la(offset)
855 }
856
857 fn lookahead_at(&self, position: usize, offset: isize) -> i32 {
858 if offset == 0 {
859 return 0;
860 }
861 let absolute = if offset > 0 {
862 position.checked_add((offset - 1).cast_unsigned())
863 } else {
864 offset
865 .checked_neg()
866 .and_then(|distance| usize::try_from(distance).ok())
867 .and_then(|distance| position.checked_sub(distance))
868 };
869 let Some(index) = absolute.filter(|index| *index < self.input.size()) else {
870 return EOF;
871 };
872 if let Some(symbol) = self.input.symbol_at(index) {
873 return symbol;
874 }
875 self.input
876 .text(TextInterval::new(index, index))
877 .chars()
878 .next()
879 .map_or(EOF, |ch| u32::from(ch).cast_signed())
880 }
881
882 pub fn consume_char(&mut self) {
889 let la = self.input.la(1);
890 if la == EOF {
891 return;
892 }
893 self.input.consume();
894 if char::from_u32(la.cast_unsigned()) == Some('\n') {
895 self.line += 1;
896 self.column = 0;
897 } else {
898 self.column += 1;
899 }
900 }
901
902 pub(crate) fn commit_position(&mut self, start: usize, target: usize) {
905 self.reposition_from(start, self.line, self.column, target);
906 }
907
908 fn reposition_from(&mut self, start: usize, line: usize, column: usize, target: usize) {
909 let start = start.min(self.input.size());
910 let target = target.max(start).min(self.input.size());
911 if let Some(summary) = self.input.position_summary(start, target) {
912 self.input.seek(target);
913 (self.line, self.column) = summary.apply(line, column);
914 #[cfg(feature = "perf-counters")]
915 crate::perf::record_lexer_bulk_commit(target - start);
916 return;
917 }
918
919 self.input.seek(start);
920 self.line = line;
921 self.column = column;
922 #[cfg(feature = "perf-counters")]
923 let before = self.input.index();
924 while self.input.index() < target && self.input.la(1) != EOF {
925 self.consume_char();
926 }
927 #[cfg(feature = "perf-counters")]
928 crate::perf::record_lexer_scalar_replay(self.input.index().saturating_sub(before));
929 }
930
931 pub fn reset_accept_position(&mut self, index: usize) {
938 let target = index.max(self.token_start);
939 self.reposition_from(
940 self.token_start,
941 self.token_start_line,
942 self.token_start_column,
943 target,
944 );
945 }
946
947 pub fn set_token_start(&mut self, index: usize) -> bool {
953 if index < self.token_start || index > self.input.index() {
954 return false;
955 }
956 let (line, column) = self.position_at(index);
957 self.token_start = index;
958 self.token_start_line = line;
959 self.token_start_column = column;
960 true
961 }
962
963 pub fn emit(
971 &self,
972 sink: &mut TokenSink<'_>,
973 token_type: i32,
974 channel: i32,
975 text: Option<String>,
976 ) -> Result<TokenId, TokenStoreError> {
977 let stop = self.input.index().checked_sub(1).unwrap_or(usize::MAX);
978 self.emit_with_stop(sink, token_type, channel, stop, text)
979 }
980
981 pub fn emit_with_stop(
987 &self,
988 sink: &mut TokenSink<'_>,
989 token_type: i32,
990 channel: i32,
991 stop: usize,
992 text: Option<String>,
993 ) -> Result<TokenId, TokenStoreError> {
994 sink.push(self.token_spec_with_stop(token_type, channel, stop, text))
995 }
996
997 fn token_spec_with_stop(
998 &self,
999 token_type: i32,
1000 channel: i32,
1001 stop: usize,
1002 text: Option<String>,
1003 ) -> TokenSpec {
1004 let text = text.or_else(|| {
1005 if stop == usize::MAX {
1006 Some("<EOF>".to_owned())
1007 } else {
1008 None
1009 }
1010 });
1011 let source_interval = if self.has_source_text
1012 && text.is_none()
1013 && stop != usize::MAX
1014 && self.token_start <= stop
1015 {
1016 self.input
1017 .byte_interval(TextInterval::new(self.token_start, stop))
1018 } else {
1019 None
1020 };
1021 let text = text.or_else(|| {
1022 source_interval
1023 .is_none()
1024 .then(|| self.input.text(TextInterval::new(self.token_start, stop)))
1025 });
1026 let (start_byte, stop_byte) = source_interval
1027 .or_else(|| self.token_byte_span(stop))
1028 .unwrap_or((self.token_start, self.token_start));
1029 TokenSpec {
1030 token_type,
1031 channel,
1032 start: self.token_start,
1033 stop,
1034 start_byte,
1035 stop_byte,
1036 line: self.token_start_line,
1037 column: self.token_start_column,
1038 text,
1039 source_backed: source_interval.is_some(),
1040 }
1041 }
1042
1043 pub fn enqueue_token(
1049 &mut self,
1050 token_type: i32,
1051 channel: i32,
1052 stop: usize,
1053 text: Option<String>,
1054 ) {
1055 let token = self.token_spec_with_stop(token_type, channel, stop, text);
1056 self.pending_tokens.push_back(token);
1057 }
1058
1059 pub(crate) fn emit_pending_token(
1060 &mut self,
1061 sink: &mut TokenSink<'_>,
1062 ) -> Result<Option<TokenId>, TokenStoreError> {
1063 self.pending_tokens
1064 .pop_front()
1065 .map(|token| sink.push(token))
1066 .transpose()
1067 }
1068
1069 pub(crate) fn emit_or_enqueue_with_stop(
1070 &mut self,
1071 sink: &mut TokenSink<'_>,
1072 stop: usize,
1073 text: Option<String>,
1074 ) -> Result<TokenId, TokenStoreError> {
1075 let token = self.token_spec_with_stop(self.token_type, self.channel, stop, text);
1076 self.emit_or_enqueue(sink, token)
1077 }
1078
1079 fn emit_or_enqueue(
1080 &mut self,
1081 sink: &mut TokenSink<'_>,
1082 token: TokenSpec,
1083 ) -> Result<TokenId, TokenStoreError> {
1084 if self.pending_tokens.is_empty() {
1085 return sink.push(token);
1086 }
1087 self.pending_tokens.push_back(token);
1088 self.emit_pending_token(sink)?
1089 .ok_or_else(|| unreachable!("the pending-token queue was just populated"))
1090 }
1091
1092 pub fn token_text(&self) -> String {
1095 self.token_text_until(self.input.index())
1096 }
1097
1098 pub fn token_text_until(&self, stop_exclusive: usize) -> String {
1106 if stop_exclusive <= self.token_start {
1107 return String::new();
1108 }
1109 self.input
1110 .text(TextInterval::new(self.token_start, stop_exclusive - 1))
1111 }
1112
1113 pub fn column_at(&self, position: usize) -> usize {
1116 self.position_at(position).1
1117 }
1118
1119 fn position_at(&self, position: usize) -> (usize, usize) {
1120 let mut line = self.token_start_line;
1121 let mut column = self.token_start_column;
1122 if position <= self.token_start {
1123 return (line, column);
1124 }
1125 if let Some(summary) = self.input.position_summary(self.token_start, position) {
1126 return summary.apply(line, column);
1127 }
1128 for ch in self
1129 .input
1130 .text(TextInterval::new(self.token_start, position - 1))
1131 .chars()
1132 {
1133 if ch == '\n' {
1134 line += 1;
1135 column = 0;
1136 } else {
1137 column += 1;
1138 }
1139 }
1140 (line, column)
1141 }
1142
1143 pub fn eof_token(&self, sink: &mut TokenSink<'_>) -> Result<TokenId, TokenStoreError> {
1145 sink.push(self.eof_token_spec())
1146 }
1147
1148 pub(crate) fn emit_eof_or_pending(
1149 &mut self,
1150 sink: &mut TokenSink<'_>,
1151 ) -> Result<TokenId, TokenStoreError> {
1152 let token = self.eof_token_spec();
1153 self.emit_or_enqueue(sink, token)
1154 }
1155
1156 fn eof_token_spec(&self) -> TokenSpec {
1157 let byte_offset = self.eof_byte_offset().unwrap_or_else(|| self.input.index());
1158 TokenSpec::eof(self.input.index(), byte_offset, self.line, self.column)
1159 }
1160
1161 fn eof_byte_offset(&self) -> Option<usize> {
1162 self.byte_offset_at(self.input.index())
1163 }
1164
1165 fn token_byte_span(&self, stop: usize) -> Option<(usize, usize)> {
1166 if stop != usize::MAX && self.token_start <= stop {
1167 let (start_byte, stop_byte) = self
1168 .input
1169 .byte_interval(TextInterval::new(self.token_start, stop))?;
1170 return Some((start_byte, stop_byte));
1171 }
1172 let byte_offset = self.byte_offset_at(self.token_start)?;
1173 Some((byte_offset, byte_offset))
1174 }
1175
1176 fn byte_offset_at(&self, index: usize) -> Option<usize> {
1177 let byte_offset = if index == 0 {
1178 0
1179 } else {
1180 let previous = TextInterval::new(index - 1, index - 1);
1181 self.input.byte_interval(previous)?.1
1182 };
1183 Some(byte_offset)
1184 }
1185}
1186
1187impl<I> Recognizer for BaseLexer<I>
1188where
1189 I: CharStream,
1190{
1191 fn data(&self) -> &RecognizerData {
1192 &self.data
1193 }
1194
1195 fn data_mut(&mut self) -> &mut RecognizerData {
1196 &mut self.data
1197 }
1198}
1199
1200impl<I> Lexer for BaseLexer<I>
1201where
1202 I: CharStream,
1203{
1204 fn mode(&self) -> i32 {
1205 self.mode
1206 }
1207
1208 fn set_mode(&mut self, mode: i32) {
1209 self.mode = mode;
1210 }
1211
1212 fn push_mode(&mut self, mode: i32) {
1213 self.mode_stack.push(self.mode);
1214 self.mode = mode;
1215 }
1216
1217 fn pop_mode(&mut self) -> Option<i32> {
1218 let mode = self.mode_stack.pop()?;
1219 self.mode = mode;
1220 Some(mode)
1221 }
1222}
1223
1224impl<I> BaseLexer<I>
1225where
1226 I: CharStream,
1227{
1228 pub const fn line(&self) -> usize {
1229 self.line
1230 }
1231
1232 pub const fn column(&self) -> usize {
1233 self.column
1234 }
1235
1236 pub fn source_name(&self) -> &str {
1237 self.input.source_name()
1238 }
1239
1240 pub fn source_text(&self) -> Option<Rc<str>> {
1241 self.input.source_text()
1242 }
1243
1244 pub const fn hit_eof(&self) -> bool {
1245 self.hit_eof
1246 }
1247
1248 pub const fn set_hit_eof(&mut self, hit_eof: bool) {
1249 self.hit_eof = hit_eof;
1250 }
1251
1252 pub const fn set_force_interpreted(&mut self, force_interpreted: bool) {
1260 self.force_interpreted = force_interpreted;
1261 }
1262
1263 pub const fn force_interpreted(&self) -> bool {
1265 self.force_interpreted
1266 }
1267
1268 pub fn record_error(&self, line: usize, column: usize, message: impl Into<String>) {
1271 self.errors
1272 .borrow_mut()
1273 .push(TokenSourceError::new(line, column, message));
1274 }
1275
1276 pub fn record_semantic_error(&self, action: bool, rule_index: usize, coordinate_index: usize) {
1278 let kind = u8::from(action);
1279 if !self.semantic_error_coordinates.borrow_mut().insert((
1280 kind,
1281 rule_index,
1282 coordinate_index,
1283 self.token_start,
1284 )) {
1285 return;
1286 }
1287 let label = if action { "action" } else { "predicate" };
1288 self.record_error(
1289 self.token_start_line,
1290 self.token_start_column,
1291 format!("unhandled lexer semantic {label}: rule={rule_index} index={coordinate_index}"),
1292 );
1293 }
1294
1295 pub fn drain_errors(&mut self) -> Vec<TokenSourceError> {
1297 std::mem::take(self.errors.get_mut())
1298 }
1299
1300 pub(crate) fn lexer_dfa_state(
1303 &self,
1304 key: LexerDfaKey,
1305 accept_prediction: Option<i32>,
1306 ) -> usize {
1307 let mut cache = self.dfa_cache.borrow_mut();
1308 let next = cache.state_numbers.len();
1309 let state = *cache.state_numbers.entry(key).or_insert(next);
1310 if let Some(prediction) = accept_prediction {
1311 cache.accept_predictions.insert(state, prediction);
1312 }
1313 state
1314 }
1315
1316 pub fn record_lexer_dfa_edge(&self, from: usize, symbol: i32, to: usize) {
1318 self.dfa_cache
1319 .borrow_mut()
1320 .edges
1321 .insert(LexerDfaEdge { from, symbol, to });
1322 }
1323
1324 pub(crate) fn cached_lexer_dfa_transition(
1325 &self,
1326 state: usize,
1327 symbol: i32,
1328 ) -> Option<LexerDfaCachedTransition> {
1329 let cache = self.dfa_cache.borrow();
1330 if let Ok(sym) = usize::try_from(symbol)
1331 && sym < DENSE_EDGE_SYMBOLS
1332 {
1333 let transition = cache.dense_edges.get(state)?.as_ref()?[sym];
1334 return (transition.target_state != usize::MAX).then_some(transition);
1335 }
1336 cache.sparse_edges.get(&(state, symbol)).copied()
1337 }
1338
1339 pub(crate) fn cache_lexer_dfa_transition(
1340 &self,
1341 state: usize,
1342 symbol: i32,
1343 transition: LexerDfaCachedTransition,
1344 ) {
1345 let mut cache = self.dfa_cache.borrow_mut();
1346 if let Ok(sym) = usize::try_from(symbol)
1347 && sym < DENSE_EDGE_SYMBOLS
1348 {
1349 if cache.dense_edges.len() <= state {
1350 cache.dense_edges.resize_with(state + 1, || None);
1351 }
1352 let row = cache.dense_edges[state]
1353 .get_or_insert_with(|| Box::new([EMPTY_DENSE_EDGE; DENSE_EDGE_SYMBOLS]));
1354 if row[sym].target_state == usize::MAX {
1356 row[sym] = transition;
1357 }
1358 return;
1359 }
1360 cache
1361 .sparse_edges
1362 .entry((state, symbol))
1363 .or_insert(transition);
1364 }
1365
1366 pub(crate) fn cached_lexer_dfa_state(&self, state: usize) -> Option<Rc<LexerDfaCachedState>> {
1367 self.dfa_cache
1368 .borrow()
1369 .cached_states
1370 .get(state)
1371 .cloned()
1372 .flatten()
1373 }
1374
1375 pub(crate) fn cache_lexer_dfa_state(&self, state: usize, cached_state: LexerDfaCachedState) {
1376 let mut cache = self.dfa_cache.borrow_mut();
1377 if cache.cached_states.len() <= state {
1378 cache.cached_states.resize_with(state + 1, || None);
1379 }
1380 cache.cached_states[state].get_or_insert_with(|| Rc::new(cached_state));
1381 }
1382
1383 pub(crate) fn cached_lexer_mode_start(&self, mode: i32) -> Option<usize> {
1384 self.dfa_cache.borrow().mode_starts.get(&mode).copied()
1385 }
1386
1387 pub(crate) fn cache_lexer_mode_start(&self, mode: i32, state: usize) {
1388 self.dfa_cache
1389 .borrow_mut()
1390 .mode_starts
1391 .entry(mode)
1392 .or_insert(state);
1393 }
1394
1395 pub fn lexer_dfa_string(&self) -> String {
1397 let mut out = String::new();
1398 let cache = self.dfa_cache.borrow();
1399 for edge in &cache.edges {
1400 let Some(label) = lexer_dfa_edge_label(edge.symbol) else {
1401 continue;
1402 };
1403 out.push_str(&self.lexer_dfa_state_string(edge.from));
1404 out.push('-');
1405 out.push_str(&label);
1406 out.push_str("->");
1407 out.push_str(&self.lexer_dfa_state_string(edge.to));
1408 out.push('\n');
1409 }
1410 out
1411 }
1412
1413 fn lexer_dfa_state_string(&self, state: usize) -> String {
1414 self.dfa_cache
1415 .borrow()
1416 .accept_predictions
1417 .get(&state)
1418 .map_or_else(
1419 || format!("s{state}"),
1420 |prediction| format!(":s{state}=>{prediction}"),
1421 )
1422 }
1423}
1424
1425fn lexer_dfa_edge_label(symbol: i32) -> Option<String> {
1426 char::from_u32(symbol.cast_unsigned()).map(|ch| format!("'{ch}'"))
1427}
1428
1429#[cfg(test)]
1430mod tests {
1431 use super::*;
1432 use crate::char_stream::InputStream;
1433 use crate::int_stream::IntStream;
1434 use crate::recognizer::RecognizerData;
1435 use crate::token::{DEFAULT_CHANNEL, Token, TokenStore};
1436 use crate::vocabulary::Vocabulary;
1437
1438 #[derive(Clone, Debug)]
1439 struct UnsharedInput(InputStream);
1440
1441 impl IntStream for UnsharedInput {
1442 fn consume(&mut self) {
1443 self.0.consume();
1444 }
1445
1446 fn la(&mut self, offset: isize) -> i32 {
1447 self.0.la(offset)
1448 }
1449
1450 fn index(&self) -> usize {
1451 self.0.index()
1452 }
1453
1454 fn seek(&mut self, index: usize) {
1455 self.0.seek(index);
1456 }
1457
1458 fn size(&self) -> usize {
1459 self.0.size()
1460 }
1461
1462 fn source_name(&self) -> &str {
1463 self.0.source_name()
1464 }
1465 }
1466
1467 impl CharStream for UnsharedInput {
1468 fn text(&self, interval: TextInterval) -> String {
1469 self.0.text(interval)
1470 }
1471
1472 fn byte_interval(&self, interval: TextInterval) -> Option<(usize, usize)> {
1473 self.0.byte_interval(interval)
1474 }
1475 }
1476
1477 #[test]
1478 fn eof_token_uses_utf8_byte_offset_after_non_ascii_input() {
1479 let data = RecognizerData::new(
1480 "T",
1481 Vocabulary::new(
1482 std::iter::empty::<Option<&str>>(),
1483 std::iter::empty::<Option<&str>>(),
1484 std::iter::empty::<Option<&str>>(),
1485 ),
1486 );
1487 let mut lexer = BaseLexer::new(InputStream::new("β"), data);
1488 lexer.consume_char();
1489
1490 let mut store = TokenStore::new(lexer.source_text(), lexer.source_name());
1491 let mut sink = TokenSink::new(&mut store);
1492 let id = lexer.eof_token(&mut sink).expect("test token should fit");
1493 let token = sink.view(id).expect("emitted token should exist");
1494
1495 assert_eq!(token.start(), 1);
1496 assert_eq!(token.stop(), 0);
1497 assert_eq!(token.text(), "<EOF>");
1498 assert_eq!(token.byte_span(), 2..2);
1499 }
1500
1501 #[test]
1502 fn eof_rule_token_uses_utf8_byte_offset_after_non_ascii_input() {
1503 let data = RecognizerData::new(
1504 "T",
1505 Vocabulary::new(
1506 std::iter::empty::<Option<&str>>(),
1507 std::iter::empty::<Option<&str>>(),
1508 std::iter::empty::<Option<&str>>(),
1509 ),
1510 );
1511 let mut lexer = BaseLexer::new(InputStream::new("β"), data);
1512 lexer.consume_char();
1513 lexer.begin_token();
1514
1515 let mut store = TokenStore::new(lexer.source_text(), lexer.source_name());
1516 let mut sink = TokenSink::new(&mut store);
1517 let id = lexer
1518 .emit_with_stop(&mut sink, 1, DEFAULT_CHANNEL, 0, Some("<EOF>".to_owned()))
1519 .expect("test token should fit");
1520 let token = sink.view(id).expect("emitted token should exist");
1521
1522 assert_eq!(token.start(), 1);
1523 assert_eq!(token.stop(), 0);
1524 assert_eq!(token.text(), "<EOF>");
1525 assert_eq!(token.byte_span(), 2..2);
1526 }
1527
1528 #[test]
1529 fn emit_implicit_text_uses_utf8_byte_span_for_non_ascii_input() {
1530 let data = RecognizerData::new(
1531 "T",
1532 Vocabulary::new(
1533 std::iter::empty::<Option<&str>>(),
1534 std::iter::empty::<Option<&str>>(),
1535 std::iter::empty::<Option<&str>>(),
1536 ),
1537 );
1538 let mut lexer = BaseLexer::new(InputStream::new("β"), data);
1539 lexer.begin_token();
1540 lexer.consume_char();
1541
1542 let mut store = TokenStore::new(lexer.source_text(), lexer.source_name());
1543 let mut sink = TokenSink::new(&mut store);
1544 let id = lexer
1545 .emit(&mut sink, 1, DEFAULT_CHANNEL, None)
1546 .expect("test token should fit");
1547 let token = sink.view(id).expect("emitted token should exist");
1548
1549 assert_eq!(token.start(), 0);
1550 assert_eq!(token.stop(), 0);
1551 assert_eq!(token.text(), "β");
1552 assert_eq!(token.byte_span(), 0..2);
1553 }
1554
1555 #[test]
1556 fn emit_falls_back_to_explicit_text_without_shareable_source() {
1557 let data = RecognizerData::new(
1558 "T",
1559 Vocabulary::new(
1560 std::iter::empty::<Option<&str>>(),
1561 std::iter::empty::<Option<&str>>(),
1562 std::iter::empty::<Option<&str>>(),
1563 ),
1564 );
1565 let mut lexer = BaseLexer::new(UnsharedInput(InputStream::new("β")), data);
1566 lexer.begin_token();
1567 lexer.consume_char();
1568
1569 let mut store = TokenStore::new(lexer.source_text(), lexer.source_name());
1570 let mut sink = TokenSink::new(&mut store);
1571 let id = lexer
1572 .emit(&mut sink, 1, DEFAULT_CHANNEL, None)
1573 .expect("unshared input should emit explicit token text");
1574 let token = sink.view(id).expect("emitted token should exist");
1575
1576 assert_eq!(token.text(), "β");
1577 assert_eq!(token.byte_span(), 0..2);
1578 }
1579
1580 #[test]
1581 fn position_commits_and_rewinds_preserve_line_and_column() {
1582 let data = RecognizerData::new(
1583 "T",
1584 Vocabulary::new(
1585 std::iter::empty::<Option<&str>>(),
1586 std::iter::empty::<Option<&str>>(),
1587 std::iter::empty::<Option<&str>>(),
1588 ),
1589 );
1590 let mut lexer = BaseLexer::new(InputStream::new("ab\nγd"), data);
1591 lexer.begin_token();
1592
1593 lexer.commit_position(0, 5);
1594 assert_eq!(lexer.input().index(), 5);
1595 assert_eq!((lexer.line(), lexer.column()), (2, 2));
1596 assert_eq!(lexer.column_at(2), 2);
1597 assert_eq!(lexer.column_at(4), 1);
1598
1599 lexer.reset_accept_position(3);
1600 assert_eq!(lexer.input().index(), 3);
1601 assert_eq!((lexer.line(), lexer.column()), (2, 0));
1602 }
1603
1604 #[test]
1605 fn custom_stream_position_commit_replays_without_fast_path_methods() {
1606 let data = RecognizerData::new(
1607 "T",
1608 Vocabulary::new(
1609 std::iter::empty::<Option<&str>>(),
1610 std::iter::empty::<Option<&str>>(),
1611 std::iter::empty::<Option<&str>>(),
1612 ),
1613 );
1614 let mut lexer = BaseLexer::new(UnsharedInput(InputStream::new("a\nb")), data);
1615 lexer.begin_token();
1616
1617 lexer.commit_position(0, 3);
1618 assert_eq!(lexer.input().index(), 3);
1619 assert_eq!((lexer.line(), lexer.column()), (2, 1));
1620 }
1621
1622 #[test]
1623 fn semantic_hook_errors_are_deduplicated_per_token_coordinate() {
1624 let data = RecognizerData::new(
1625 "T",
1626 Vocabulary::new(
1627 std::iter::empty::<Option<&str>>(),
1628 std::iter::empty::<Option<&str>>(),
1629 std::iter::empty::<Option<&str>>(),
1630 ),
1631 );
1632 let mut lexer = BaseLexer::new(InputStream::new("a"), data);
1633 lexer.begin_token();
1634 lexer.record_semantic_error(false, 3, 7);
1635 lexer.record_semantic_error(false, 3, 7);
1636
1637 let errors = lexer.drain_errors();
1638 assert_eq!(errors.len(), 1);
1639 assert_eq!(
1640 errors[0].message,
1641 "unhandled lexer semantic predicate: rule=3 index=7"
1642 );
1643
1644 lexer.begin_token();
1645 lexer.record_semantic_error(false, 3, 7);
1646 assert_eq!(
1647 lexer.drain_errors().len(),
1648 1,
1649 "deduplication resets at every token boundary, even after rewinding"
1650 );
1651 }
1652}