1use std::collections::HashMap;
21use std::hash::BuildHasherDefault;
22
23use crate::atn::lexer::{
24 LexerConfig, best_accept, epsilon_closure, lexer_action_belongs_to_accept,
25 prune_after_accepts, set_config_state,
26};
27use crate::atn::{Atn, Transition};
28use crate::int_stream::EOF;
29use crate::lexer::{LexerDfaActionKey, LexerDfaConfigKey, LexerDfaKey};
30use crate::prediction::PredictionFxHasher;
31
32#[allow(clippy::disallowed_types)]
33type FxHashMap<K, V> = HashMap<K, V, BuildHasherDefault<PredictionFxHasher>>;
34
35const MIN_CHAR_VALUE: i32 = 0;
36const MAX_CHAR_VALUE: i32 = 0x0010_FFFF;
37
38pub(super) const DEAD_STATE: u16 = u16::MAX;
40
41pub(super) const ESCAPE_STATE: u16 = u16::MAX - 1;
43
44const MAX_MODE_STATES: usize = 4096;
47
48const MAX_STACK_DEPTH: usize = 32;
51
52const MAX_ACTION_TRACES: usize = 16;
56
57const ASCII_EDGE_SYMBOLS: usize = 128;
59const ASCII_EDGE_LIMIT: i32 = 128;
61
62#[derive(Clone, Debug)]
69pub struct CompiledLexerDfa {
70 mode_starts: Vec<Option<u16>>,
71 states: Vec<CompiledLexerState>,
72 ascii_rows: Vec<[u16; ASCII_EDGE_SYMBOLS]>,
73 wide_rows: Vec<Box<[WideRange]>>,
74 accepts: Vec<CompiledLexerAccept>,
75}
76
77#[derive(Clone, Copy, Debug)]
80struct CompiledLexerState {
81 ascii_row: u32,
82 wide_row: u32,
83 eof_target: u16,
84 accept: u32,
86}
87
88#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
90struct WideRange {
91 low: u32,
92 high: u32,
93 target: u16,
94}
95
96#[derive(Clone, Debug)]
99pub(super) struct CompiledLexerAccept {
100 pub(super) rule_index: usize,
101 pub(super) consumed_eof: bool,
102 pub(super) actions: Vec<CompiledLexerActionTrace>,
103}
104
105#[derive(Clone, Copy, Debug)]
108pub(super) struct CompiledLexerActionTrace {
109 pub(super) action_index: usize,
110 pub(super) rule_index: usize,
111 pub(super) behind: usize,
113}
114
115impl CompiledLexerDfa {
116 pub fn compile(atn: &Atn) -> Self {
119 let mut dfa = Self {
120 mode_starts: Vec::new(),
121 states: Vec::new(),
122 ascii_rows: Vec::new(),
123 wide_rows: Vec::new(),
124 accepts: Vec::new(),
125 };
126 let mut pools = RowPools::default();
127 for mode in 0..atn.mode_to_start_state().len() {
128 let start = build_mode(atn, mode, &mut dfa, &mut pools);
129 dfa.mode_starts.push(start);
130 }
131 dfa
132 }
133
134 pub fn has_compiled_modes(&self) -> bool {
136 self.mode_starts.iter().any(Option::is_some)
137 }
138
139 pub const fn state_count(&self) -> usize {
141 self.states.len()
142 }
143
144 pub fn compiled_mode_flags(&self) -> Vec<bool> {
146 self.mode_starts.iter().map(Option::is_some).collect()
147 }
148
149 pub fn mode_state_counts(&self) -> Vec<usize> {
151 let mut starts: Vec<usize> = self
152 .mode_starts
153 .iter()
154 .flatten()
155 .map(|&start| usize::from(start))
156 .collect();
157 starts.push(self.states.len());
158 starts.windows(2).map(|pair| pair[1] - pair[0]).collect()
159 }
160
161 pub(super) fn mode_start(&self, mode: i32) -> Option<u16> {
164 let mode = usize::try_from(mode).ok()?;
165 self.mode_starts.get(mode).copied().flatten()
166 }
167
168 pub(super) fn accept(&self, state: u16) -> Option<&CompiledLexerAccept> {
169 self.accepts
170 .get(self.states[usize::from(state)].accept as usize)
171 }
172
173 pub(super) fn char_target(&self, state: u16, symbol: i32) -> u16 {
175 let compiled = &self.states[usize::from(state)];
176 let code_point = symbol.cast_unsigned();
177 if let Ok(ascii) = usize::try_from(symbol)
178 && ascii < ASCII_EDGE_SYMBOLS
179 {
180 return self.ascii_rows[compiled.ascii_row as usize][ascii];
181 }
182 let row = &self.wide_rows[compiled.wide_row as usize];
183 match row.binary_search_by(|range| range.low.cmp(&code_point)) {
184 Ok(found) => row[found].target,
185 Err(insert) => {
186 if insert > 0 && row[insert - 1].high >= code_point {
187 row[insert - 1].target
188 } else {
189 DEAD_STATE
190 }
191 }
192 }
193 }
194
195 pub(super) fn eof_target(&self, state: u16) -> u16 {
197 self.states[usize::from(state)].eof_target
198 }
199
200 pub fn serialize(&self) -> Vec<u32> {
207 let wide_words: usize = self.wide_rows.iter().map(|row| 1 + row.len() * 3).sum();
212 let accept_words: usize = self
213 .accepts
214 .iter()
215 .map(|accept| 3 + accept.actions.len() * 3)
216 .sum();
217 let capacity = 6
218 + self.mode_starts.len()
219 + self.states.len() * 4
220 + self.ascii_rows.len() * (ASCII_EDGE_SYMBOLS / 2)
221 + wide_words
222 + accept_words;
223 let mut out = Vec::with_capacity(capacity);
224 out.push(SERIALIZED_TAG);
225 out.push(self.mode_starts.len() as u32);
226 for start in &self.mode_starts {
227 out.push(start.map_or(u32::MAX, u32::from));
228 }
229 out.push(self.states.len() as u32);
230 for state in &self.states {
231 out.push(state.ascii_row);
232 out.push(state.wide_row);
233 out.push(u32::from(state.eof_target));
234 out.push(state.accept);
235 }
236 out.push(self.ascii_rows.len() as u32);
237 for row in &self.ascii_rows {
238 for pair in row.chunks(2) {
239 out.push(u32::from(pair[0]) | (u32::from(pair[1]) << 16));
240 }
241 }
242 out.push(self.wide_rows.len() as u32);
243 for row in &self.wide_rows {
244 out.push(row.len() as u32);
245 for range in &**row {
246 out.push(range.low);
247 out.push(range.high);
248 out.push(u32::from(range.target));
249 }
250 }
251 out.push(self.accepts.len() as u32);
252 for accept in &self.accepts {
253 out.push(accept.rule_index as u32);
254 out.push(u32::from(accept.consumed_eof));
255 out.push(accept.actions.len() as u32);
256 for action in &accept.actions {
257 out.push(action.action_index as u32);
258 out.push(action.rule_index as u32);
259 out.push(action.behind as u32);
260 }
261 }
262 debug_assert_eq!(out.len(), capacity, "serialized stream fills its capacity exactly");
263 out
264 }
265
266 pub fn from_serialized(data: &[u32]) -> Option<Self> {
269 let mut reader = SerializedReader { data, position: 0 };
270 if reader.next()? != SERIALIZED_TAG {
271 return None;
272 }
273 let mode_count = reader.next_len()?;
274 let mut mode_starts = Vec::with_capacity(mode_count);
275 for _ in 0..mode_count {
276 let word = reader.next()?;
277 let start = if word == u32::MAX {
278 None
279 } else {
280 Some(u16::try_from(word).ok()?)
281 };
282 mode_starts.push(start);
283 }
284 let states = reader.read_states()?;
285 let ascii_rows = reader.read_ascii_rows()?;
286 let wide_rows = reader.read_wide_rows()?;
287 let accepts = reader.read_accepts()?;
288 if reader.position != data.len() {
289 return None;
290 }
291 let dfa = Self {
292 mode_starts,
293 states,
294 ascii_rows,
295 wide_rows,
296 accepts,
297 };
298 dfa.table_indexes_are_valid().then_some(dfa)
299 }
300
301 fn table_indexes_are_valid(&self) -> bool {
304 let state_ok = |target: u16| {
305 usize::from(target) < self.states.len() || target >= ESCAPE_STATE
306 };
307 self.mode_starts
308 .iter()
309 .flatten()
310 .all(|&start| usize::from(start) < self.states.len())
311 && self.states.iter().all(|state| {
312 (state.ascii_row as usize) < self.ascii_rows.len()
313 && (state.wide_row as usize) < self.wide_rows.len()
314 && state_ok(state.eof_target)
315 && (state.accept == u32::MAX || (state.accept as usize) < self.accepts.len())
316 })
317 && self.ascii_rows.iter().all(|row| row.iter().all(|&target| state_ok(target)))
318 && self.wide_rows.iter().all(|row| {
319 wide_row_is_searchable(row) && row.iter().all(|range| state_ok(range.target))
320 })
321 }
322}
323
324fn wide_row_is_searchable(row: &[WideRange]) -> bool {
328 row.iter().all(|range| range.low <= range.high)
329 && row.windows(2).all(|pair| pair[0].high < pair[1].low)
330}
331
332const SERIALIZED_TAG: u32 = 0x4C58_4401;
334
335struct SerializedReader<'a> {
337 data: &'a [u32],
338 position: usize,
339}
340
341impl SerializedReader<'_> {
342 fn next(&mut self) -> Option<u32> {
343 let value = self.data.get(self.position).copied();
344 self.position += 1;
345 value
346 }
347
348 fn next_u16(&mut self) -> Option<u16> {
349 u16::try_from(self.next()?).ok()
350 }
351
352 fn next_len(&mut self) -> Option<usize> {
353 usize::try_from(self.next()?).ok()
354 }
355
356 fn read_states(&mut self) -> Option<Vec<CompiledLexerState>> {
357 let count = self.next_len()?;
358 let mut states = Vec::with_capacity(count.min(self.data.len()));
359 for _ in 0..count {
360 states.push(CompiledLexerState {
361 ascii_row: self.next()?,
362 wide_row: self.next()?,
363 eof_target: self.next_u16()?,
364 accept: self.next()?,
365 });
366 }
367 Some(states)
368 }
369
370 fn read_ascii_rows(&mut self) -> Option<Vec<[u16; ASCII_EDGE_SYMBOLS]>> {
371 let count = self.next_len()?;
372 let mut rows = Vec::with_capacity(count.min(self.data.len()));
373 for _ in 0..count {
374 let mut row = [DEAD_STATE; ASCII_EDGE_SYMBOLS];
375 for pair in 0..ASCII_EDGE_SYMBOLS / 2 {
376 let word = self.next()?;
377 row[pair * 2] = (word & 0xFFFF) as u16;
378 row[pair * 2 + 1] = (word >> 16) as u16;
379 }
380 rows.push(row);
381 }
382 Some(rows)
383 }
384
385 fn read_wide_rows(&mut self) -> Option<Vec<Box<[WideRange]>>> {
386 let count = self.next_len()?;
387 let mut rows = Vec::with_capacity(count.min(self.data.len()));
388 for _ in 0..count {
389 let len = self.next_len()?;
390 let mut row = Vec::with_capacity(len.min(self.data.len()));
391 for _ in 0..len {
392 row.push(WideRange {
393 low: self.next()?,
394 high: self.next()?,
395 target: self.next_u16()?,
396 });
397 }
398 rows.push(row.into());
399 }
400 Some(rows)
401 }
402
403 fn read_accepts(&mut self) -> Option<Vec<CompiledLexerAccept>> {
404 let count = self.next_len()?;
405 let mut accepts = Vec::with_capacity(count.min(self.data.len()));
406 for _ in 0..count {
407 let rule_index = self.next_len()?;
408 let consumed_eof = self.next()? != 0;
409 let action_count = self.next_len()?;
410 let mut actions = Vec::with_capacity(action_count.min(self.data.len()));
411 for _ in 0..action_count {
412 actions.push(CompiledLexerActionTrace {
413 action_index: self.next_len()?,
414 rule_index: self.next_len()?,
415 behind: self.next_len()?,
416 });
417 }
418 accepts.push(CompiledLexerAccept {
419 rule_index,
420 consumed_eof,
421 actions,
422 });
423 }
424 Some(accepts)
425 }
426}
427
428#[derive(Debug, Default)]
430struct RowPools {
431 ascii_ids: FxHashMap<[u16; ASCII_EDGE_SYMBOLS], u32>,
432 wide_ids: FxHashMap<Box<[WideRange]>, u32>,
433}
434
435impl RowPools {
436 fn intern_ascii(&mut self, rows: &mut Vec<[u16; ASCII_EDGE_SYMBOLS]>, row: [u16; ASCII_EDGE_SYMBOLS]) -> u32 {
437 *self.ascii_ids.entry(row).or_insert_with(|| {
438 rows.push(row);
439 (rows.len() - 1) as u32
440 })
441 }
442
443 fn intern_wide(&mut self, rows: &mut Vec<Box<[WideRange]>>, row: Vec<WideRange>) -> u32 {
444 let row: Box<[WideRange]> = row.into();
445 if let Some(&id) = self.wide_ids.get(&row) {
446 return id;
447 }
448 rows.push(row.clone());
449 let id = (rows.len() - 1) as u32;
450 self.wide_ids.insert(row, id);
451 id
452 }
453}
454
455struct ModeBuild {
461 base: usize,
462 ids: FxHashMap<LexerDfaKey, u16>,
463 configs: Vec<Vec<LexerConfig>>,
464 steps: Vec<usize>,
465 accepts: Vec<Option<CompiledLexerAccept>>,
466}
467
468struct StateRows {
470 segments: Vec<(i32, i32, u16)>,
472 eof_target: u16,
473}
474
475impl ModeBuild {
476 fn new(base: usize) -> Self {
477 Self {
478 base,
479 ids: FxHashMap::default(),
480 configs: Vec::new(),
481 steps: Vec::new(),
482 accepts: Vec::new(),
483 }
484 }
485
486 const fn len(&self) -> usize {
487 self.configs.len()
488 }
489
490 fn intern(&mut self, atn: &Atn, configs: Vec<LexerConfig>, step: usize) -> u16 {
495 let key = LexerDfaKey::new(
496 configs
497 .iter()
498 .map(|config| relative_config_key(config, step))
499 .collect(),
500 );
501 if let Some(&id) = self.ids.get(&key) {
502 return id;
503 }
504 let local = self.configs.len();
505 let global = self.base + local;
506 if local >= MAX_MODE_STATES || global >= usize::from(ESCAPE_STATE) {
507 return ESCAPE_STATE;
508 }
509 let Ok(id) = u16::try_from(global) else {
510 return ESCAPE_STATE;
511 };
512 self.ids.insert(key, id);
513 self.accepts.push(compiled_accept(atn, &configs, step));
514 self.configs.push(configs);
515 self.steps.push(step);
516 id
517 }
518}
519
520fn relative_config_key(config: &LexerConfig, step: usize) -> LexerDfaConfigKey {
528 LexerDfaConfigKey::new(
529 config.state,
530 config.alt_rule_index,
531 config.consumed_eof,
532 config.passed_non_greedy,
533 config.stack.clone(),
534 config
535 .actions
536 .iter()
537 .map(|action| LexerDfaActionKey {
538 action_index: action.action_index,
539 position_delta: step.saturating_sub(action.position),
540 rule_index: action.rule_index,
541 })
542 .collect(),
543 )
544}
545
546fn compiled_accept(atn: &Atn, configs: &[LexerConfig], step: usize) -> Option<CompiledLexerAccept> {
549 let accept = best_accept(atn, configs)?;
550 debug_assert!(
551 accept.position == step,
552 "every config in a lexer DFA state shares the state's input offset"
553 );
554 Some(CompiledLexerAccept {
555 rule_index: accept.rule_index,
556 consumed_eof: accept.consumed_eof,
557 actions: accept
558 .actions
559 .iter()
560 .map(|trace| CompiledLexerActionTrace {
561 action_index: trace.action_index,
562 rule_index: trace.rule_index,
563 behind: accept.position.saturating_sub(trace.position),
564 })
565 .collect(),
566 })
567}
568
569fn build_mode(
572 atn: &Atn,
573 mode: usize,
574 dfa: &mut CompiledLexerDfa,
575 pools: &mut RowPools,
576) -> Option<u16> {
577 let start_state = atn.mode_to_start_state().get(mode).copied()?;
578 let mut build = ModeBuild::new(dfa.states.len());
579 let start_configs = closed_configs(
580 atn,
581 vec![LexerConfig {
582 state: start_state,
583 position: 0,
584 consumed_eof: false,
585 alt_rule_index: None,
586 passed_non_greedy: false,
587 stack: Vec::new(),
588 actions: Vec::new(),
589 }],
590 )?;
591 let start_id = build.intern(atn, start_configs, 0);
592 if start_id == ESCAPE_STATE {
593 return None;
594 }
595
596 let mut rows = Vec::new();
597 let mut cursor = 0;
598 while cursor < build.len() {
599 rows.push(expand_state(atn, &mut build, cursor));
600 cursor += 1;
601 }
602
603 commit_mode(dfa, pools, build, rows);
604 Some(start_id)
605}
606
607fn closed_configs(atn: &Atn, moved: Vec<LexerConfig>) -> Option<Vec<LexerConfig>> {
612 let closure = epsilon_closure(atn, moved, &mut |_| true);
613 if closure.has_semantic_context {
614 return None;
615 }
616 if closure.configs.iter().any(has_recursive_stack) {
617 return None;
618 }
619 let mut configs = closure.configs;
620 for config in &mut configs {
621 prune_dead_action_traces(atn, config);
622 if config.actions.len() > MAX_ACTION_TRACES {
623 return None;
624 }
625 }
626 Some(prune_after_accepts(atn, configs))
627}
628
629fn prune_dead_action_traces(atn: &Atn, config: &mut LexerConfig) {
638 let Some(accept_rule) = config.alt_rule_index else {
639 return;
640 };
641 config
642 .actions
643 .retain(|trace| lexer_action_belongs_to_accept(atn, accept_rule, trace.rule_index));
644}
645
646fn has_recursive_stack(config: &LexerConfig) -> bool {
650 let stack = &config.stack;
651 if stack.len() > MAX_STACK_DEPTH {
652 return true;
653 }
654 stack
655 .iter()
656 .enumerate()
657 .any(|(index, follow)| stack[..index].contains(follow))
658}
659
660fn expand_state(atn: &Atn, build: &mut ModeBuild, local: usize) -> StateRows {
662 let configs = build.configs[local].clone();
663 let step = build.steps[local];
664 let entries = consuming_entries(atn, &configs);
665 let eof_target = eof_move(atn, build, &configs, step, &entries);
666
667 let entry_intervals: Vec<Vec<(i32, i32)>> = entries
668 .iter()
669 .map(|(_, transition)| transition_char_intervals(transition))
670 .collect();
671 let segments = char_segments(&entry_intervals);
672 let matrix = segment_mask_matrix(&segments, &entry_intervals, entries.len());
673 let words = entries.len().div_ceil(64);
674
675 let mut rows = StateRows {
676 segments: Vec::new(),
677 eof_target,
678 };
679 let mut mask_targets: FxHashMap<Vec<u64>, u16> = FxHashMap::default();
683 for (index, &(low, high)) in segments.iter().enumerate() {
684 let mask = &matrix[index * words..(index + 1) * words];
685 if mask.iter().all(|&word| word == 0) {
686 continue;
687 }
688 let target = match mask_targets.get(mask) {
689 Some(&target) => target,
690 None => {
691 let target = move_target(atn, build, &configs, step, &entries, mask);
692 mask_targets.insert(mask.to_vec(), target);
693 target
694 }
695 };
696 if target != DEAD_STATE {
697 rows.segments.push((low, high, target));
698 }
699 }
700 rows
701}
702
703fn consuming_entries<'a>(atn: &'a Atn, configs: &[LexerConfig]) -> Vec<(usize, &'a Transition)> {
705 let mut entries = Vec::new();
706 for (config_index, config) in configs.iter().enumerate() {
707 let Some(state) = atn.state(config.state) else {
708 continue;
709 };
710 for transition in &state.transitions {
711 if !transition.is_epsilon() {
712 entries.push((config_index, transition));
713 }
714 }
715 }
716 entries
717}
718
719fn char_segments(entry_intervals: &[Vec<(i32, i32)>]) -> Vec<(i32, i32)> {
722 let mut cuts = Vec::new();
723 for intervals in entry_intervals {
724 for &(low, high) in intervals {
725 cuts.push(low);
726 cuts.push(high + 1);
727 }
728 }
729 cuts.sort_unstable();
730 cuts.dedup();
731 cuts.windows(2).map(|pair| (pair[0], pair[1] - 1)).collect()
732}
733
734fn segment_mask_matrix(
738 segments: &[(i32, i32)],
739 entry_intervals: &[Vec<(i32, i32)>],
740 entry_count: usize,
741) -> Vec<u64> {
742 let words = entry_count.div_ceil(64);
743 let mut matrix = vec![0_u64; segments.len() * words];
744 for (bit, intervals) in entry_intervals.iter().enumerate() {
745 for &(low, high) in intervals {
746 let from = segments.partition_point(|&(start, _)| start < low);
749 let to = segments.partition_point(|&(start, _)| start <= high);
750 for segment in from..to {
751 matrix[segment * words + bit / 64] |= 1 << (bit % 64);
752 }
753 }
754 }
755 matrix
756}
757
758fn transition_char_intervals(transition: &Transition) -> Vec<(i32, i32)> {
761 let mut intervals = Vec::new();
762 let mut push_clamped = |low: i32, high: i32| {
763 let low = low.max(MIN_CHAR_VALUE);
764 let high = high.min(MAX_CHAR_VALUE);
765 if low <= high {
766 intervals.push((low, high));
767 }
768 };
769 match transition {
770 Transition::Atom { label, .. } => push_clamped(*label, *label),
771 Transition::Range { start, stop, .. } => push_clamped(*start, *stop),
772 Transition::Set { set, .. } => {
773 for &(low, high) in set.ranges() {
774 push_clamped(low, high);
775 }
776 }
777 Transition::NotSet { set, .. } => {
778 let mut next = MIN_CHAR_VALUE;
781 for &(low, high) in set.ranges() {
782 if low > next {
783 push_clamped(next, low - 1);
784 }
785 next = next.max(high.saturating_add(1));
786 }
787 push_clamped(next, MAX_CHAR_VALUE);
788 }
789 Transition::Wildcard { .. } => push_clamped(MIN_CHAR_VALUE, MAX_CHAR_VALUE),
790 _ => {}
791 }
792 intervals
793}
794
795fn move_target(
798 atn: &Atn,
799 build: &mut ModeBuild,
800 configs: &[LexerConfig],
801 step: usize,
802 entries: &[(usize, &Transition)],
803 mask: &[u64],
804) -> u16 {
805 let mut moved = Vec::new();
806 for (bit, (config_index, transition)) in entries.iter().enumerate() {
807 if mask[bit / 64] & (1 << (bit % 64)) == 0 {
808 continue;
809 }
810 let mut advanced = configs[*config_index].clone();
811 set_config_state(atn, &mut advanced, transition.target());
812 advanced.position += 1;
813 moved.push(advanced);
814 }
815 let Some(active) = closed_configs(atn, moved) else {
816 return ESCAPE_STATE;
817 };
818 if active.is_empty() {
819 return DEAD_STATE;
820 }
821 build.intern(atn, active, step + 1)
822}
823
824fn eof_move(
827 atn: &Atn,
828 build: &mut ModeBuild,
829 configs: &[LexerConfig],
830 step: usize,
831 entries: &[(usize, &Transition)],
832) -> u16 {
833 let mut moved = Vec::new();
834 for (config_index, transition) in entries {
835 if !transition.matches(EOF, MIN_CHAR_VALUE, MAX_CHAR_VALUE) {
836 continue;
837 }
838 let mut advanced = configs[*config_index].clone();
839 set_config_state(atn, &mut advanced, transition.target());
840 advanced.consumed_eof = true;
841 moved.push(advanced);
842 }
843 if moved.is_empty() {
844 return DEAD_STATE;
845 }
846 let Some(active) = closed_configs(atn, moved) else {
847 return ESCAPE_STATE;
848 };
849 if active.is_empty() {
850 return DEAD_STATE;
851 }
852 build.intern(atn, active, step)
853}
854
855fn commit_mode(dfa: &mut CompiledLexerDfa, pools: &mut RowPools, build: ModeBuild, rows: Vec<StateRows>) {
857 for (accept, state_rows) in build.accepts.into_iter().zip(rows) {
858 let accept_id = accept.map_or(u32::MAX, |accept| {
859 dfa.accepts.push(accept);
860 (dfa.accepts.len() - 1) as u32
861 });
862 let (ascii_row, wide_row) = split_rows(&state_rows.segments);
863 dfa.states.push(CompiledLexerState {
864 ascii_row: pools.intern_ascii(&mut dfa.ascii_rows, ascii_row),
865 wide_row: pools.intern_wide(&mut dfa.wide_rows, wide_row),
866 eof_target: state_rows.eof_target,
867 accept: accept_id,
868 });
869 }
870}
871
872fn split_rows(segments: &[(i32, i32, u16)]) -> ([u16; ASCII_EDGE_SYMBOLS], Vec<WideRange>) {
874 let mut ascii = [DEAD_STATE; ASCII_EDGE_SYMBOLS];
875 let mut wide: Vec<WideRange> = Vec::new();
876 for &(low, high, target) in segments {
877 let ascii_high = high.min(ASCII_EDGE_LIMIT - 1);
878 for code_point in low..=ascii_high {
879 ascii[code_point.cast_unsigned() as usize] = target;
880 }
881 if high >= ASCII_EDGE_LIMIT {
882 let low = low.max(ASCII_EDGE_LIMIT).cast_unsigned();
883 let high = high.cast_unsigned();
884 if let Some(last) = wide.last_mut()
885 && last.target == target
886 && last.high + 1 == low
887 {
888 last.high = high;
889 continue;
890 }
891 wide.push(WideRange { low, high, target });
892 }
893 }
894 (ascii, wide)
895}
896
897#[cfg(test)]
898mod tests {
899 use super::*;
900 use crate::atn::lexer::{next_token, next_token_compiled, next_token_compiled_with_hooks};
901 use crate::atn::serialized::{AtnDeserializer, SerializedAtn};
902 use crate::char_stream::InputStream;
903 use crate::lexer::BaseLexer;
904 use crate::recognizer::RecognizerData;
905 use crate::token::{TOKEN_EOF, Token};
906 use crate::vocabulary::Vocabulary;
907
908 fn recognizer_data() -> RecognizerData {
909 RecognizerData::new(
910 "T",
911 Vocabulary::new(
912 [None, Some("'ab'"), Some("' '")],
913 [None, Some("AB"), Some("WS")],
914 [None::<&str>, None, None],
915 ),
916 )
917 }
918
919 fn two_rule_atn(with_predicate: bool) -> Atn {
922 let epsilon_or_predicate = if with_predicate { 4 } else { 1 };
923 AtnDeserializer::new(&SerializedAtn::from_i32(&[
924 4, 0, 2, 9, 6, -1, 2, 0, 1, 0, 1, 0, 7, 0, 2, 1, 1, 1, 1, 1, 7, 1, 0, 0, 2, 1, 1, 5, 2, 1, 0, 0, 8, 0, 1, 1, 0, 0, 0, 0, 5, 1, 0, 0, 0, 1, 2, 5, 'a' as i32, 0, 0, 2, 3, 5, 'b' as i32, 0, 0, 3, 4, epsilon_or_predicate, 0, 0, 0, 5, 6, 5, ' ' as i32, 0, 0, 6, 7, 1, 0, 0, 0, 7, 8, 6, 1, 0, 0, 1, 0, 1, 6, 0, 0, ]))
956 .deserialize()
957 .expect("artificial lexer ATN should deserialize")
958 }
959
960 fn wide_range_atn() -> Atn {
962 AtnDeserializer::new(&SerializedAtn::from_i32(&[
963 4, 0, 1, 5, 6, -1, 2, 0, 1, 0, 1, 0, 7, 0, 0, 0, 1, 1, 1, 1, 0, 0, 5, 0, 1, 1, 0, 0, 0, 1, 2, 1, 0, 0, 0, 2, 3, 2, 0x100, 0x200, 0, 3, 2, 1, 0, 0, 0, 3, 4, 1, 0, 0, 0, 0, 0, ]))
986 .deserialize()
987 .expect("artificial wide-range lexer ATN should deserialize")
988 }
989
990 #[test]
991 fn compiled_dfa_matches_longest_token_and_skips() {
992 let atn = two_rule_atn(false);
993 let dfa = CompiledLexerDfa::compile(&atn);
994 assert!(dfa.has_compiled_modes());
995 assert!(dfa.mode_start(0).is_some());
996
997 let mut lexer = BaseLexer::new(InputStream::new(" ab"), recognizer_data());
998 let token = next_token_compiled(&mut lexer, &atn, &dfa);
999 assert_eq!(token.token_type(), 1);
1000 assert_eq!(token.text(), "ab");
1001 assert_eq!(
1002 next_token_compiled(&mut lexer, &atn, &dfa).token_type(),
1003 TOKEN_EOF
1004 );
1005 }
1006
1007 #[test]
1008 fn predicate_edge_escapes_to_the_interpreter() {
1009 let atn = two_rule_atn(true);
1010 let dfa = CompiledLexerDfa::compile(&atn);
1011 assert!(dfa.mode_start(0).is_some());
1014
1015 let mut lexer = BaseLexer::new(InputStream::new(" ab"), recognizer_data());
1016 let token = next_token_compiled_with_hooks(
1017 &mut lexer,
1018 &atn,
1019 &dfa,
1020 |_, _| {},
1021 |_, _| true,
1022 |_, _, _| {},
1023 );
1024 assert_eq!(token.token_type(), 1);
1025 assert_eq!(token.text(), "ab");
1026 }
1027
1028 #[test]
1029 fn compiled_dfa_walks_wide_ranges() {
1030 let atn = wide_range_atn();
1031 let dfa = CompiledLexerDfa::compile(&atn);
1032 assert!(dfa.mode_start(0).is_some());
1033
1034 let mut lexer = BaseLexer::new(InputStream::new("ĀĂ"), recognizer_data());
1035 let token = next_token_compiled(&mut lexer, &atn, &dfa);
1036 assert_eq!(token.token_type(), 1);
1037 assert_eq!(token.text(), "ĀĂ");
1038 assert_eq!(
1039 next_token_compiled(&mut lexer, &atn, &dfa).token_type(),
1040 TOKEN_EOF
1041 );
1042 }
1043
1044 #[test]
1045 fn compiled_dfa_reports_recognition_errors_like_the_interpreter() {
1046 let atn = wide_range_atn();
1047 let dfa = CompiledLexerDfa::compile(&atn);
1048
1049 let mut compiled = BaseLexer::new(InputStream::new("zĀ"), recognizer_data());
1050 let mut interpreted = BaseLexer::new(InputStream::new("zĀ"), recognizer_data());
1051 loop {
1052 let compiled_token = next_token_compiled(&mut compiled, &atn, &dfa);
1053 let interpreted_token = next_token(&mut interpreted, &atn);
1054 assert_eq!(compiled_token.token_type(), interpreted_token.token_type());
1055 assert_eq!(compiled_token.text(), interpreted_token.text());
1056 if compiled_token.token_type() == TOKEN_EOF {
1057 break;
1058 }
1059 }
1060 let compiled_errors: Vec<String> = compiled
1061 .drain_errors()
1062 .into_iter()
1063 .map(|error| error.message)
1064 .collect();
1065 let interpreted_errors: Vec<String> = interpreted
1066 .drain_errors()
1067 .into_iter()
1068 .map(|error| error.message)
1069 .collect();
1070 assert_eq!(compiled_errors, vec!["token recognition error at: 'z'"]);
1071 assert_eq!(compiled_errors, interpreted_errors);
1072 }
1073
1074 #[test]
1075 fn serialization_round_trips() {
1076 let atn = two_rule_atn(false);
1077 let dfa = CompiledLexerDfa::compile(&atn);
1078 let stream = dfa.serialize();
1079
1080 let restored =
1081 CompiledLexerDfa::from_serialized(&stream).expect("stream should deserialize");
1082 assert_eq!(restored.serialize(), stream);
1083
1084 let mut lexer = BaseLexer::new(InputStream::new(" ab"), recognizer_data());
1085 let token = next_token_compiled(&mut lexer, &atn, &restored);
1086 assert_eq!(token.token_type(), 1);
1087 assert_eq!(token.text(), "ab");
1088
1089 let mut wrong_tag = stream;
1091 wrong_tag[0] ^= 1;
1092 assert!(CompiledLexerDfa::from_serialized(&wrong_tag).is_none());
1093 }
1094
1095 #[test]
1096 fn malformed_wide_rows_are_rejected() {
1097 let atn = wide_range_atn();
1098 let stream = CompiledLexerDfa::compile(&atn).serialize();
1099
1100 let position = stream
1103 .windows(2)
1104 .position(|pair| pair == [0x100, 0x200])
1105 .expect("wide-range test grammar serializes its range bounds");
1106 let mut inverted = stream;
1107 inverted.swap(position, position + 1);
1108 assert!(CompiledLexerDfa::from_serialized(&inverted).is_none());
1109 }
1110
1111 #[test]
1112 fn force_interpreted_bypasses_compiled_tables() {
1113 let atn = two_rule_atn(false);
1114 let dfa = CompiledLexerDfa::compile(&atn);
1115
1116 let mut lexer = BaseLexer::new(InputStream::new("ab"), recognizer_data());
1117 lexer.set_force_interpreted(true);
1118 let token = next_token_compiled(&mut lexer, &atn, &dfa);
1119 assert_eq!(token.token_type(), 1);
1120 assert!(!lexer.lexer_dfa_string().is_empty());
1123 }
1124}