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