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