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::semir::MemberEnv;
14use crate::token::{
15 DEFAULT_CHANNEL, INVALID_TOKEN_TYPE, TokenId, TokenSink, TokenSourceError, TokenSpec,
16 TokenStoreError,
17};
18
19#[allow(clippy::disallowed_types)]
20type FxHashMap<K, V> = HashMap<K, V, BuildHasherDefault<PredictionFxHasher>>;
21
22pub const SKIP: i32 = -3;
23pub const MORE: i32 = -2;
24pub const DEFAULT_MODE: i32 = 0;
25
26#[derive(Clone, Copy, Debug, Eq, PartialEq)]
27pub struct LexerMode(pub i32);
28
29#[derive(Clone, Copy, Debug, Eq, PartialEq)]
36pub struct LexerCustomAction {
37 rule_index: i32,
38 action_index: i32,
39 position: usize,
40}
41
42impl LexerCustomAction {
43 pub const fn new(rule_index: i32, action_index: i32, position: usize) -> Self {
45 Self {
46 rule_index,
47 action_index,
48 position,
49 }
50 }
51
52 pub const fn rule_index(self) -> i32 {
54 self.rule_index
55 }
56
57 pub const fn action_index(self) -> i32 {
59 self.action_index
60 }
61
62 pub const fn position(self) -> usize {
64 self.position
65 }
66}
67
68#[derive(Clone, Copy, Debug, Eq, PartialEq)]
70pub struct LexerPredicate {
71 rule_index: usize,
72 pred_index: usize,
73 position: usize,
74}
75
76impl LexerPredicate {
77 pub const fn new(rule_index: usize, pred_index: usize, position: usize) -> Self {
79 Self {
80 rule_index,
81 pred_index,
82 position,
83 }
84 }
85
86 pub const fn rule_index(self) -> usize {
88 self.rule_index
89 }
90
91 pub const fn pred_index(self) -> usize {
93 self.pred_index
94 }
95
96 pub const fn position(self) -> usize {
98 self.position
99 }
100}
101
102#[derive(Debug)]
107enum LexerRef<'a, I>
108where
109 I: CharStream,
110{
111 Shared(&'a BaseLexer<I>),
112 Mut(&'a mut BaseLexer<I>),
113}
114
115impl<I> LexerRef<'_, I>
116where
117 I: CharStream,
118{
119 const fn get(&self) -> &BaseLexer<I> {
120 match self {
121 LexerRef::Shared(lexer) => lexer,
122 LexerRef::Mut(lexer) => lexer,
123 }
124 }
125}
126
127#[derive(Debug)]
129pub struct LexerSemCtx<'a, I>
130where
131 I: CharStream,
132{
133 lexer: LexerRef<'a, I>,
134 rule_index: usize,
135 coordinate_index: usize,
136 position: usize,
137}
138
139impl<'a, I> LexerSemCtx<'a, I>
140where
141 I: CharStream,
142{
143 pub(crate) const fn new(
144 lexer: &'a BaseLexer<I>,
145 rule_index: usize,
146 coordinate_index: usize,
147 position: usize,
148 ) -> Self {
149 Self {
150 lexer: LexerRef::Shared(lexer),
151 rule_index,
152 coordinate_index,
153 position,
154 }
155 }
156
157 pub(crate) const fn new_mut(
160 lexer: &'a mut BaseLexer<I>,
161 rule_index: usize,
162 coordinate_index: usize,
163 position: usize,
164 ) -> Self {
165 Self {
166 lexer: LexerRef::Mut(lexer),
167 rule_index,
168 coordinate_index,
169 position,
170 }
171 }
172
173 #[must_use]
175 pub const fn rule_index(&self) -> usize {
176 self.rule_index
177 }
178
179 #[must_use]
181 pub const fn coordinate_index(&self) -> usize {
182 self.coordinate_index
183 }
184
185 #[must_use]
187 pub const fn position(&self) -> usize {
188 self.position
189 }
190
191 #[must_use]
193 pub fn mode(&self) -> i32 {
194 self.lexer.get().mode()
195 }
196
197 #[must_use]
199 pub const fn column(&self) -> usize {
200 self.lexer.get().column()
201 }
202
203 #[must_use]
205 pub fn position_column(&self) -> usize {
206 self.lexer.get().column_at(self.position)
207 }
208
209 #[must_use]
211 pub const fn token_start_column(&self) -> usize {
212 self.lexer.get().token_start_column()
213 }
214
215 #[must_use]
217 pub fn text_so_far(&self) -> String {
218 self.lexer.get().token_text_until(self.position)
219 }
220
221 pub fn la(&mut self, offset: isize) -> i32 {
227 match &mut self.lexer {
228 LexerRef::Shared(lexer) => lexer.lookahead_at(self.position, offset),
229 LexerRef::Mut(lexer) => lexer.input_mut().la(offset),
230 }
231 }
232
233 #[must_use]
235 pub const fn token_start(&self) -> usize {
236 self.lexer.get().token_start()
237 }
238
239 #[must_use]
241 pub const fn token_type(&self) -> i32 {
242 self.lexer.get().token_type()
243 }
244
245 #[must_use]
247 pub const fn channel(&self) -> i32 {
248 self.lexer.get().channel()
249 }
250
251 pub const fn set_type(&mut self, token_type: i32) -> bool {
254 match &mut self.lexer {
255 LexerRef::Mut(lexer) => {
256 lexer.set_type(token_type);
257 true
258 }
259 LexerRef::Shared(_) => false,
260 }
261 }
262
263 pub const fn set_channel(&mut self, channel: i32) -> bool {
266 match &mut self.lexer {
267 LexerRef::Mut(lexer) => {
268 lexer.set_channel(channel);
269 true
270 }
271 LexerRef::Shared(_) => false,
272 }
273 }
274
275 pub fn consume(&mut self) -> bool {
278 match &mut self.lexer {
279 LexerRef::Mut(lexer) => {
280 lexer.consume_char();
281 true
282 }
283 LexerRef::Shared(_) => false,
284 }
285 }
286
287 pub const fn skip(&mut self) -> bool {
289 self.set_type(SKIP)
290 }
291
292 pub const fn more(&mut self) -> bool {
295 self.set_type(MORE)
296 }
297
298 pub fn reset_accept_position(&mut self, index: usize) -> bool {
300 match &mut self.lexer {
301 LexerRef::Mut(lexer) => {
302 lexer.reset_accept_position(index);
303 true
304 }
305 LexerRef::Shared(_) => false,
306 }
307 }
308
309 pub fn set_token_start(&mut self, index: usize) -> bool {
315 match &mut self.lexer {
316 LexerRef::Mut(lexer) => lexer.set_token_start(index),
317 LexerRef::Shared(_) => false,
318 }
319 }
320
321 pub fn enqueue_token(&mut self, token_type: i32, stop: usize) -> bool {
327 let channel = self.channel();
328 self.enqueue_token_with_channel(token_type, channel, stop)
329 }
330
331 pub fn enqueue_token_with_channel(
334 &mut self,
335 token_type: i32,
336 channel: i32,
337 stop: usize,
338 ) -> bool {
339 match &mut self.lexer {
340 LexerRef::Mut(lexer) => {
341 lexer.enqueue_token(token_type, channel, stop, None);
342 true
343 }
344 LexerRef::Shared(_) => false,
345 }
346 }
347
348 pub fn set_mode(&mut self, mode: i32) -> bool {
355 match &mut self.lexer {
356 LexerRef::Mut(lexer) => {
357 lexer.set_mode(mode);
358 true
359 }
360 LexerRef::Shared(_) => false,
361 }
362 }
363
364 pub fn push_mode(&mut self, mode: i32) -> bool {
367 match &mut self.lexer {
368 LexerRef::Mut(lexer) => {
369 lexer.push_mode(mode);
370 true
371 }
372 LexerRef::Shared(_) => false,
373 }
374 }
375
376 pub fn pop_mode(&mut self) -> Option<i32> {
380 match &mut self.lexer {
381 LexerRef::Mut(lexer) => lexer.pop_mode(),
382 LexerRef::Shared(_) => None,
383 }
384 }
385
386 #[must_use]
388 pub fn member_int(&self, member: usize) -> Option<i64> {
389 self.lexer.get().members().scalar(member)
390 }
391
392 #[must_use]
395 pub fn member_stack_top(&self, member: usize) -> Option<i64> {
396 self.lexer.get().members().stack_top(member)
397 }
398
399 #[must_use]
401 pub fn member_stack_len(&self, member: usize) -> usize {
402 self.lexer.get().members().stack_len(member)
403 }
404
405 pub fn set_member_int(&mut self, member: usize, value: i64) -> bool {
408 self.with_members_mut(|members| members.set_scalar(member, value))
409 .is_some()
410 }
411
412 pub fn add_member_int(&mut self, member: usize, delta: i64) -> Option<i64> {
415 self.with_members_mut(|members| members.add_scalar(member, delta))
416 }
417
418 pub fn push_member(&mut self, member: usize, value: i64) -> bool {
421 self.with_members_mut(|members| members.push_stack(member, value))
422 .is_some()
423 }
424
425 pub fn pop_member(&mut self, member: usize) -> Option<i64> {
428 self.with_members_mut(|members| members.pop_stack(member))
429 .flatten()
430 }
431
432 fn with_members_mut<T>(&mut self, apply: impl FnOnce(&mut MemberEnv) -> T) -> Option<T> {
435 match &mut self.lexer {
436 LexerRef::Mut(lexer) => Some(apply(lexer.members_mut())),
437 LexerRef::Shared(_) => None,
438 }
439 }
440}
441
442#[derive(Clone, Copy, Debug, Eq, PartialEq)]
444pub struct LexerSemanticPredicate {
445 pub rule_index: usize,
447 pub pred_index: usize,
449 pub expr: crate::semir::ExprId,
451}
452
453#[derive(Clone, Copy, Debug, Eq, PartialEq)]
455pub struct LexerSemanticAction {
456 pub rule_index: usize,
458 pub action_index: usize,
460 pub stmt: crate::semir::StmtId,
462}
463
464#[derive(Clone, Debug, Default, Eq, PartialEq)]
470pub struct LexerSemantics {
471 pub ir: crate::semir::SemIr,
472 pub predicates: Vec<LexerSemanticPredicate>,
473 pub actions: Vec<LexerSemanticAction>,
474}
475
476impl LexerSemantics {
477 pub fn eval_predicate<I>(&self, lexer: &BaseLexer<I>, predicate: LexerPredicate) -> Option<bool>
480 where
481 I: CharStream,
482 {
483 let entry = self.predicates.iter().find(|entry| {
484 entry.rule_index == predicate.rule_index() && entry.pred_index == predicate.pred_index()
485 })?;
486 let mut ctx = LexerSemIrCtx::new(lexer, predicate);
487 Some(crate::semir::eval_pred(&self.ir, entry.expr, &mut ctx))
488 }
489
490 pub fn exec_action<I>(&self, lexer: &mut BaseLexer<I>, action: LexerCustomAction) -> bool
493 where
494 I: CharStream,
495 {
496 let Ok(rule_index) = usize::try_from(action.rule_index()) else {
497 return false;
498 };
499 let Ok(action_index) = usize::try_from(action.action_index()) else {
500 return false;
501 };
502 let Some(entry) = self
503 .actions
504 .iter()
505 .find(|entry| entry.rule_index == rule_index && entry.action_index == action_index)
506 else {
507 return false;
508 };
509 let stmt = entry.stmt;
510 let mut ctx = LexerSemIrCtx::new_mut(lexer, action);
511 crate::semir::exec_stmt(&self.ir, stmt, &mut ctx);
512 true
513 }
514}
515
516#[derive(Debug)]
524pub struct LexerSemIrCtx<'a, I>
525where
526 I: CharStream,
527{
528 ctx: LexerSemCtx<'a, I>,
529}
530
531impl<'a, I> LexerSemIrCtx<'a, I>
532where
533 I: CharStream,
534{
535 pub(crate) const fn new(lexer: &'a BaseLexer<I>, predicate: LexerPredicate) -> Self {
537 Self {
538 ctx: LexerSemCtx::new(
539 lexer,
540 predicate.rule_index(),
541 predicate.pred_index(),
542 predicate.position(),
543 ),
544 }
545 }
546
547 pub(crate) fn new_mut(lexer: &'a mut BaseLexer<I>, action: LexerCustomAction) -> Self {
549 let rule_index = usize::try_from(action.rule_index()).unwrap_or_default();
550 let action_index = usize::try_from(action.action_index()).unwrap_or_default();
551 Self {
552 ctx: LexerSemCtx::new_mut(lexer, rule_index, action_index, action.position()),
553 }
554 }
555
556 pub const fn ctx_mut(&mut self) -> &mut LexerSemCtx<'a, I> {
558 &mut self.ctx
559 }
560}
561
562impl<I> crate::semir::PredContext for LexerSemIrCtx<'_, I>
563where
564 I: CharStream,
565{
566 type TokenText<'a>
567 = String
568 where
569 Self: 'a;
570
571 fn la(&mut self, offset: isize) -> i64 {
572 i64::from(self.ctx.la(offset))
573 }
574
575 fn token_text(&mut self, _offset: isize) -> Option<Self::TokenText<'_>> {
578 None
579 }
580
581 fn token_index_adjacent(&mut self) -> bool {
582 false
583 }
584
585 fn ctx_rule_text(&self, _rule_index: usize) -> Option<String> {
586 None
587 }
588
589 fn member(&self, member: usize) -> Option<i64> {
590 Some(self.ctx.member_int(member).unwrap_or_default())
591 }
592
593 fn member_top(&self, member: usize) -> Option<i64> {
594 self.ctx.member_stack_top(member)
595 }
596
597 fn member_len(&self, member: usize) -> usize {
598 self.ctx.member_stack_len(member)
599 }
600
601 fn local_arg(&self) -> Option<i64> {
602 None
603 }
604
605 fn column(&self) -> Option<i64> {
606 Some(i64::try_from(self.ctx.position_column()).unwrap_or(i64::MAX))
607 }
608
609 fn token_start_column(&self) -> Option<i64> {
610 Some(i64::try_from(self.ctx.token_start_column()).unwrap_or(i64::MAX))
611 }
612
613 fn token_text_so_far(&self) -> Option<String> {
614 Some(self.ctx.text_so_far())
615 }
616
617 fn hook(&mut self, _hook: crate::semir::HookId) -> bool {
620 false
621 }
622}
623
624impl<I> crate::semir::ActContext for LexerSemIrCtx<'_, I>
625where
626 I: CharStream,
627{
628 fn set_member(&mut self, member: usize, value: i64) {
629 self.ctx.set_member_int(member, value);
630 }
631
632 fn push_member(&mut self, member: usize, value: i64) {
633 self.ctx.push_member(member, value);
634 }
635
636 fn pop_member(&mut self, member: usize) -> Option<i64> {
637 self.ctx.pop_member(member)
638 }
639
640 fn set_return(&mut self, _name: &str, _value: i64) {}
642
643 fn action_hook(&mut self, _hook: crate::semir::HookId) {}
644}
645
646#[derive(Debug)]
654pub struct LexerLifecycleCtx<'a, I>
655where
656 I: CharStream,
657{
658 lexer: &'a mut BaseLexer<I>,
659 accept_position: Option<usize>,
660}
661
662impl<'a, I> LexerLifecycleCtx<'a, I>
663where
664 I: CharStream,
665{
666 pub(crate) const fn new(lexer: &'a mut BaseLexer<I>, accept_position: Option<usize>) -> Self {
667 Self {
668 lexer,
669 accept_position,
670 }
671 }
672
673 #[must_use]
678 pub const fn accept_position(&self) -> Option<usize> {
679 self.accept_position
680 }
681
682 #[must_use]
684 pub fn input_position(&self) -> usize {
685 self.lexer.input().index()
686 }
687
688 #[must_use]
690 pub const fn mode(&self) -> i32 {
691 self.lexer.mode
692 }
693
694 #[must_use]
696 pub const fn line(&self) -> usize {
697 self.lexer.line()
698 }
699
700 #[must_use]
702 pub const fn column(&self) -> usize {
703 self.lexer.column()
704 }
705
706 #[must_use]
708 pub const fn token_start(&self) -> usize {
709 self.lexer.token_start()
710 }
711
712 #[must_use]
714 pub const fn token_start_line(&self) -> usize {
715 self.lexer.token_start_line()
716 }
717
718 #[must_use]
720 pub const fn token_start_column(&self) -> usize {
721 self.lexer.token_start_column()
722 }
723
724 #[must_use]
726 pub const fn token_type(&self) -> i32 {
727 self.lexer.token_type()
728 }
729
730 #[must_use]
732 pub const fn channel(&self) -> i32 {
733 self.lexer.channel()
734 }
735
736 #[must_use]
738 pub fn pending_token_count(&self) -> usize {
739 self.lexer.pending_tokens.len()
740 }
741
742 #[must_use]
744 pub fn token_text(&self) -> String {
745 self.lexer.token_text()
746 }
747
748 #[must_use]
752 pub fn accepted_text(&self) -> Option<String> {
753 self.accept_position
754 .map(|position| self.lexer.token_text_until(position))
755 }
756
757 pub fn la(&mut self, offset: isize) -> i32 {
760 self.lexer.la(offset)
761 }
762
763 pub fn consume(&mut self) {
765 self.lexer.consume_char();
766 }
767
768 pub const fn set_type(&mut self, token_type: i32) {
770 self.lexer.set_type(token_type);
771 }
772
773 pub const fn set_channel(&mut self, channel: i32) {
775 self.lexer.set_channel(channel);
776 }
777
778 pub const fn skip(&mut self) {
780 self.lexer.skip();
781 }
782
783 pub const fn more(&mut self) {
785 self.lexer.more();
786 }
787
788 pub fn reset_accept_position(&mut self, index: usize) {
790 self.lexer.reset_accept_position(index);
791 }
792
793 pub fn set_token_start(&mut self, index: usize) -> bool {
795 self.lexer.set_token_start(index)
796 }
797
798 pub fn enqueue_token(&mut self, token_type: i32, stop: usize) {
800 self.enqueue_token_with_channel(token_type, self.channel(), stop);
801 }
802
803 pub fn enqueue_token_with_channel(&mut self, token_type: i32, channel: i32, stop: usize) {
805 self.lexer.enqueue_token(token_type, channel, stop, None);
806 }
807
808 pub fn set_mode(&mut self, mode: i32) {
810 self.lexer.set_mode(mode);
811 }
812
813 pub fn push_mode(&mut self, mode: i32) {
815 self.lexer.push_mode(mode);
816 }
817
818 pub fn pop_mode(&mut self) -> Option<i32> {
820 self.lexer.pop_mode()
821 }
822}
823
824pub trait Lexer: Recognizer {
825 fn mode(&self) -> i32;
826 fn set_mode(&mut self, mode: i32);
827 fn push_mode(&mut self, mode: i32);
828 fn pop_mode(&mut self) -> Option<i32>;
829}
830
831#[derive(Clone, Debug)]
832pub struct BaseLexer<I> {
833 input: I,
834 data: RecognizerData,
835 has_source_text: bool,
836 mode: i32,
837 mode_stack: Vec<i32>,
838 token_type: i32,
839 channel: i32,
840 token_start: usize,
841 token_start_line: usize,
842 token_start_column: usize,
843 line: usize,
844 column: usize,
845 hit_eof: bool,
846 force_interpreted: bool,
847 errors: RefCell<Vec<TokenSourceError>>,
848 semantic_error_coordinates: RefCell<BTreeSet<(u8, usize, usize, usize)>>,
849 pending_tokens: VecDeque<TokenSpec>,
850 members: MemberEnv,
859 member_inits: Vec<(usize, i64)>,
863 dfa_cache: Rc<RefCell<LexerDfaCache>>,
864}
865
866#[derive(Debug, Default)]
874struct LexerDfaCache {
875 prediction: LexerPredictionStore,
876 state_numbers: FxHashMap<LexerDfaKey, usize>,
877 accept_predictions: FxHashMap<usize, i32>,
878 edges: BTreeSet<LexerDfaEdge>,
882 cached_states: Vec<Option<Rc<LexerDfaCachedState>>>,
884 dense_edges: Vec<Option<Box<DenseEdgeRow>>>,
889 sparse_edges: FxHashMap<(usize, i32), LexerDfaCachedTransition>,
891 mode_starts: FxHashMap<i32, usize>,
892}
893
894#[derive(Debug, Default)]
897pub(crate) struct LexerPredictionStore {
898 pub(crate) contexts: LexerContextArena,
899 pub(crate) workspace: PredictionWorkspace,
900}
901
902#[repr(transparent)]
904#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
905pub(crate) struct LexerContextId(u32);
906
907pub(crate) const EMPTY_LEXER_CONTEXT: LexerContextId = LexerContextId(0);
908
909#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
915pub(crate) enum LexerContextNode {
916 Empty,
917 Singleton {
918 parent: LexerContextId,
919 return_state: usize,
920 },
921 Union {
922 left: LexerContextId,
923 right: LexerContextId,
924 },
925}
926
927#[derive(Clone, Copy, Debug)]
928struct LexerContextRecord {
929 node: LexerContextNode,
930 path_set: ContextId,
931}
932
933#[derive(Debug)]
935pub(crate) struct LexerContextArena {
936 records: Vec<LexerContextRecord>,
937 ids: FxHashMap<LexerContextNode, LexerContextId>,
938 path_sets: ContextArena,
939}
940
941impl LexerContextArena {
942 pub(crate) fn new() -> Self {
943 let mut ids = FxHashMap::default();
944 ids.insert(LexerContextNode::Empty, EMPTY_LEXER_CONTEXT);
945 Self {
946 records: vec![LexerContextRecord {
947 node: LexerContextNode::Empty,
948 path_set: EMPTY_CONTEXT,
949 }],
950 ids,
951 path_sets: ContextArena::new(),
952 }
953 }
954
955 pub(crate) fn singleton(
956 &mut self,
957 parent: LexerContextId,
958 return_state: usize,
959 ) -> LexerContextId {
960 self.assert_valid(parent);
961 let node = LexerContextNode::Singleton {
962 parent,
963 return_state,
964 };
965 if let Some(&context) = self.ids.get(&node) {
966 return context;
967 }
968 let path_set = self
969 .path_sets
970 .singleton(self.record(parent).path_set, return_state);
971 self.intern(node, path_set)
972 }
973
974 pub(crate) fn merge(
975 &mut self,
976 left: LexerContextId,
977 right: LexerContextId,
978 workspace: &mut PredictionWorkspace,
979 ) -> LexerContextId {
980 self.assert_valid(left);
981 self.assert_valid(right);
982 if left == right {
983 return left;
984 }
985 let left_set = self.record(left).path_set;
986 let right_set = self.record(right).path_set;
987 let path_set = self.path_sets.merge(left_set, right_set, false, workspace);
988 if path_set == left_set {
989 return left;
990 }
991 let node = LexerContextNode::Union { left, right };
992 if let Some(&context) = self.ids.get(&node) {
993 return context;
994 }
995 self.intern(node, path_set)
996 }
997
998 pub(crate) fn node(&self, context: LexerContextId) -> LexerContextNode {
999 self.record(context).node
1000 }
1001
1002 #[cfg(test)]
1003 pub(crate) const fn len(&self) -> usize {
1004 self.records.len()
1005 }
1006
1007 fn intern(&mut self, node: LexerContextNode, path_set: ContextId) -> LexerContextId {
1008 let context = LexerContextId(
1009 u32::try_from(self.records.len()).expect("lexer context arena must fit in u32"),
1010 );
1011 self.records.push(LexerContextRecord { node, path_set });
1012 self.ids.insert(node, context);
1013 context
1014 }
1015
1016 fn record(&self, context: LexerContextId) -> &LexerContextRecord {
1017 self.assert_valid(context);
1018 &self.records[usize::try_from(context.0).expect("u32 lexer context ID fits in usize")]
1019 }
1020
1021 fn assert_valid(&self, context: LexerContextId) {
1022 assert!(
1023 usize::try_from(context.0).is_ok_and(|index| index < self.records.len()),
1024 "lexer context ID does not belong to this store"
1025 );
1026 }
1027}
1028
1029impl Default for LexerContextArena {
1030 fn default() -> Self {
1031 Self::new()
1032 }
1033}
1034
1035const DENSE_EDGE_SYMBOLS: usize = 128;
1037
1038type DenseEdgeRow = [LexerDfaCachedTransition; DENSE_EDGE_SYMBOLS];
1039
1040const EMPTY_DENSE_EDGE: LexerDfaCachedTransition = LexerDfaCachedTransition {
1043 target_state: usize::MAX,
1044 position_delta: 0,
1045};
1046
1047thread_local! {
1048 static SHARED_LEXER_DFA_CACHES: RefCell<HashMap<usize, Rc<RefCell<LexerDfaCache>>>> =
1051 RefCell::new(HashMap::new());
1052}
1053
1054#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
1059pub(crate) struct LexerDfaKey {
1060 configs: Vec<LexerDfaConfigKey>,
1061}
1062
1063impl LexerDfaKey {
1064 pub(crate) const fn new(configs: Vec<LexerDfaConfigKey>) -> Self {
1065 Self { configs }
1066 }
1067}
1068
1069#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
1071pub(crate) struct LexerDfaConfigKey {
1072 pub(crate) state: usize,
1073 pub(crate) alt_rule_index: Option<usize>,
1074 pub(crate) consumed_eof: bool,
1075 pub(crate) passed_non_greedy: bool,
1076 pub(crate) context: LexerContextId,
1077 pub(crate) actions: Vec<LexerDfaActionKey>,
1078}
1079
1080#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
1081pub(crate) struct LexerDfaActionKey {
1082 pub(crate) action_index: usize,
1083 pub(crate) position_delta: usize,
1084 pub(crate) rule_index: usize,
1085}
1086
1087impl LexerDfaConfigKey {
1088 pub(crate) const fn new(
1089 state: usize,
1090 alt_rule_index: Option<usize>,
1091 consumed_eof: bool,
1092 passed_non_greedy: bool,
1093 context: LexerContextId,
1094 actions: Vec<LexerDfaActionKey>,
1095 ) -> Self {
1096 Self {
1097 state,
1098 alt_rule_index,
1099 consumed_eof,
1100 passed_non_greedy,
1101 context,
1102 actions,
1103 }
1104 }
1105}
1106
1107#[derive(Clone, Copy, Debug)]
1108pub(crate) struct LexerDfaCachedTransition {
1109 pub(crate) target_state: usize,
1110 pub(crate) position_delta: usize,
1111}
1112
1113#[derive(Clone, Debug)]
1114pub(crate) struct LexerDfaCachedAccept {
1115 pub(crate) position_delta: usize,
1116 pub(crate) rule_index: usize,
1117 pub(crate) consumed_eof: bool,
1118 pub(crate) actions: Vec<LexerDfaActionKey>,
1119}
1120
1121#[derive(Clone, Debug)]
1122pub(crate) struct LexerDfaCachedState {
1123 pub(crate) has_semantic_context: bool,
1124 pub(crate) configs: Vec<LexerDfaConfigKey>,
1125 pub(crate) accept: Option<LexerDfaCachedAccept>,
1126}
1127
1128#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
1131struct LexerDfaEdge {
1132 from: usize,
1133 symbol: i32,
1134 to: usize,
1135}
1136
1137impl<I> BaseLexer<I>
1138where
1139 I: CharStream,
1140{
1141 pub fn new(input: I, data: RecognizerData) -> Self {
1142 let has_source_text = input.source_text().is_some();
1143 Self {
1144 input,
1145 data,
1146 has_source_text,
1147 mode: DEFAULT_MODE,
1148 mode_stack: Vec::new(),
1149 token_type: INVALID_TOKEN_TYPE,
1150 channel: DEFAULT_CHANNEL,
1151 token_start: 0,
1152 token_start_line: 1,
1153 token_start_column: 0,
1154 line: 1,
1155 column: 0,
1156 hit_eof: false,
1157 force_interpreted: false,
1158 errors: RefCell::new(Vec::new()),
1159 semantic_error_coordinates: RefCell::new(BTreeSet::new()),
1160 pending_tokens: VecDeque::new(),
1161 members: MemberEnv::new(),
1162 member_inits: Vec::new(),
1163 dfa_cache: Rc::new(RefCell::new(LexerDfaCache::default())),
1164 }
1165 }
1166
1167 #[must_use]
1174 pub fn with_initial_members(mut self, initial: impl IntoIterator<Item = (usize, i64)>) -> Self {
1175 self.member_inits = initial.into_iter().collect();
1176 self.members = MemberEnv::with_initial_scalars(self.member_inits.iter().copied());
1177 self
1178 }
1179
1180 pub fn reset(&mut self) {
1187 self.input.seek(0);
1188 self.mode = DEFAULT_MODE;
1189 self.mode_stack.clear();
1190 self.token_type = INVALID_TOKEN_TYPE;
1191 self.channel = DEFAULT_CHANNEL;
1192 self.token_start = 0;
1193 self.token_start_line = 1;
1194 self.token_start_column = 0;
1195 self.line = 1;
1196 self.column = 0;
1197 self.hit_eof = false;
1198 self.errors.get_mut().clear();
1199 self.semantic_error_coordinates.get_mut().clear();
1200 self.pending_tokens.clear();
1201 self.members
1206 .reset_to_initial(self.member_inits.iter().copied());
1207 }
1208
1209 pub fn set_input_stream(&mut self, input: I) {
1214 self.input = input;
1215 self.has_source_text = self.input.source_text().is_some();
1216 self.reset();
1217 }
1218
1219 #[must_use]
1229 pub fn with_shared_dfa(mut self, atn: &'static LexerAtn) -> Self {
1230 let ptr: *const LexerAtn = atn;
1231 let key = ptr as usize;
1232 self.dfa_cache = SHARED_LEXER_DFA_CACHES
1233 .with(|caches| Rc::clone(caches.borrow_mut().entry(key).or_insert_with(Rc::default)));
1234 self
1235 }
1236
1237 pub fn clear_dfa(&self) {
1243 let mut cache = self.dfa_cache.borrow_mut();
1244 let prediction = std::mem::take(&mut cache.prediction);
1247 *cache = LexerDfaCache {
1248 prediction,
1249 ..LexerDfaCache::default()
1250 };
1251 }
1252
1253 pub const fn input(&self) -> &I {
1254 &self.input
1255 }
1256
1257 pub const fn input_mut(&mut self) -> &mut I {
1258 &mut self.input
1259 }
1260
1261 pub fn begin_token(&mut self) {
1264 self.semantic_error_coordinates.get_mut().clear();
1265 self.token_type = INVALID_TOKEN_TYPE;
1266 self.channel = DEFAULT_CHANNEL;
1267 self.token_start = self.input.index();
1268 self.token_start_line = self.line;
1269 self.token_start_column = self.column;
1270 }
1271
1272 pub const fn token_start(&self) -> usize {
1274 self.token_start
1275 }
1276
1277 pub const fn token_start_line(&self) -> usize {
1279 self.token_start_line
1280 }
1281
1282 pub const fn token_start_column(&self) -> usize {
1284 self.token_start_column
1285 }
1286
1287 pub const fn token_type(&self) -> i32 {
1289 self.token_type
1290 }
1291
1292 pub const fn set_type(&mut self, token_type: i32) {
1294 self.token_type = token_type;
1295 }
1296
1297 pub const fn channel(&self) -> i32 {
1299 self.channel
1300 }
1301
1302 pub const fn set_channel(&mut self, channel: i32) {
1304 self.channel = channel;
1305 }
1306
1307 pub const fn skip(&mut self) {
1309 self.set_type(SKIP);
1310 }
1311
1312 pub const fn more(&mut self) {
1314 self.set_type(MORE);
1315 }
1316
1317 pub fn la(&mut self, offset: isize) -> i32 {
1320 self.input.la(offset)
1321 }
1322
1323 fn lookahead_at(&self, position: usize, offset: isize) -> i32 {
1324 if offset == 0 {
1325 return 0;
1326 }
1327 let absolute = if offset > 0 {
1328 position.checked_add((offset - 1).cast_unsigned())
1329 } else {
1330 offset
1331 .checked_neg()
1332 .and_then(|distance| usize::try_from(distance).ok())
1333 .and_then(|distance| position.checked_sub(distance))
1334 };
1335 let Some(index) = absolute.filter(|index| *index < self.input.size()) else {
1336 return EOF;
1337 };
1338 if let Some(symbol) = self.input.symbol_at(index) {
1339 return symbol;
1340 }
1341 self.input
1342 .text(TextInterval::new(index, index))
1343 .chars()
1344 .next()
1345 .map_or(EOF, |ch| u32::from(ch).cast_signed())
1346 }
1347
1348 pub fn consume_char(&mut self) {
1355 let la = self.input.la(1);
1356 if la == EOF {
1357 return;
1358 }
1359 self.input.consume();
1360 if char::from_u32(la.cast_unsigned()) == Some('\n') {
1361 self.line += 1;
1362 self.column = 0;
1363 } else {
1364 self.column += 1;
1365 }
1366 }
1367
1368 pub(crate) fn commit_position(&mut self, start: usize, target: usize) {
1371 self.reposition_from(start, self.line, self.column, target);
1372 }
1373
1374 fn reposition_from(&mut self, start: usize, line: usize, column: usize, target: usize) {
1375 let start = start.min(self.input.size());
1376 let target = target.max(start).min(self.input.size());
1377 if let Some(summary) = self.input.position_summary(start, target) {
1378 self.input.seek(target);
1379 (self.line, self.column) = summary.apply(line, column);
1380 #[cfg(feature = "perf-counters")]
1381 crate::perf::record_lexer_bulk_commit(target - start);
1382 return;
1383 }
1384
1385 self.input.seek(start);
1386 self.line = line;
1387 self.column = column;
1388 #[cfg(feature = "perf-counters")]
1389 let before = self.input.index();
1390 while self.input.index() < target && self.input.la(1) != EOF {
1391 self.consume_char();
1392 }
1393 #[cfg(feature = "perf-counters")]
1394 crate::perf::record_lexer_scalar_replay(self.input.index().saturating_sub(before));
1395 }
1396
1397 pub fn reset_accept_position(&mut self, index: usize) {
1404 let target = index.max(self.token_start);
1405 self.reposition_from(
1406 self.token_start,
1407 self.token_start_line,
1408 self.token_start_column,
1409 target,
1410 );
1411 }
1412
1413 pub fn set_token_start(&mut self, index: usize) -> bool {
1419 if index < self.token_start || index > self.input.index() {
1420 return false;
1421 }
1422 let (line, column) = self.position_at(index);
1423 self.token_start = index;
1424 self.token_start_line = line;
1425 self.token_start_column = column;
1426 true
1427 }
1428
1429 pub fn emit(
1437 &self,
1438 sink: &mut TokenSink<'_>,
1439 token_type: i32,
1440 channel: i32,
1441 text: Option<String>,
1442 ) -> Result<TokenId, TokenStoreError> {
1443 let stop = self.input.index().checked_sub(1).unwrap_or(usize::MAX);
1444 self.emit_with_stop(sink, token_type, channel, stop, text)
1445 }
1446
1447 pub fn emit_with_stop(
1453 &self,
1454 sink: &mut TokenSink<'_>,
1455 token_type: i32,
1456 channel: i32,
1457 stop: usize,
1458 text: Option<String>,
1459 ) -> Result<TokenId, TokenStoreError> {
1460 sink.push(self.token_spec_with_stop(token_type, channel, stop, text))
1461 }
1462
1463 fn token_spec_with_stop(
1464 &self,
1465 token_type: i32,
1466 channel: i32,
1467 stop: usize,
1468 text: Option<String>,
1469 ) -> TokenSpec {
1470 let text = text.or_else(|| {
1471 if stop == usize::MAX {
1472 Some("<EOF>".to_owned())
1473 } else {
1474 None
1475 }
1476 });
1477 let source_interval = if self.has_source_text
1478 && text.is_none()
1479 && stop != usize::MAX
1480 && self.token_start <= stop
1481 {
1482 self.input
1483 .byte_interval(TextInterval::new(self.token_start, stop))
1484 } else {
1485 None
1486 };
1487 let text = text.or_else(|| {
1488 source_interval
1489 .is_none()
1490 .then(|| self.input.text(TextInterval::new(self.token_start, stop)))
1491 });
1492 let (start_byte, stop_byte) = source_interval
1493 .or_else(|| self.token_byte_span(stop))
1494 .unwrap_or((self.token_start, self.token_start));
1495 TokenSpec {
1496 token_type,
1497 channel,
1498 start: self.token_start,
1499 stop,
1500 start_byte,
1501 stop_byte,
1502 line: self.token_start_line,
1503 column: self.token_start_column,
1504 text,
1505 source_backed: source_interval.is_some(),
1506 }
1507 }
1508
1509 pub fn enqueue_token(
1515 &mut self,
1516 token_type: i32,
1517 channel: i32,
1518 stop: usize,
1519 text: Option<String>,
1520 ) {
1521 let token = self.token_spec_with_stop(token_type, channel, stop, text);
1522 self.pending_tokens.push_back(token);
1523 }
1524
1525 pub(crate) fn emit_pending_token(
1526 &mut self,
1527 sink: &mut TokenSink<'_>,
1528 ) -> Result<Option<TokenId>, TokenStoreError> {
1529 self.pending_tokens
1530 .pop_front()
1531 .map(|token| sink.push(token))
1532 .transpose()
1533 }
1534
1535 pub(crate) fn emit_or_enqueue_with_stop(
1536 &mut self,
1537 sink: &mut TokenSink<'_>,
1538 stop: usize,
1539 text: Option<String>,
1540 ) -> Result<TokenId, TokenStoreError> {
1541 let token = self.token_spec_with_stop(self.token_type, self.channel, stop, text);
1542 self.emit_or_enqueue(sink, token)
1543 }
1544
1545 fn emit_or_enqueue(
1546 &mut self,
1547 sink: &mut TokenSink<'_>,
1548 token: TokenSpec,
1549 ) -> Result<TokenId, TokenStoreError> {
1550 if self.pending_tokens.is_empty() {
1551 return sink.push(token);
1552 }
1553 self.pending_tokens.push_back(token);
1554 self.emit_pending_token(sink)?
1555 .ok_or_else(|| unreachable!("the pending-token queue was just populated"))
1556 }
1557
1558 pub fn token_text(&self) -> String {
1561 self.token_text_until(self.input.index())
1562 }
1563
1564 pub fn token_text_until(&self, stop_exclusive: usize) -> String {
1572 if stop_exclusive <= self.token_start {
1573 return String::new();
1574 }
1575 self.input
1576 .text(TextInterval::new(self.token_start, stop_exclusive - 1))
1577 }
1578
1579 pub fn column_at(&self, position: usize) -> usize {
1582 self.position_at(position).1
1583 }
1584
1585 #[must_use]
1587 pub const fn members(&self) -> &MemberEnv {
1588 &self.members
1589 }
1590
1591 pub const fn members_mut(&mut self) -> &mut MemberEnv {
1593 &mut self.members
1594 }
1595
1596 fn position_at(&self, position: usize) -> (usize, usize) {
1597 let mut line = self.token_start_line;
1598 let mut column = self.token_start_column;
1599 if position <= self.token_start {
1600 return (line, column);
1601 }
1602 if let Some(summary) = self.input.position_summary(self.token_start, position) {
1603 return summary.apply(line, column);
1604 }
1605 for ch in self
1606 .input
1607 .text(TextInterval::new(self.token_start, position - 1))
1608 .chars()
1609 {
1610 if ch == '\n' {
1611 line += 1;
1612 column = 0;
1613 } else {
1614 column += 1;
1615 }
1616 }
1617 (line, column)
1618 }
1619
1620 pub fn eof_token(&self, sink: &mut TokenSink<'_>) -> Result<TokenId, TokenStoreError> {
1622 sink.push(self.eof_token_spec())
1623 }
1624
1625 pub(crate) fn emit_eof_or_pending(
1626 &mut self,
1627 sink: &mut TokenSink<'_>,
1628 ) -> Result<TokenId, TokenStoreError> {
1629 let token = self.eof_token_spec();
1630 self.emit_or_enqueue(sink, token)
1631 }
1632
1633 fn eof_token_spec(&self) -> TokenSpec {
1634 let byte_offset = self.eof_byte_offset().unwrap_or_else(|| self.input.index());
1635 TokenSpec::eof(self.input.index(), byte_offset, self.line, self.column)
1636 }
1637
1638 fn eof_byte_offset(&self) -> Option<usize> {
1639 self.byte_offset_at(self.input.index())
1640 }
1641
1642 fn token_byte_span(&self, stop: usize) -> Option<(usize, usize)> {
1643 if stop != usize::MAX && self.token_start <= stop {
1644 let (start_byte, stop_byte) = self
1645 .input
1646 .byte_interval(TextInterval::new(self.token_start, stop))?;
1647 return Some((start_byte, stop_byte));
1648 }
1649 let byte_offset = self.byte_offset_at(self.token_start)?;
1650 Some((byte_offset, byte_offset))
1651 }
1652
1653 fn byte_offset_at(&self, index: usize) -> Option<usize> {
1654 let byte_offset = if index == 0 {
1655 0
1656 } else {
1657 let previous = TextInterval::new(index - 1, index - 1);
1658 self.input.byte_interval(previous)?.1
1659 };
1660 Some(byte_offset)
1661 }
1662}
1663
1664impl<I> Recognizer for BaseLexer<I>
1665where
1666 I: CharStream,
1667{
1668 fn data(&self) -> &RecognizerData {
1669 &self.data
1670 }
1671
1672 fn data_mut(&mut self) -> &mut RecognizerData {
1673 &mut self.data
1674 }
1675}
1676
1677impl<I> Lexer for BaseLexer<I>
1678where
1679 I: CharStream,
1680{
1681 fn mode(&self) -> i32 {
1682 self.mode
1683 }
1684
1685 fn set_mode(&mut self, mode: i32) {
1686 self.mode = mode;
1687 }
1688
1689 fn push_mode(&mut self, mode: i32) {
1690 self.mode_stack.push(self.mode);
1691 self.mode = mode;
1692 }
1693
1694 fn pop_mode(&mut self) -> Option<i32> {
1695 let mode = self.mode_stack.pop()?;
1696 self.mode = mode;
1697 Some(mode)
1698 }
1699}
1700
1701impl<I> BaseLexer<I>
1702where
1703 I: CharStream,
1704{
1705 pub const fn line(&self) -> usize {
1706 self.line
1707 }
1708
1709 pub const fn column(&self) -> usize {
1710 self.column
1711 }
1712
1713 pub fn source_name(&self) -> &str {
1714 self.input.source_name()
1715 }
1716
1717 pub fn source_text(&self) -> Option<Rc<str>> {
1718 self.input.source_text()
1719 }
1720
1721 pub const fn hit_eof(&self) -> bool {
1722 self.hit_eof
1723 }
1724
1725 pub const fn set_hit_eof(&mut self, hit_eof: bool) {
1726 self.hit_eof = hit_eof;
1727 }
1728
1729 pub const fn set_force_interpreted(&mut self, force_interpreted: bool) {
1737 self.force_interpreted = force_interpreted;
1738 }
1739
1740 pub const fn force_interpreted(&self) -> bool {
1742 self.force_interpreted
1743 }
1744
1745 pub fn record_error(&self, line: usize, column: usize, message: impl Into<String>) {
1748 self.errors
1749 .borrow_mut()
1750 .push(TokenSourceError::new(line, column, message));
1751 }
1752
1753 pub fn record_semantic_error(&self, action: bool, rule_index: usize, coordinate_index: usize) {
1755 let kind = u8::from(action);
1756 if !self.semantic_error_coordinates.borrow_mut().insert((
1757 kind,
1758 rule_index,
1759 coordinate_index,
1760 self.token_start,
1761 )) {
1762 return;
1763 }
1764 let label = if action { "action" } else { "predicate" };
1765 self.record_error(
1766 self.token_start_line,
1767 self.token_start_column,
1768 format!("unhandled lexer semantic {label}: rule={rule_index} index={coordinate_index}"),
1769 );
1770 }
1771
1772 pub fn drain_errors(&mut self) -> Vec<TokenSourceError> {
1774 std::mem::take(self.errors.get_mut())
1775 }
1776
1777 pub(crate) fn lexer_prediction_store(&self) -> RefMut<'_, LexerPredictionStore> {
1780 RefMut::map(self.dfa_cache.borrow_mut(), |cache| &mut cache.prediction)
1781 }
1782
1783 pub(crate) fn reset_lexer_prediction_workspace(&self) {
1786 self.dfa_cache.borrow_mut().prediction.workspace.reset();
1787 }
1788
1789 #[cfg(test)]
1790 pub(crate) fn lexer_dfa_cache_shape(&self) -> (usize, usize, usize, usize) {
1791 let cache = self.dfa_cache.borrow();
1792 let cached_states = cache.cached_states.iter().flatten().count();
1793 let cached_transitions = cache
1794 .dense_edges
1795 .iter()
1796 .flatten()
1797 .map(|row| {
1798 row.iter()
1799 .filter(|transition| transition.target_state != usize::MAX)
1800 .count()
1801 })
1802 .sum::<usize>()
1803 + cache.sparse_edges.len();
1804 let max_configs = cache
1805 .cached_states
1806 .iter()
1807 .flatten()
1808 .map(|state| state.configs.len())
1809 .max()
1810 .unwrap_or(0);
1811 let contexts = cache.prediction.contexts.len();
1812 (cached_states, cached_transitions, max_configs, contexts)
1813 }
1814
1815 pub(crate) fn lexer_dfa_state(
1818 &self,
1819 key: LexerDfaKey,
1820 accept_prediction: Option<i32>,
1821 ) -> usize {
1822 let mut cache = self.dfa_cache.borrow_mut();
1823 let next = cache.state_numbers.len();
1824 let state = *cache.state_numbers.entry(key).or_insert(next);
1825 if let Some(prediction) = accept_prediction {
1826 cache.accept_predictions.insert(state, prediction);
1827 }
1828 state
1829 }
1830
1831 pub fn record_lexer_dfa_edge(&self, from: usize, symbol: i32, to: usize) {
1833 self.dfa_cache
1834 .borrow_mut()
1835 .edges
1836 .insert(LexerDfaEdge { from, symbol, to });
1837 }
1838
1839 pub(crate) fn cached_lexer_dfa_transition(
1840 &self,
1841 state: usize,
1842 symbol: i32,
1843 ) -> Option<LexerDfaCachedTransition> {
1844 let cache = self.dfa_cache.borrow();
1845 if let Ok(sym) = usize::try_from(symbol)
1846 && sym < DENSE_EDGE_SYMBOLS
1847 {
1848 let transition = cache.dense_edges.get(state)?.as_ref()?[sym];
1849 return (transition.target_state != usize::MAX).then_some(transition);
1850 }
1851 cache.sparse_edges.get(&(state, symbol)).copied()
1852 }
1853
1854 pub(crate) fn cache_lexer_dfa_transition(
1855 &self,
1856 state: usize,
1857 symbol: i32,
1858 transition: LexerDfaCachedTransition,
1859 ) {
1860 let mut cache = self.dfa_cache.borrow_mut();
1861 if let Ok(sym) = usize::try_from(symbol)
1862 && sym < DENSE_EDGE_SYMBOLS
1863 {
1864 if cache.dense_edges.len() <= state {
1865 cache.dense_edges.resize_with(state + 1, || None);
1866 }
1867 let row = cache.dense_edges[state]
1868 .get_or_insert_with(|| Box::new([EMPTY_DENSE_EDGE; DENSE_EDGE_SYMBOLS]));
1869 if row[sym].target_state == usize::MAX {
1871 row[sym] = transition;
1872 }
1873 return;
1874 }
1875 cache
1876 .sparse_edges
1877 .entry((state, symbol))
1878 .or_insert(transition);
1879 }
1880
1881 pub(crate) fn cached_lexer_dfa_state(&self, state: usize) -> Option<Rc<LexerDfaCachedState>> {
1882 self.dfa_cache
1883 .borrow()
1884 .cached_states
1885 .get(state)
1886 .cloned()
1887 .flatten()
1888 }
1889
1890 pub(crate) fn cache_lexer_dfa_state(&self, state: usize, cached_state: LexerDfaCachedState) {
1891 let mut cache = self.dfa_cache.borrow_mut();
1892 if cache.cached_states.len() <= state {
1893 cache.cached_states.resize_with(state + 1, || None);
1894 }
1895 cache.cached_states[state].get_or_insert_with(|| Rc::new(cached_state));
1896 }
1897
1898 pub(crate) fn cached_lexer_mode_start(&self, mode: i32) -> Option<usize> {
1899 self.dfa_cache.borrow().mode_starts.get(&mode).copied()
1900 }
1901
1902 pub(crate) fn cache_lexer_mode_start(&self, mode: i32, state: usize) {
1903 self.dfa_cache
1904 .borrow_mut()
1905 .mode_starts
1906 .entry(mode)
1907 .or_insert(state);
1908 }
1909
1910 pub fn lexer_dfa_string(&self) -> String {
1912 let mut out = String::new();
1913 let cache = self.dfa_cache.borrow();
1914 for edge in &cache.edges {
1915 let Some(label) = lexer_dfa_edge_label(edge.symbol) else {
1916 continue;
1917 };
1918 out.push_str(&self.lexer_dfa_state_string(edge.from));
1919 out.push('-');
1920 out.push_str(&label);
1921 out.push_str("->");
1922 out.push_str(&self.lexer_dfa_state_string(edge.to));
1923 out.push('\n');
1924 }
1925 out
1926 }
1927
1928 fn lexer_dfa_state_string(&self, state: usize) -> String {
1929 self.dfa_cache
1930 .borrow()
1931 .accept_predictions
1932 .get(&state)
1933 .map_or_else(
1934 || format!("s{state}"),
1935 |prediction| format!(":s{state}=>{prediction}"),
1936 )
1937 }
1938}
1939
1940fn lexer_dfa_edge_label(symbol: i32) -> Option<String> {
1941 char::from_u32(symbol.cast_unsigned()).map(|ch| format!("'{ch}'"))
1942}
1943
1944#[cfg(test)]
1945#[allow(clippy::disallowed_methods)] mod tests {
1947 use super::*;
1948 use crate::char_stream::InputStream;
1949 use crate::int_stream::IntStream;
1950 use crate::recognizer::RecognizerData;
1951 use crate::token::{DEFAULT_CHANNEL, Token, TokenStore};
1952 use crate::vocabulary::Vocabulary;
1953
1954 #[derive(Clone, Debug)]
1955 struct UnsharedInput(InputStream);
1956
1957 impl IntStream for UnsharedInput {
1958 fn consume(&mut self) {
1959 self.0.consume();
1960 }
1961
1962 fn la(&mut self, offset: isize) -> i32 {
1963 self.0.la(offset)
1964 }
1965
1966 fn index(&self) -> usize {
1967 self.0.index()
1968 }
1969
1970 fn seek(&mut self, index: usize) {
1971 self.0.seek(index);
1972 }
1973
1974 fn size(&self) -> usize {
1975 self.0.size()
1976 }
1977
1978 fn source_name(&self) -> &str {
1979 self.0.source_name()
1980 }
1981 }
1982
1983 impl CharStream for UnsharedInput {
1984 fn text(&self, interval: TextInterval) -> String {
1985 self.0.text(interval)
1986 }
1987
1988 fn byte_interval(&self, interval: TextInterval) -> Option<(usize, usize)> {
1989 self.0.byte_interval(interval)
1990 }
1991 }
1992
1993 #[test]
1994 fn eof_token_uses_utf8_byte_offset_after_non_ascii_input() {
1995 let data = RecognizerData::new(
1996 "T",
1997 Vocabulary::new(
1998 std::iter::empty::<Option<&str>>(),
1999 std::iter::empty::<Option<&str>>(),
2000 std::iter::empty::<Option<&str>>(),
2001 ),
2002 );
2003 let mut lexer = BaseLexer::new(InputStream::new("β"), data);
2004 lexer.consume_char();
2005
2006 let mut store = TokenStore::new(lexer.source_text(), lexer.source_name());
2007 let mut sink = TokenSink::new(&mut store);
2008 let id = lexer.eof_token(&mut sink).expect("test token should fit");
2009 let token = sink.view(id).expect("emitted token should exist");
2010
2011 insta::assert_compact_debug_snapshot!(
2014 (token.start(), token.stop(), token.text(), token.byte_span()),
2015 @r#"(1, 0, Some("<EOF>"), 2..2)"#
2016 );
2017 }
2018
2019 #[test]
2020 fn eof_rule_token_uses_utf8_byte_offset_after_non_ascii_input() {
2021 let data = RecognizerData::new(
2022 "T",
2023 Vocabulary::new(
2024 std::iter::empty::<Option<&str>>(),
2025 std::iter::empty::<Option<&str>>(),
2026 std::iter::empty::<Option<&str>>(),
2027 ),
2028 );
2029 let mut lexer = BaseLexer::new(InputStream::new("β"), data);
2030 lexer.consume_char();
2031 lexer.begin_token();
2032
2033 let mut store = TokenStore::new(lexer.source_text(), lexer.source_name());
2034 let mut sink = TokenSink::new(&mut store);
2035 let id = lexer
2036 .emit_with_stop(&mut sink, 1, DEFAULT_CHANNEL, 0, Some("<EOF>".to_owned()))
2037 .expect("test token should fit");
2038 let token = sink.view(id).expect("emitted token should exist");
2039
2040 insta::assert_compact_debug_snapshot!(
2043 (token.start(), token.stop(), token.text(), token.byte_span()),
2044 @r#"(1, 0, Some("<EOF>"), 2..2)"#
2045 );
2046 }
2047
2048 #[test]
2049 fn emit_implicit_text_uses_utf8_byte_span_for_non_ascii_input() {
2050 let data = RecognizerData::new(
2051 "T",
2052 Vocabulary::new(
2053 std::iter::empty::<Option<&str>>(),
2054 std::iter::empty::<Option<&str>>(),
2055 std::iter::empty::<Option<&str>>(),
2056 ),
2057 );
2058 let mut lexer = BaseLexer::new(InputStream::new("β"), data);
2059 lexer.begin_token();
2060 lexer.consume_char();
2061
2062 let mut store = TokenStore::new(lexer.source_text(), lexer.source_name());
2063 let mut sink = TokenSink::new(&mut store);
2064 let id = lexer
2065 .emit(&mut sink, 1, DEFAULT_CHANNEL, None)
2066 .expect("test token should fit");
2067 let token = sink.view(id).expect("emitted token should exist");
2068
2069 insta::assert_compact_debug_snapshot!(
2072 (token.start(), token.stop(), token.text(), token.byte_span()),
2073 @r#"(0, 0, Some("β"), 0..2)"#
2074 );
2075 }
2076
2077 #[test]
2078 fn emit_falls_back_to_explicit_text_without_shareable_source() {
2079 let data = RecognizerData::new(
2080 "T",
2081 Vocabulary::new(
2082 std::iter::empty::<Option<&str>>(),
2083 std::iter::empty::<Option<&str>>(),
2084 std::iter::empty::<Option<&str>>(),
2085 ),
2086 );
2087 let mut lexer = BaseLexer::new(UnsharedInput(InputStream::new("β")), data);
2088 lexer.begin_token();
2089 lexer.consume_char();
2090
2091 let mut store = TokenStore::new(lexer.source_text(), lexer.source_name());
2092 let mut sink = TokenSink::new(&mut store);
2093 let id = lexer
2094 .emit(&mut sink, 1, DEFAULT_CHANNEL, None)
2095 .expect("unshared input should emit explicit token text");
2096 let token = sink.view(id).expect("emitted token should exist");
2097
2098 assert_eq!(token.text(), Some("β"));
2099 assert_eq!(token.byte_span(), 0..2);
2100 }
2101
2102 #[test]
2103 fn position_commits_and_rewinds_preserve_line_and_column() {
2104 let data = RecognizerData::new(
2105 "T",
2106 Vocabulary::new(
2107 std::iter::empty::<Option<&str>>(),
2108 std::iter::empty::<Option<&str>>(),
2109 std::iter::empty::<Option<&str>>(),
2110 ),
2111 );
2112 let mut lexer = BaseLexer::new(InputStream::new("ab\nγd"), data);
2113 lexer.begin_token();
2114
2115 lexer.commit_position(0, 5);
2116 assert_eq!(lexer.input().index(), 5);
2117 assert_eq!((lexer.line(), lexer.column()), (2, 2));
2118 assert_eq!(lexer.column_at(2), 2);
2119 assert_eq!(lexer.column_at(4), 1);
2120
2121 lexer.reset_accept_position(3);
2122 assert_eq!(lexer.input().index(), 3);
2123 assert_eq!((lexer.line(), lexer.column()), (2, 0));
2124 }
2125
2126 #[test]
2127 fn custom_stream_position_commit_replays_without_fast_path_methods() {
2128 let data = RecognizerData::new(
2129 "T",
2130 Vocabulary::new(
2131 std::iter::empty::<Option<&str>>(),
2132 std::iter::empty::<Option<&str>>(),
2133 std::iter::empty::<Option<&str>>(),
2134 ),
2135 );
2136 let mut lexer = BaseLexer::new(UnsharedInput(InputStream::new("a\nb")), data);
2137 lexer.begin_token();
2138
2139 lexer.commit_position(0, 3);
2140 assert_eq!(lexer.input().index(), 3);
2141 assert_eq!((lexer.line(), lexer.column()), (2, 1));
2142 }
2143
2144 #[test]
2145 fn semantic_hook_errors_are_deduplicated_per_token_coordinate() {
2146 let data = RecognizerData::new(
2147 "T",
2148 Vocabulary::new(
2149 std::iter::empty::<Option<&str>>(),
2150 std::iter::empty::<Option<&str>>(),
2151 std::iter::empty::<Option<&str>>(),
2152 ),
2153 );
2154 let mut lexer = BaseLexer::new(InputStream::new("a"), data);
2155 lexer.begin_token();
2156 lexer.record_semantic_error(false, 3, 7);
2157 lexer.record_semantic_error(false, 3, 7);
2158
2159 let errors = lexer.drain_errors();
2160 insta::assert_compact_debug_snapshot!(errors, @r#"[TokenSourceError { line: 1, column: 0, message: "unhandled lexer semantic predicate: rule=3 index=7" }]"#);
2161
2162 lexer.begin_token();
2163 lexer.record_semantic_error(false, 3, 7);
2164 assert_eq!(
2165 lexer.drain_errors().len(),
2166 1,
2167 "deduplication resets at every token boundary, even after rewinding"
2168 );
2169 }
2170
2171 #[test]
2172 fn set_input_stream_replaces_input_and_resets_transient_state() {
2173 let data = RecognizerData::new(
2174 "T",
2175 Vocabulary::new(
2176 std::iter::empty::<Option<&str>>(),
2177 std::iter::empty::<Option<&str>>(),
2178 std::iter::empty::<Option<&str>>(),
2179 ),
2180 );
2181 let mut lexer = BaseLexer::new(InputStream::new("old"), data);
2182 lexer.consume_char();
2183 lexer.set_mode(7);
2184 lexer.push_mode(9);
2185 lexer.set_type(3);
2186 lexer.record_error(1, 0, "stale");
2187
2188 lexer.set_input_stream(InputStream::with_source_name("new", "replacement"));
2189
2190 assert_eq!(lexer.input().index(), 0);
2191 assert_eq!(lexer.input().size(), 3);
2192 assert_eq!(lexer.source_name(), "replacement");
2193 assert_eq!(lexer.source_text().as_deref(), Some("new"));
2194 assert_eq!(lexer.mode(), DEFAULT_MODE);
2195 assert_eq!(lexer.token_type(), INVALID_TOKEN_TYPE);
2196 assert_eq!((lexer.line(), lexer.column()), (1, 0));
2197 assert!(!lexer.hit_eof());
2198 assert!(lexer.drain_errors().is_empty());
2199 assert!(lexer.pop_mode().is_none());
2200 }
2201
2202 #[test]
2203 fn clear_dfa_invalidates_all_lexers_sharing_the_cache() {
2204 let atn = Box::leak(Box::new(LexerAtn::new(1)));
2205 let data = || {
2206 RecognizerData::new(
2207 "T",
2208 Vocabulary::new(
2209 std::iter::empty::<Option<&str>>(),
2210 std::iter::empty::<Option<&str>>(),
2211 std::iter::empty::<Option<&str>>(),
2212 ),
2213 )
2214 };
2215 let first = BaseLexer::new(InputStream::new("a"), data()).with_shared_dfa(atn);
2216 let second = BaseLexer::new(InputStream::new("a"), data()).with_shared_dfa(atn);
2217 let state = first.lexer_dfa_state(LexerDfaKey::new(Vec::new()), Some(1));
2218 first.record_lexer_dfa_edge(state, i32::from(b'a'), state);
2219
2220 assert!(!second.lexer_dfa_string().is_empty());
2221 first.clear_dfa();
2222 assert!(first.lexer_dfa_string().is_empty());
2223 assert!(second.lexer_dfa_string().is_empty());
2224 }
2225
2226 mod member_slots {
2230 pub(super) const INTERPOLATED_STRING_LEVEL: usize = 0;
2231 pub(super) const VERBATIUM: usize = 1;
2232 pub(super) const INTERPOLATED_VERBATIUMS: usize = 0;
2233 pub(super) const CURLY_LEVELS: usize = 1;
2234 }
2235
2236 fn member_state_lexer() -> BaseLexer<InputStream> {
2237 let data = RecognizerData::new(
2238 "CSharpLexer",
2239 Vocabulary::new(
2240 std::iter::empty::<Option<&str>>(),
2241 std::iter::empty::<Option<&str>>(),
2242 std::iter::empty::<Option<&str>>(),
2243 ),
2244 );
2245 BaseLexer::new(InputStream::new("$\"{x}\""), data)
2246 }
2247
2248 #[test]
2254 fn lexer_stack_members_track_nested_interpolation_state() {
2255 use member_slots::{INTERPOLATED_STRING_LEVEL, INTERPOLATED_VERBATIUMS};
2256
2257 let mut lexer = member_state_lexer();
2258 let members = lexer.members_mut();
2259
2260 members.add_scalar(INTERPOLATED_STRING_LEVEL, 1);
2262 members.push_stack(INTERPOLATED_VERBATIUMS, 0);
2263 assert_eq!(members.stack_top(INTERPOLATED_VERBATIUMS), Some(0));
2264 assert_eq!(members.scalar(INTERPOLATED_STRING_LEVEL), Some(1));
2265
2266 members.add_scalar(INTERPOLATED_STRING_LEVEL, 1);
2268 members.push_stack(INTERPOLATED_VERBATIUMS, 1);
2269 assert_eq!(members.stack_top(INTERPOLATED_VERBATIUMS), Some(1));
2270 assert_eq!(members.stack_len(INTERPOLATED_VERBATIUMS), 2);
2271
2272 members.add_scalar(INTERPOLATED_STRING_LEVEL, -1);
2275 assert_eq!(members.pop_stack(INTERPOLATED_VERBATIUMS), Some(1));
2276 assert_eq!(members.stack_top(INTERPOLATED_VERBATIUMS), Some(0));
2277
2278 members.add_scalar(INTERPOLATED_STRING_LEVEL, -1);
2281 assert_eq!(members.pop_stack(INTERPOLATED_VERBATIUMS), Some(0));
2282 assert_eq!(members.stack_top(INTERPOLATED_VERBATIUMS), None);
2283 assert_eq!(members.scalar(INTERPOLATED_STRING_LEVEL), Some(0));
2284 }
2285
2286 #[test]
2289 fn lexer_reset_clears_member_state() {
2290 use member_slots::{CURLY_LEVELS, INTERPOLATED_STRING_LEVEL};
2291
2292 let mut lexer = member_state_lexer();
2293 lexer.members_mut().add_scalar(INTERPOLATED_STRING_LEVEL, 2);
2294 lexer.members_mut().push_stack(CURLY_LEVELS, 1);
2295 assert!(!lexer.members().is_empty());
2296
2297 lexer.reset();
2298
2299 assert!(lexer.members().is_empty(), "reset must clear member state");
2300 assert_eq!(lexer.members().scalar(INTERPOLATED_STRING_LEVEL), None);
2301 assert_eq!(lexer.members().stack_top(CURLY_LEVELS), None);
2302 }
2303
2304 #[test]
2309 fn lexer_declared_initial_members_survive_construction_and_reset() {
2310 use member_slots::{CURLY_LEVELS, INTERPOLATED_STRING_LEVEL, VERBATIUM};
2311
2312 let mut lexer = member_state_lexer().with_initial_members([(VERBATIUM, 1)]);
2313 assert_eq!(lexer.members().scalar(VERBATIUM), Some(1));
2314
2315 lexer.members_mut().set_scalar(VERBATIUM, 0);
2317 lexer.members_mut().add_scalar(INTERPOLATED_STRING_LEVEL, 3);
2318 lexer.members_mut().push_stack(CURLY_LEVELS, 1);
2319
2320 lexer.reset();
2321
2322 assert_eq!(lexer.members().scalar(VERBATIUM), Some(1));
2324 assert_eq!(lexer.members().scalar(INTERPOLATED_STRING_LEVEL), None);
2326 assert_eq!(lexer.members().stack_len(CURLY_LEVELS), 0);
2327 }
2328
2329 #[test]
2333 fn lexer_predicate_context_cannot_mutate_member_state() {
2334 use member_slots::{INTERPOLATED_VERBATIUMS, VERBATIUM};
2335
2336 let mut lexer = member_state_lexer();
2337 lexer.members_mut().set_scalar(VERBATIUM, 1);
2338 lexer.members_mut().push_stack(INTERPOLATED_VERBATIUMS, 1);
2339
2340 let mut ctx = LexerSemCtx::new(&lexer, 0, 0, 0);
2341 assert_eq!(ctx.member_int(VERBATIUM), Some(1));
2343 assert_eq!(ctx.member_stack_top(INTERPOLATED_VERBATIUMS), Some(1));
2344 assert_eq!(ctx.member_stack_len(INTERPOLATED_VERBATIUMS), 1);
2345 assert!(!ctx.set_member_int(VERBATIUM, 0));
2347 assert!(!ctx.push_member(INTERPOLATED_VERBATIUMS, 0));
2348 assert_eq!(ctx.pop_member(INTERPOLATED_VERBATIUMS), None);
2349 assert_eq!(ctx.add_member_int(VERBATIUM, 5), None);
2350
2351 assert_eq!(lexer.members().scalar(VERBATIUM), Some(1));
2352 assert_eq!(lexer.members().stack_len(INTERPOLATED_VERBATIUMS), 1);
2353 }
2354
2355 #[test]
2359 fn lexer_semantics_evaluates_stack_guards_written_by_lowered_actions() {
2360 use crate::semir::{AStmt, PExpr, SemIr};
2361 use member_slots::INTERPOLATED_VERBATIUMS;
2362
2363 let mut ir = SemIr::new();
2364 let top = ir.expr(PExpr::MemberTop(INTERPOLATED_VERBATIUMS));
2366 let not_top = ir.expr(PExpr::Not(top));
2368 let yes = ir.expr(PExpr::Bool(true));
2370 let push_verbatim = ir.stmt(AStmt::PushMember(INTERPOLATED_VERBATIUMS, yes));
2371 let pop = ir.stmt(AStmt::PopMember(INTERPOLATED_VERBATIUMS));
2372
2373 let semantics = LexerSemantics {
2374 ir,
2375 predicates: vec![
2376 LexerSemanticPredicate {
2377 rule_index: 1,
2378 pred_index: 0,
2379 expr: top,
2380 },
2381 LexerSemanticPredicate {
2382 rule_index: 2,
2383 pred_index: 0,
2384 expr: not_top,
2385 },
2386 ],
2387 actions: vec![
2388 LexerSemanticAction {
2389 rule_index: 0,
2390 action_index: 0,
2391 stmt: push_verbatim,
2392 },
2393 LexerSemanticAction {
2394 rule_index: 3,
2395 action_index: 0,
2396 stmt: pop,
2397 },
2398 ],
2399 };
2400
2401 let verbatim_guard = LexerPredicate::new(1, 0, 0);
2402 let regular_guard = LexerPredicate::new(2, 0, 0);
2403 let mut lexer = member_state_lexer();
2404
2405 assert_eq!(
2408 semantics.eval_predicate(&lexer, verbatim_guard),
2409 Some(false)
2410 );
2411 assert_eq!(semantics.eval_predicate(&lexer, regular_guard), Some(true));
2412
2413 assert!(semantics.exec_action(&mut lexer, LexerCustomAction::new(0, 0, 0)));
2415 assert_eq!(semantics.eval_predicate(&lexer, verbatim_guard), Some(true));
2416 assert_eq!(semantics.eval_predicate(&lexer, regular_guard), Some(false));
2417
2418 assert!(semantics.exec_action(&mut lexer, LexerCustomAction::new(3, 0, 0)));
2420 assert_eq!(
2421 semantics.eval_predicate(&lexer, verbatim_guard),
2422 Some(false)
2423 );
2424 assert_eq!(semantics.eval_predicate(&lexer, regular_guard), Some(true));
2425
2426 assert_eq!(
2429 semantics.eval_predicate(&lexer, LexerPredicate::new(9, 9, 0)),
2430 None
2431 );
2432 assert!(!semantics.exec_action(&mut lexer, LexerCustomAction::new(9, 9, 0)));
2433 }
2434}