1use crate::atn::AtnStateKind;
2use crate::atn::parser_atn::{
3 ParserAtn as Atn, ParserAtnState as AtnState, ParserTransition, ParserTransitionKind,
4};
5#[cfg(test)]
6use crate::atn::parser_atn::{ParserAtnBuilder, ParserTransitionSpec};
7use crate::dfa::{
8 DfaStateBuilder, DfaStateId, NO_DFA_STATE, ParserDfa, ParserDfaStateView, ParserDfaStats,
9};
10use crate::int_stream::IntStream;
11use crate::prediction::{
12 AtnConfig, AtnConfigSet, ContextArena, ContextId, EMPTY_CONTEXT, EMPTY_RETURN_STATE,
13 PredictionContextStats, PredictionFxHasher, PredictionWorkspace, SemanticContext,
14 all_subsets_conflict, all_subsets_equal, conflicting_alt_subsets,
15 has_sll_conflict_terminating_prediction, single_viable_alt,
16};
17use crate::token::TOKEN_EOF;
18use std::cell::RefCell;
19use std::collections::{HashMap, HashSet};
20use std::hash::BuildHasherDefault;
21
22type FxHashSet<T> = HashSet<T, BuildHasherDefault<PredictionFxHasher>>;
23
24#[derive(Debug)]
25pub struct ParserAtnSimulator<'a> {
26 atn: &'a Atn,
27 store: PredictionStore,
28 workspace: PredictionWorkspace,
29 outer_context_cache: Option<CachedOuterContext>,
30 outer_context_cache_hits: usize,
31 outer_context_cache_misses: usize,
32 deferred_accept_states: FxHashSet<(usize, DfaStateId)>,
35 shared_cache_key: Option<usize>,
36 shared_cache_generation: u64,
37 has_trained_decision: bool,
38 measure_adaptive_work: bool,
39 adaptive_calls: usize,
40 adaptive_closure_work: usize,
41 exact_ambig_detection: bool,
45 full_context_memo: HashMap<
56 FullContextMemoKey,
57 Vec<FullContextMemoEntry>,
58 BuildHasherDefault<PredictionFxHasher>,
59 >,
60 full_context_memo_len: usize,
61 full_context_memo_gate: Option<bool>,
65}
66
67#[derive(Clone, Copy, Debug)]
68struct CachedOuterContext {
69 rule_context_version: usize,
70 context: ContextId,
71}
72
73#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
84struct FullContextMemoKey {
85 decision: usize,
86 precedence: i32,
87 outer_context: ContextId,
88 first_symbol: i32,
89}
90
91#[derive(Clone, Debug)]
102struct FullContextMemoEntry {
103 window_tail: Vec<i32>,
104 prediction: FullContextPrediction,
105}
106
107const FULL_CONTEXT_MEMO_MAX_WINDOW: usize = 16;
111const FULL_CONTEXT_MEMO_MAX_ENTRIES: usize = 4096;
115
116fn atn_has_predicate_transition(atn: &Atn) -> bool {
123 thread_local! {
124 static GATES: RefCell<HashMap<usize, bool, BuildHasherDefault<PredictionFxHasher>>> =
125 RefCell::new(HashMap::default());
126 }
127 let ptr: *const Atn = atn;
128 let key = ptr as usize;
129 GATES.with(|gates| {
130 *gates.borrow_mut().entry(key).or_insert_with(|| {
131 (0..atn.state_count()).any(|state_number| {
132 atn.state(state_number).is_some_and(|state| {
133 state
134 .transitions()
135 .into_iter()
136 .any(|transition| transition.kind() == ParserTransitionKind::Predicate)
137 })
138 })
139 })
140 })
141}
142
143#[derive(Debug, Default)]
144struct PredictionStore {
145 contexts: ContextArena,
146 decision_to_dfa: Vec<ParserDfa>,
147}
148
149impl PredictionStore {
150 fn new(atn: &Atn) -> Self {
151 Self {
152 contexts: ContextArena::new(),
153 decision_to_dfa: initial_decision_dfas(atn),
154 }
155 }
156}
157
158#[derive(Debug, Default)]
159struct SharedPredictionStore {
160 generation: u64,
161 store: Option<PredictionStore>,
162}
163
164thread_local! {
165 static SHARED_PREDICTION_STORES: RefCell<HashMap<usize, SharedPredictionStore>> =
166 RefCell::new(HashMap::new());
167}
168
169fn clear_shared_prediction_store(key: usize) -> u64 {
170 SHARED_PREDICTION_STORES.with(|cache| {
171 let mut cache = cache.borrow_mut();
172 let shared = cache.entry(key).or_default();
173 shared.generation = shared.generation.wrapping_add(1);
174 shared.store = None;
175 shared.generation
176 })
177}
178
179const ADAPTIVE_ATN_PREFERENCE_MIN_CALLS: usize = 32;
180const ADAPTIVE_ATN_PREFERENCE_MIN_CLOSURE_WORK_PER_CALL: usize = 256;
181const ADAPTIVE_ATN_PREFERENCE_DECISIVE_CLOSURE_WORK_PER_CALL: usize = 512;
182
183const fn adaptive_prediction_has_work_density(
184 calls: usize,
185 closure_work: usize,
186 minimum_closure_work_per_call: usize,
187) -> bool {
188 calls >= ADAPTIVE_ATN_PREFERENCE_MIN_CALLS
189 && closure_work >= calls.saturating_mul(minimum_closure_work_per_call)
190}
191
192#[derive(Clone, Debug, Eq, PartialEq)]
193pub struct ParserAtnPrediction {
194 pub alt: usize,
195 pub requires_full_context: bool,
196 pub has_semantic_context: bool,
197 pub diagnostic: Option<ParserAtnPredictionDiagnostic>,
198}
199
200#[derive(Clone, Debug, Eq, PartialEq)]
201pub struct ParserAtnPredictionDiagnostic {
202 pub kind: ParserAtnPredictionDiagnosticKind,
203 pub start_index: usize,
204 pub sll_stop_index: usize,
205 pub ll_stop_index: usize,
206 pub conflicting_alts: Vec<usize>,
207 pub exact: bool,
211}
212
213#[derive(Clone, Copy, Debug, Eq, PartialEq)]
214pub enum ParserAtnPredictionDiagnosticKind {
215 Ambiguity,
216 ContextSensitivity,
217}
218
219#[derive(Clone, Copy)]
220struct PredictionCheck {
221 decision: usize,
222 decision_state: usize,
223 state_number: DfaStateId,
224 start_index: usize,
225 precedence: i32,
226 outer_context: ContextId,
227 force_full_context_retry: bool,
228 sll_probe_only: bool,
229}
230
231#[derive(Clone, Copy)]
232struct AdaptivePredictRequest {
233 decision: usize,
234 precedence: usize,
235 outer_context: ContextId,
236 force_full_context_retry: bool,
237 sll_probe_only: bool,
245}
246
247#[derive(Clone, Copy)]
248struct DfaEdge {
249 decision: usize,
250 source_state: DfaStateId,
251}
252
253#[derive(Clone, Debug)]
254struct PreviousGoodAlt {
255 alt: usize,
256 configs: Vec<AtnConfig>,
257}
258
259#[derive(Clone, Debug, Eq, PartialEq)]
260struct DfaPredictionInfo {
261 prediction: ParserAtnPrediction,
262 conflicting_alts: Vec<usize>,
263}
264
265#[derive(Clone, Debug, Eq, PartialEq)]
266struct FullContextPrediction {
267 prediction: ParserAtnPrediction,
268 stop_index: usize,
269 resolution: FullContextResolution,
270}
271
272#[derive(Clone, Debug, Eq, PartialEq)]
277enum FullContextResolution {
278 Unique,
279 Ambiguous { exact: bool, alts: Vec<usize> },
280}
281
282fn full_context_prediction(
283 alt: usize,
284 configs: &AtnConfigSet,
285 stop_index: usize,
286 resolution: FullContextResolution,
287) -> FullContextPrediction {
288 FullContextPrediction {
289 prediction: ParserAtnPrediction {
290 alt,
291 requires_full_context: true,
292 has_semantic_context: configs_have_semantic_context_for_alt(configs, alt),
293 diagnostic: None,
294 },
295 stop_index,
296 resolution,
297 }
298}
299
300#[derive(Clone, Debug, Eq, Hash, PartialEq)]
301struct ClosureConfigKey {
302 state: usize,
303 alt: usize,
304 context: ContextId,
305 semantic_context: SemanticContext,
306 precedence_filter_suppressed: bool,
307}
308
309impl From<&AtnConfig> for ClosureConfigKey {
310 fn from(config: &AtnConfig) -> Self {
311 Self {
312 state: config.state,
313 alt: config.alt,
314 context: config.context,
315 semantic_context: config.semantic_context.clone(),
316 precedence_filter_suppressed: config.precedence_filter_suppressed,
317 }
318 }
319}
320
321#[derive(Default)]
328struct ClosureScratch {
329 stack: Vec<(AtnConfig, bool)>,
336 visited: FxHashSet<ClosureConfigKey>,
337}
338
339#[derive(Clone, Copy)]
342struct ClosureParams {
343 precedence: i32,
344 collect_predicates: bool,
345 treat_eof_as_epsilon: bool,
346}
347
348#[derive(Debug)]
349struct LookaheadIntStream {
350 symbols: Vec<i32>,
351 index: usize,
352}
353
354impl LookaheadIntStream {
355 const fn new(symbols: Vec<i32>) -> Self {
356 Self { symbols, index: 0 }
357 }
358}
359
360impl IntStream for LookaheadIntStream {
361 fn consume(&mut self) {
362 if self.la(1) != TOKEN_EOF {
363 self.index += 1;
364 }
365 }
366
367 fn la(&mut self, offset: isize) -> i32 {
368 if offset <= 0 {
369 return 0;
370 }
371 let offset = offset.cast_unsigned() - 1;
372 self.symbols
373 .get(self.index + offset)
374 .copied()
375 .unwrap_or(TOKEN_EOF)
376 }
377
378 fn index(&self) -> usize {
379 self.index
380 }
381
382 fn seek(&mut self, index: usize) {
383 self.index = index.min(self.symbols.len());
384 }
385
386 fn size(&self) -> usize {
387 self.symbols.len()
388 }
389}
390
391fn initial_decision_dfas(atn: &Atn) -> Vec<ParserDfa> {
392 atn.decision_to_state()
393 .iter()
394 .enumerate()
395 .map(|(decision, state)| {
396 let mut dfa = ParserDfa::with_max_token_type(state, decision, atn.max_token_type());
397 if atn
398 .state(state)
399 .is_some_and(AtnState::precedence_rule_decision)
400 {
401 dfa.set_precedence_dfa(true);
402 }
403 dfa
404 })
405 .collect()
406}
407
408fn union_decision_dfas(shared: &mut Vec<ParserDfa>, local: Vec<ParserDfa>) {
418 if shared.len() != local.len() {
419 *shared = local;
420 return;
421 }
422 for (shared_dfa, local_dfa) in shared.iter_mut().zip(local) {
423 union_decision_dfa(shared_dfa, local_dfa);
424 }
425}
426
427fn union_prediction_stores(
428 shared: &mut PredictionStore,
429 mut local: PredictionStore,
430 workspace: &mut PredictionWorkspace,
431) {
432 let remap = shared.contexts.import_all(&local.contexts, workspace);
433 for dfa in &mut local.decision_to_dfa {
434 dfa.remap_contexts(&remap, &shared.contexts);
435 }
436 union_decision_dfas(&mut shared.decision_to_dfa, local.decision_to_dfa);
437}
438
439fn union_decision_dfa(shared: &mut ParserDfa, local: ParserDfa) {
440 if shared.is_precedence_dfa() != local.is_precedence_dfa() {
441 if local.state_count() > shared.state_count() {
444 *shared = local;
445 }
446 return;
447 }
448 let mut renumber = Vec::with_capacity(local.state_count());
453 for state in local.states() {
454 let configs = local.configs(state.id());
455 let number = shared.state_id_for_configs(configs).unwrap_or_else(|| {
456 let missing = local.clone_state_without_edges(state.id());
457 shared.insert_state(missing)
458 });
459 renumber.push(number);
460 }
461 for state in local.states() {
466 let mapped = renumber[state.id().index()];
467 for transition in state.transitions() {
468 let Some(&mapped_target) = renumber.get(transition.target.index()) else {
469 continue;
470 };
471 if shared.edge(mapped, transition.symbol).is_none() {
472 shared.add_edge(mapped, transition.symbol, mapped_target);
473 }
474 }
475 }
476 if shared.start_state().is_none()
477 && let Some(start) = local.start_state()
478 && let Some(&mapped) = renumber.get(start.index())
479 {
480 shared.set_start_state(mapped);
481 }
482 for (precedence, start) in local.precedence_start_states().iter().copied().enumerate() {
483 if start == NO_DFA_STATE {
484 continue;
485 }
486 if shared.precedence_start_state(precedence).is_none()
487 && let Some(&mapped) = renumber.get(start.index())
488 {
489 shared.set_precedence_start_state(precedence, mapped);
490 }
491 }
492}
493
494impl Drop for ParserAtnSimulator<'_> {
495 fn drop(&mut self) {
496 let Some(key) = self.shared_cache_key else {
497 return;
498 };
499 #[cfg(feature = "perf-counters")]
500 let publication_started = std::time::Instant::now();
501 #[cfg(feature = "perf-counters")]
502 let published_states = self
503 .store
504 .decision_to_dfa
505 .iter()
506 .map(ParserDfa::state_count)
507 .sum();
508 let store = std::mem::take(&mut self.store);
514 let published = SHARED_PREDICTION_STORES.with(|cache| {
515 let mut cache = cache.borrow_mut();
516 let shared = cache.entry(key).or_default();
517 if shared.generation != self.shared_cache_generation {
518 return false;
519 }
520 if let Some(shared_store) = shared.store.as_mut() {
521 union_prediction_stores(shared_store, store, &mut self.workspace);
522 } else {
523 shared.store = Some(store);
524 }
525 true
526 });
527 #[cfg(feature = "perf-counters")]
528 if published {
529 crate::perf::record_dfa_cache_publication(
530 publication_started.elapsed().as_nanos(),
531 published_states,
532 );
533 }
534 #[cfg(not(feature = "perf-counters"))]
535 let _ = published;
536 }
537}
538
539impl<'a> ParserAtnSimulator<'a> {
540 pub fn new(atn: &'a Atn) -> Self {
541 Self {
542 atn,
543 store: PredictionStore::new(atn),
544 workspace: PredictionWorkspace::default(),
545 outer_context_cache: None,
546 outer_context_cache_hits: 0,
547 outer_context_cache_misses: 0,
548 deferred_accept_states: FxHashSet::default(),
549 shared_cache_key: None,
550 shared_cache_generation: 0,
551 has_trained_decision: false,
552 measure_adaptive_work: false,
553 adaptive_calls: 0,
554 adaptive_closure_work: 0,
555 exact_ambig_detection: false,
556 full_context_memo: HashMap::default(),
557 full_context_memo_len: 0,
558 full_context_memo_gate: None,
559 }
560 }
561
562 pub fn reset(&mut self) {
564 self.measure_adaptive_work = false;
565 self.adaptive_calls = 0;
566 self.adaptive_closure_work = 0;
567 self.outer_context_cache = None;
568 self.deferred_accept_states.clear();
569 self.workspace.reset();
570 }
571
572 pub fn clear_dfa(&mut self) {
577 self.store = PredictionStore::new(self.atn);
578 self.full_context_memo.clear();
581 self.full_context_memo_len = 0;
582 self.reset();
583 self.has_trained_decision = false;
584 if let Some(key) = self.shared_cache_key {
585 self.shared_cache_generation = clear_shared_prediction_store(key);
586 }
587 }
588
589 pub fn clear_shared_dfa(atn: &'static Atn) {
591 let ptr: *const Atn = atn;
592 clear_shared_prediction_store(ptr as usize);
593 }
594
595 pub const fn set_exact_ambig_detection(&mut self, exact: bool) {
598 self.exact_ambig_detection = exact;
599 }
600
601 pub fn dump_dfa_java_style(&self, vocabulary: &crate::vocabulary::Vocabulary) -> String {
619 use std::fmt::Write as _;
620 let mut out = String::new();
621 let mut seen_one = false;
622 for dfa in &self.store.decision_to_dfa {
623 if dfa.is_empty() {
624 continue;
625 }
626 if seen_one {
627 out.push('\n');
628 }
629 seen_one = true;
630 let _ = writeln!(out, "Decision {}:", dfa.decision());
631 for state in dfa.states() {
632 let source = dfa_state_display(
633 state,
634 self.deferred_accept_states
635 .contains(&(dfa.decision(), state.id())),
636 );
637 for transition in state.transitions() {
638 let Some(target_state) = dfa.state(transition.target) else {
639 continue;
640 };
641 let label = vocabulary.display_name(transition.symbol);
642 let target = dfa_state_display(
643 target_state,
644 self.deferred_accept_states
645 .contains(&(dfa.decision(), target_state.id())),
646 );
647 let _ = writeln!(out, "{source}-{label}->{target}");
648 }
649 }
650 }
651 out
652 }
653
654 pub fn new_shared(atn: &'static Atn) -> Self {
655 let ptr: *const Atn = atn;
656 let key = ptr as usize;
657 #[cfg(feature = "perf-counters")]
658 let import_started = std::time::Instant::now();
659 let (store, generation) = SHARED_PREDICTION_STORES.with(|cache| {
660 let mut cache = cache.borrow_mut();
661 let shared = cache.entry(key).or_default();
662 (
663 shared
664 .store
665 .take()
666 .unwrap_or_else(|| PredictionStore::new(atn)),
667 shared.generation,
668 )
669 });
670 let has_trained_decision = store.decision_to_dfa.iter().any(|dfa| !dfa.is_empty());
671 #[cfg(feature = "perf-counters")]
672 crate::perf::record_dfa_cache_import(
673 import_started.elapsed().as_nanos(),
674 store
675 .decision_to_dfa
676 .iter()
677 .map(ParserDfa::state_count)
678 .sum(),
679 );
680 Self {
681 atn,
682 store,
683 workspace: PredictionWorkspace::default(),
684 outer_context_cache: None,
685 outer_context_cache_hits: 0,
686 outer_context_cache_misses: 0,
687 deferred_accept_states: FxHashSet::default(),
688 shared_cache_key: Some(key),
689 shared_cache_generation: generation,
690 has_trained_decision,
691 measure_adaptive_work: false,
692 adaptive_calls: 0,
693 adaptive_closure_work: 0,
694 exact_ambig_detection: false,
695 full_context_memo: HashMap::default(),
696 full_context_memo_len: 0,
697 full_context_memo_gate: None,
698 }
699 }
700
701 pub fn decision_dfas(&self) -> &[ParserDfa] {
702 &self.store.decision_to_dfa
703 }
704
705 #[doc(hidden)]
711 pub const fn adaptive_prediction_work(&self) -> Option<(usize, usize)> {
712 if self.has_trained_decision {
713 Some((self.adaptive_calls, self.adaptive_closure_work))
714 } else {
715 None
716 }
717 }
718
719 #[doc(hidden)]
722 pub const fn adaptive_prediction_delta_is_expensive(
723 before: (usize, usize),
724 after: (usize, usize),
725 ) -> bool {
726 adaptive_prediction_has_work_density(
727 after.0.saturating_sub(before.0),
728 after.1.saturating_sub(before.1),
729 ADAPTIVE_ATN_PREFERENCE_MIN_CLOSURE_WORK_PER_CALL,
730 )
731 }
732
733 #[doc(hidden)]
737 pub const fn adaptive_prediction_delta_is_decisive(
738 before: (usize, usize),
739 after: (usize, usize),
740 ) -> bool {
741 adaptive_prediction_has_work_density(
742 after.0.saturating_sub(before.0),
743 after.1.saturating_sub(before.1),
744 ADAPTIVE_ATN_PREFERENCE_DECISIVE_CLOSURE_WORK_PER_CALL,
745 )
746 }
747
748 pub fn parser_dfa_stats(&self) -> ParserDfaStats {
750 let mut stats = ParserDfaStats::default();
751 for dfa in &self.store.decision_to_dfa {
752 stats.add_assign(dfa.stats());
753 }
754 stats
755 }
756
757 pub fn prediction_context_stats(&self) -> PredictionContextStats {
760 let mut stats = self.store.contexts.stats();
761 stats.retained_bytes += self.workspace.retained_bytes();
762 stats.workspace_merge_cache_entries = self.workspace.merge_cache_len();
763 stats.workspace_merge_cache_capacity = self.workspace.merge_cache_capacity();
764 stats.workspace_entry_capacity = self.workspace.entry_capacity();
765 stats.outer_context_cache_hits = self.outer_context_cache_hits;
766 stats.outer_context_cache_misses = self.outer_context_cache_misses;
767 stats
768 }
769
770 pub fn intern_prediction_context(
774 &mut self,
775 rule_context_version: usize,
776 return_states: impl IntoIterator<Item = usize>,
777 ) -> ContextId {
778 if let Some(cached) = self.outer_context_cache
779 && cached.rule_context_version == rule_context_version
780 {
781 self.outer_context_cache_hits = self.outer_context_cache_hits.saturating_add(1);
782 return cached.context;
783 }
784 self.outer_context_cache_misses = self.outer_context_cache_misses.saturating_add(1);
785 let mut context = EMPTY_CONTEXT;
786 for return_state in return_states {
787 context = self.store.contexts.singleton(context, return_state);
788 }
789 self.outer_context_cache = Some(CachedOuterContext {
790 rule_context_version,
791 context,
792 });
793 context
794 }
795
796 pub fn adaptive_predict(
797 &mut self,
798 decision: usize,
799 lookahead: impl IntoIterator<Item = i32>,
800 ) -> Result<usize, ParserAtnSimulatorError> {
801 self.adaptive_predict_with_precedence(decision, 0, lookahead)
802 }
803
804 pub fn adaptive_predict_stream<T: IntStream>(
805 &mut self,
806 decision: usize,
807 input: &mut T,
808 ) -> Result<usize, ParserAtnSimulatorError> {
809 self.adaptive_predict_stream_with_precedence(decision, 0, input)
810 }
811
812 pub fn adaptive_predict_stream_with_precedence<T: IntStream>(
813 &mut self,
814 decision: usize,
815 precedence: usize,
816 input: &mut T,
817 ) -> Result<usize, ParserAtnSimulatorError> {
818 self.adaptive_predict_stream_info_with_precedence(decision, precedence, input)
819 .map(|prediction| prediction.alt)
820 }
821
822 pub fn adaptive_predict_stream_info_with_precedence<T: IntStream>(
823 &mut self,
824 decision: usize,
825 precedence: usize,
826 input: &mut T,
827 ) -> Result<ParserAtnPrediction, ParserAtnSimulatorError> {
828 let marker = input.mark();
829 let index = input.index();
830 let mut workspace = std::mem::take(&mut self.workspace);
831 workspace.reset();
832 let result = self.adaptive_predict_stream_inner(
833 AdaptivePredictRequest {
834 decision,
835 precedence,
836 outer_context: EMPTY_CONTEXT,
837 force_full_context_retry: false,
838 sll_probe_only: false,
839 },
840 input,
841 &mut workspace,
842 );
843 self.workspace = workspace;
844 input.seek(index);
845 input.release(marker);
846 result
847 }
848
849 pub fn adaptive_predict_stream_info_sll_probe<T: IntStream>(
859 &mut self,
860 decision: usize,
861 precedence: usize,
862 input: &mut T,
863 ) -> Result<ParserAtnPrediction, ParserAtnSimulatorError> {
864 let marker = input.mark();
865 let index = input.index();
866 let mut workspace = std::mem::take(&mut self.workspace);
867 workspace.reset();
868 let result = self.adaptive_predict_stream_inner(
869 AdaptivePredictRequest {
870 decision,
871 precedence,
872 outer_context: EMPTY_CONTEXT,
873 force_full_context_retry: false,
874 sll_probe_only: true,
875 },
876 input,
877 &mut workspace,
878 );
879 self.workspace = workspace;
880 input.seek(index);
881 input.release(marker);
882 result
883 }
884
885 pub fn adaptive_predict_stream_info_with_context<T: IntStream>(
886 &mut self,
887 decision: usize,
888 precedence: usize,
889 input: &mut T,
890 outer_context: ContextId,
891 ) -> Result<ParserAtnPrediction, ParserAtnSimulatorError> {
892 self.store.contexts.assert_valid(outer_context);
893 let marker = input.mark();
894 let index = input.index();
895 let mut workspace = std::mem::take(&mut self.workspace);
896 workspace.reset();
897 let result = self.adaptive_predict_stream_inner(
898 AdaptivePredictRequest {
899 decision,
900 precedence,
901 outer_context,
902 force_full_context_retry: true,
903 sll_probe_only: false,
904 },
905 input,
906 &mut workspace,
907 );
908 self.workspace = workspace;
909 input.seek(index);
910 input.release(marker);
911 result
912 }
913
914 pub fn adaptive_predict_with_precedence(
915 &mut self,
916 decision: usize,
917 precedence: usize,
918 lookahead: impl IntoIterator<Item = i32>,
919 ) -> Result<usize, ParserAtnSimulatorError> {
920 self.adaptive_predict_info_with_precedence(decision, precedence, lookahead)
921 .map(|prediction| prediction.alt)
922 }
923
924 pub fn adaptive_predict_info_with_precedence(
925 &mut self,
926 decision: usize,
927 precedence: usize,
928 lookahead: impl IntoIterator<Item = i32>,
929 ) -> Result<ParserAtnPrediction, ParserAtnSimulatorError> {
930 let mut input = LookaheadIntStream::new(lookahead.into_iter().collect());
931 self.adaptive_predict_stream_info_with_precedence(decision, precedence, &mut input)
932 }
933
934 fn adaptive_predict_stream_inner<T: IntStream>(
935 &mut self,
936 request: AdaptivePredictRequest,
937 input: &mut T,
938 merge_cache: &mut PredictionWorkspace,
939 ) -> Result<ParserAtnPrediction, ParserAtnSimulatorError> {
940 let decision = request.decision;
941 let learning_revision = self
942 .store
943 .decision_to_dfa
944 .get(decision)
945 .filter(|dfa| !dfa.is_empty())
946 .map(ParserDfa::learning_revision);
947 let work_start = (self.adaptive_calls, self.adaptive_closure_work);
948 self.measure_adaptive_work = learning_revision.is_some();
949 if self.measure_adaptive_work {
950 self.adaptive_calls = self.adaptive_calls.saturating_add(1);
951 }
952 let result = self.adaptive_predict_stream_inner_impl(request, input, merge_cache);
953 self.measure_adaptive_work = false;
954 if let Some(learning_revision) = learning_revision
955 && self
956 .store
957 .decision_to_dfa
958 .get(decision)
959 .map(ParserDfa::learning_revision)
960 != Some(learning_revision)
961 {
962 (self.adaptive_calls, self.adaptive_closure_work) = work_start;
963 }
964 self.has_trained_decision |= self
965 .store
966 .decision_to_dfa
967 .get(decision)
968 .is_some_and(|dfa| !dfa.is_empty());
969 result
970 }
971
972 fn adaptive_predict_stream_inner_impl<T: IntStream>(
973 &mut self,
974 request: AdaptivePredictRequest,
975 input: &mut T,
976 merge_cache: &mut PredictionWorkspace,
977 ) -> Result<ParserAtnPrediction, ParserAtnSimulatorError> {
978 let AdaptivePredictRequest {
979 decision,
980 precedence,
981 outer_context,
982 force_full_context_retry,
983 sll_probe_only,
984 } = request;
985 self.deferred_accept_states
986 .retain(|(stored_decision, _)| *stored_decision != decision);
987 #[cfg(feature = "perf-counters")]
988 crate::perf::record_adaptive_call(decision, force_full_context_retry);
989 let Some(decision_state) = self.atn.decision_to_state().get(decision) else {
990 return Err(ParserAtnSimulatorError::UnknownDecision(decision));
991 };
992 let start_index = input.index();
993 let precedence = i32::try_from(precedence).unwrap_or(i32::MAX);
999 let mut state_number =
1000 self.ensure_start_state(decision, decision_state, precedence, merge_cache)?;
1001 let track_previous_good_alt = !force_full_context_retry && !sll_probe_only;
1004 let mut previous_good_alt = None;
1005 if let Some(prediction) = self.prediction_or_full_context(
1006 input,
1007 PredictionCheck {
1008 decision,
1009 decision_state,
1010 state_number,
1011 start_index,
1012 precedence,
1013 outer_context,
1014 force_full_context_retry,
1015 sll_probe_only,
1016 },
1017 merge_cache,
1018 )? {
1019 return Ok(prediction);
1020 }
1021 loop {
1022 if track_previous_good_alt {
1023 let finished = self
1024 .store
1025 .decision_to_dfa
1026 .get(decision)
1027 .map(|dfa| dfa.configs(state_number))
1028 .and_then(|configs| self.previous_good_alt(configs));
1029 if finished.is_some() {
1030 previous_good_alt = finished;
1031 }
1032 }
1033 let symbol = input.la(1);
1034 let target = self
1035 .store
1036 .decision_to_dfa
1037 .get(decision)
1038 .and_then(|dfa| dfa.edge(state_number, symbol));
1039 #[cfg(feature = "perf-counters")]
1040 crate::perf::record_dfa_edge_lookup(target.is_some());
1041 if let Some(target) = target {
1042 state_number = target;
1043 } else {
1044 let configs = self
1045 .store
1046 .decision_to_dfa
1047 .get(decision)
1048 .map(|dfa| dfa.configs(state_number).clone())
1049 .ok_or(ParserAtnSimulatorError::MissingDfaState(state_number))?;
1050 let edge = DfaEdge {
1051 decision,
1052 source_state: state_number,
1053 };
1054 let target = match self.compute_target_state(
1055 edge,
1056 &configs,
1057 symbol,
1058 precedence,
1059 merge_cache,
1060 ) {
1061 Ok(target) => target,
1062 Err(ParserAtnSimulatorError::NoViableAlt { symbol, .. }) => {
1063 if let Some(fallback) = previous_good_alt.as_ref() {
1064 self.add_previous_good_alt_target(edge, symbol, fallback, merge_cache)
1065 } else {
1066 return Err(ParserAtnSimulatorError::NoViableAlt {
1067 symbol,
1068 index: input.index(),
1069 });
1070 }
1071 }
1072 Err(error) => return Err(error),
1073 };
1074 state_number = target;
1075 }
1076 if let Some(prediction) = self.prediction_or_full_context(
1077 input,
1078 PredictionCheck {
1079 decision,
1080 decision_state,
1081 state_number,
1082 start_index,
1083 precedence,
1084 outer_context,
1085 force_full_context_retry,
1086 sll_probe_only,
1087 },
1088 merge_cache,
1089 )? {
1090 let defer_unique = track_previous_good_alt
1091 && previous_good_alt.is_some()
1092 && !prediction.requires_full_context
1093 && !self.prediction_reached_decision_entry_rule_stop(
1094 DfaEdge {
1095 decision,
1096 source_state: state_number,
1097 },
1098 prediction.alt,
1099 precedence,
1100 symbol,
1101 merge_cache,
1102 );
1103 if !defer_unique {
1104 return Ok(prediction);
1105 }
1106 self.deferred_accept_states.insert((decision, state_number));
1107 }
1108 if symbol == TOKEN_EOF {
1109 if let Some(configs) = self
1119 .store
1120 .decision_to_dfa
1121 .get(decision)
1122 .map(|dfa| dfa.configs(state_number).clone())
1123 && let Some(alt) = self.alt_that_finished_decision_entry_rule(&configs)
1124 {
1125 return Ok(ParserAtnPrediction {
1126 alt,
1127 requires_full_context: false,
1128 has_semantic_context: configs_have_semantic_context_for_alt(&configs, alt),
1129 diagnostic: None,
1130 });
1131 }
1132 return Err(ParserAtnSimulatorError::PredictionRequiresMoreLookahead);
1133 }
1134 input.consume();
1135 }
1136 }
1137
1138 fn prediction_or_full_context<T: IntStream>(
1139 &mut self,
1140 input: &mut T,
1141 check: PredictionCheck,
1142 merge_cache: &mut PredictionWorkspace,
1143 ) -> Result<Option<ParserAtnPrediction>, ParserAtnSimulatorError> {
1144 let PredictionCheck {
1145 decision,
1146 decision_state,
1147 state_number,
1148 start_index,
1149 precedence,
1150 outer_context,
1151 force_full_context_retry,
1152 sll_probe_only,
1153 } = check;
1154 if self.store.contexts.is_empty(outer_context)
1155 && let Some(prediction) =
1156 self.non_greedy_exit_prediction(decision, decision_state, state_number)
1157 {
1158 return Ok(Some(prediction));
1159 }
1160 let Some(info) = self.dfa_prediction_info(decision, state_number) else {
1161 return Ok(None);
1162 };
1163 let prediction = info.prediction;
1164 if sll_probe_only && prediction.requires_full_context {
1171 return Ok(Some(prediction));
1172 }
1173 if prediction.requires_full_context
1174 && (force_full_context_retry || !prediction.has_semantic_context)
1175 {
1176 #[cfg(feature = "perf-counters")]
1177 crate::perf::record_full_context_retry(decision);
1178 let sll_stop_index = input.index();
1179 input.seek(start_index);
1180 let memo_allowed = self.full_context_memo_allowed();
1181 let memo_key = FullContextMemoKey {
1182 decision,
1183 precedence,
1184 outer_context,
1185 first_symbol: 0,
1186 };
1187 if memo_allowed
1190 && let Some(full_context) = self.probe_full_context_memo(memo_key, input)
1191 {
1192 #[cfg(feature = "perf-counters")]
1193 crate::perf::record_full_context_memo_hit(decision);
1194 return Ok(Some(Self::full_context_retry_prediction(
1195 full_context,
1196 info.conflicting_alts,
1197 start_index,
1198 sll_stop_index,
1199 )));
1200 }
1201 let full_context = self.adaptive_predict_full_context(
1202 decision_state,
1203 input,
1204 precedence,
1205 outer_context,
1206 merge_cache,
1207 )?;
1208 if memo_allowed {
1209 self.record_full_context_memo(memo_key, start_index, input, &full_context);
1210 }
1211 return Ok(Some(Self::full_context_retry_prediction(
1212 full_context,
1213 info.conflicting_alts,
1214 start_index,
1215 sll_stop_index,
1216 )));
1217 }
1218 Ok(Some(prediction))
1219 }
1220
1221 fn full_context_retry_prediction(
1225 full_context: FullContextPrediction,
1226 sll_conflicting_alts: Vec<usize>,
1227 start_index: usize,
1228 sll_stop_index: usize,
1229 ) -> ParserAtnPrediction {
1230 let (kind, exact, conflicting_alts) = match full_context.resolution {
1231 FullContextResolution::Ambiguous { exact, ref alts } => (
1232 ParserAtnPredictionDiagnosticKind::Ambiguity,
1233 exact,
1234 alts.clone(),
1235 ),
1236 FullContextResolution::Unique => (
1240 ParserAtnPredictionDiagnosticKind::ContextSensitivity,
1241 false,
1242 sll_conflicting_alts,
1243 ),
1244 };
1245 let mut prediction = full_context.prediction;
1246 if conflicting_alts.len() > 1 {
1247 prediction.diagnostic = Some(ParserAtnPredictionDiagnostic {
1248 kind,
1249 start_index,
1250 sll_stop_index,
1251 ll_stop_index: full_context.stop_index,
1252 conflicting_alts,
1253 exact,
1254 });
1255 }
1256 prediction
1257 }
1258
1259 fn full_context_memo_allowed(&mut self) -> bool {
1276 if self.exact_ambig_detection {
1277 return false;
1278 }
1279 let atn = self.atn;
1280 *self
1281 .full_context_memo_gate
1282 .get_or_insert_with(|| !atn_has_predicate_transition(atn))
1283 }
1284
1285 fn probe_full_context_memo<T: IntStream>(
1296 &self,
1297 mut key: FullContextMemoKey,
1298 input: &mut T,
1299 ) -> Option<FullContextPrediction> {
1300 if self.full_context_memo.is_empty() {
1301 return None;
1302 }
1303 let start_index = input.index();
1304 key.first_symbol = input.la(1);
1305 let entries = self.full_context_memo.get(&key)?;
1306 'candidates: for entry in entries {
1316 for &expected in &entry.window_tail {
1317 input.consume();
1318 if input.la(1) != expected {
1319 input.seek(start_index);
1320 continue 'candidates;
1321 }
1322 }
1323 let mut replay = entry.prediction.clone();
1324 replay.stop_index = input.index();
1325 return Some(replay);
1326 }
1327 None
1328 }
1329
1330 fn record_full_context_memo<T: IntStream>(
1337 &mut self,
1338 mut key: FullContextMemoKey,
1339 start_index: usize,
1340 input: &mut T,
1341 full_context: &FullContextPrediction,
1342 ) {
1343 if self.full_context_memo_len >= FULL_CONTEXT_MEMO_MAX_ENTRIES {
1344 #[cfg(feature = "perf-counters")]
1345 crate::perf::record_full_context_memo_declined(key.decision);
1346 return;
1347 }
1348 let current = input.index();
1349 input.seek(start_index);
1350 key.first_symbol = input.la(1);
1351 let mut window_tail = Vec::new();
1352 while input.index() < full_context.stop_index
1353 && window_tail.len() < FULL_CONTEXT_MEMO_MAX_WINDOW
1354 {
1355 input.consume();
1356 window_tail.push(input.la(1));
1357 }
1358 let complete = input.index() >= full_context.stop_index;
1359 input.seek(current);
1360 if !complete {
1361 #[cfg(feature = "perf-counters")]
1362 crate::perf::record_full_context_memo_declined(key.decision);
1363 return;
1364 }
1365 self.full_context_memo
1366 .entry(key)
1367 .or_default()
1368 .push(FullContextMemoEntry {
1369 window_tail,
1370 prediction: full_context.clone(),
1371 });
1372 self.full_context_memo_len += 1;
1373 }
1374
1375 fn non_greedy_exit_prediction(
1376 &self,
1377 decision: usize,
1378 decision_state: usize,
1379 state_number: DfaStateId,
1380 ) -> Option<ParserAtnPrediction> {
1381 if !self
1382 .atn
1383 .state(decision_state)
1384 .is_some_and(AtnState::non_greedy)
1385 {
1386 return None;
1387 }
1388 let configs = &self
1389 .store
1390 .decision_to_dfa
1391 .get(decision)?
1392 .configs(state_number);
1393 let alt = configs
1394 .configs()
1395 .iter()
1396 .filter(|config| {
1397 self.atn
1398 .state(config.state)
1399 .is_some_and(AtnState::is_rule_stop)
1400 && self.store.contexts.has_empty_path(config.context)
1401 })
1402 .map(|config| config.alt)
1403 .min()?;
1404 Some(ParserAtnPrediction {
1405 alt,
1406 requires_full_context: false,
1407 has_semantic_context: configs_have_semantic_context_for_alt(configs, alt),
1408 diagnostic: None,
1409 })
1410 }
1411
1412 fn ensure_start_state(
1413 &mut self,
1414 decision: usize,
1415 decision_state: usize,
1416 precedence: i32,
1417 merge_cache: &mut PredictionWorkspace,
1418 ) -> Result<DfaStateId, ParserAtnSimulatorError> {
1419 if self.store.decision_to_dfa[decision].is_precedence_dfa() {
1420 let precedence_key = usize::try_from(precedence.max(0)).unwrap_or_default();
1421 if let Some(start) =
1422 self.store.decision_to_dfa[decision].precedence_start_state(precedence_key)
1423 {
1424 return Ok(start);
1425 }
1426 } else if let Some(start) = self.store.decision_to_dfa[decision].start_state() {
1427 return Ok(start);
1428 }
1429 let decision_state = self
1430 .atn
1431 .state(decision_state)
1432 .ok_or(ParserAtnSimulatorError::MissingAtnState(decision_state))?;
1433 let configs = self.compute_start_state(decision_state, precedence, merge_cache);
1434 let state_number = self.add_dfa_state(decision, DfaStateBuilder::new(configs));
1435 if self.store.decision_to_dfa[decision].is_precedence_dfa() {
1436 let precedence_key = usize::try_from(precedence.max(0)).unwrap_or_default();
1437 self.store.decision_to_dfa[decision]
1438 .set_precedence_start_state(precedence_key, state_number);
1439 } else {
1440 self.store.decision_to_dfa[decision].set_start_state(state_number);
1441 }
1442 Ok(state_number)
1443 }
1444
1445 fn add_dfa_state(&mut self, decision: usize, state: DfaStateBuilder) -> DfaStateId {
1446 self.store.decision_to_dfa[decision].add_state(state)
1447 }
1448
1449 fn compute_start_state(
1450 &mut self,
1451 decision_state: AtnState<'_>,
1452 precedence: i32,
1453 merge_cache: &mut PredictionWorkspace,
1454 ) -> AtnConfigSet {
1455 self.compute_start_state_with_context(
1456 decision_state,
1457 false,
1458 EMPTY_CONTEXT,
1459 precedence,
1460 merge_cache,
1461 )
1462 }
1463
1464 fn compute_start_state_with_context(
1465 &mut self,
1466 decision_state: AtnState<'_>,
1467 full_context: bool,
1468 initial_context: ContextId,
1469 precedence: i32,
1470 merge_cache: &mut PredictionWorkspace,
1471 ) -> AtnConfigSet {
1472 let mut configs = AtnConfigSet::new_full_context(full_context);
1473 let mut scratch = ClosureScratch::default();
1474 let params = ClosureParams {
1475 precedence,
1476 collect_predicates: true,
1477 treat_eof_as_epsilon: false,
1478 };
1479 for (index, transition) in decision_state.transitions().iter().enumerate() {
1480 let alt = index + 1;
1481 let config = AtnConfig::new(
1482 transition.target(),
1483 alt,
1484 initial_context,
1485 &self.store.contexts,
1486 );
1487 self.closure(config, &mut configs, merge_cache, &mut scratch, params);
1488 }
1489 configs
1490 }
1491
1492 fn adaptive_predict_full_context<T: IntStream>(
1493 &mut self,
1494 decision_state: usize,
1495 input: &mut T,
1496 precedence: i32,
1497 outer_context: ContextId,
1498 merge_cache: &mut PredictionWorkspace,
1499 ) -> Result<FullContextPrediction, ParserAtnSimulatorError> {
1500 let decision_state = self
1501 .atn
1502 .state(decision_state)
1503 .ok_or(ParserAtnSimulatorError::MissingAtnState(decision_state))?;
1504 let mut configs = self.compute_start_state_with_context(
1505 decision_state,
1506 true,
1507 outer_context,
1508 precedence,
1509 merge_cache,
1510 );
1511 loop {
1519 if let Some(alt) = configs.unique_alt() {
1520 return Ok(full_context_prediction(
1521 alt,
1522 &configs,
1523 input.index(),
1524 FullContextResolution::Unique,
1525 ));
1526 }
1527 let symbol = input.la(1);
1528 let reach = self.compute_reach_set(&configs, symbol, true, precedence, merge_cache);
1529 if reach.is_empty() {
1530 return Err(ParserAtnSimulatorError::NoViableAlt {
1531 symbol,
1532 index: input.index(),
1533 });
1534 }
1535 configs = reach;
1536 if let Some(alt) = configs.unique_alt() {
1537 return Ok(full_context_prediction(
1538 alt,
1539 &configs,
1540 input.index(),
1541 FullContextResolution::Unique,
1542 ));
1543 }
1544 if !configs.has_semantic_context() {
1545 let subsets = conflicting_alt_subsets(configs.configs());
1546 if self.exact_ambig_detection {
1547 let alts: Vec<usize> = configs.alts().into_iter().collect();
1548 if all_subsets_conflict(&subsets)
1552 && all_subsets_equal(&subsets)
1553 && let Some(&alt) = alts.first()
1554 {
1555 return Ok(full_context_prediction(
1556 alt,
1557 &configs,
1558 input.index(),
1559 FullContextResolution::Ambiguous { exact: true, alts },
1560 ));
1561 }
1562 } else if let Some(alt) = single_viable_alt(&subsets) {
1563 let alts: Vec<usize> = configs.alts().into_iter().collect();
1564 return Ok(full_context_prediction(
1565 alt,
1566 &configs,
1567 input.index(),
1568 FullContextResolution::Ambiguous { exact: false, alts },
1569 ));
1570 }
1571 }
1572 if symbol == TOKEN_EOF || self.configs_all_reached_rule_stop(&configs) {
1573 let alts: Vec<usize> = configs.alts().into_iter().collect();
1578 let alt = *alts
1579 .first()
1580 .ok_or(ParserAtnSimulatorError::PredictionRequiresMoreLookahead)?;
1581 let resolution = if alts.len() > 1 {
1582 FullContextResolution::Ambiguous {
1583 exact: self.exact_ambig_detection,
1584 alts,
1585 }
1586 } else {
1587 FullContextResolution::Unique
1588 };
1589 return Ok(full_context_prediction(
1590 alt,
1591 &configs,
1592 input.index(),
1593 resolution,
1594 ));
1595 }
1596 input.consume();
1597 }
1598 }
1599
1600 fn compute_target_state(
1601 &mut self,
1602 edge: DfaEdge,
1603 configs: &AtnConfigSet,
1604 symbol: i32,
1605 precedence: i32,
1606 merge_cache: &mut PredictionWorkspace,
1607 ) -> Result<DfaStateId, ParserAtnSimulatorError> {
1608 let mut reach = self.compute_reach_set(configs, symbol, false, precedence, merge_cache);
1609 if reach.is_empty() {
1610 if let Some(prediction) = self.alt_that_finished_decision_entry_rule(configs) {
1611 let mut dfa_state = DfaStateBuilder::new(configs.clone());
1612 dfa_state.mark_accept(prediction);
1613 dfa_state.set_has_semantic_context_for_alt(
1616 configs.has_semantic_context()
1617 && configs_have_semantic_context_for_alt(configs, prediction),
1618 );
1619 let target_state = self.add_dfa_state(edge.decision, dfa_state);
1620 self.store.decision_to_dfa[edge.decision].add_edge(
1621 edge.source_state,
1622 symbol,
1623 target_state,
1624 );
1625 return Ok(target_state);
1626 }
1627 return Err(ParserAtnSimulatorError::NoViableAlt { symbol, index: 0 });
1628 }
1629 let prediction = reach.unique_alt();
1630 let conflict_prediction = prediction.or_else(|| {
1631 if !has_sll_conflict_terminating_prediction(&reach, |state| {
1632 self.atn.state(state).is_some_and(AtnState::is_rule_stop)
1633 }) {
1634 return None;
1635 }
1636 reach
1637 .conflicting_alts()
1638 .into_iter()
1639 .next()
1640 .or_else(|| reach.alts().into_iter().next())
1641 });
1642 let requires_full_context = prediction.is_none() && conflict_prediction.is_some();
1643 #[cfg(feature = "perf-counters")]
1644 if requires_full_context {
1645 crate::perf::record_sll_conflict(edge.decision);
1646 }
1647 let conflicting_alts = if requires_full_context {
1648 let alts = reach.conflicting_alts();
1649 if alts.is_empty() { reach.alts() } else { alts }
1650 .into_iter()
1651 .collect()
1652 } else {
1653 Vec::new()
1654 };
1655 let mut dfa_state = DfaStateBuilder::new(reach);
1656 if let Some(prediction) = conflict_prediction {
1657 dfa_state.mark_accept(prediction);
1658 dfa_state.set_requires_full_context(requires_full_context);
1659 dfa_state.set_conflicting_alts(conflicting_alts);
1660 dfa_state.set_has_semantic_context_for_alt(
1663 dfa_state.configs.has_semantic_context()
1664 && configs_have_semantic_context_for_alt(&dfa_state.configs, prediction),
1665 );
1666 }
1667 let target_state = self.add_dfa_state(edge.decision, dfa_state);
1668 self.store.decision_to_dfa[edge.decision].add_edge(edge.source_state, symbol, target_state);
1669 Ok(target_state)
1670 }
1671
1672 fn compute_reach_set(
1673 &mut self,
1674 configs: &AtnConfigSet,
1675 symbol: i32,
1676 full_context: bool,
1677 precedence: i32,
1678 merge_cache: &mut PredictionWorkspace,
1679 ) -> AtnConfigSet {
1680 let mut intermediate = AtnConfigSet::new_full_context(full_context);
1681 let mut skipped_stop_states = Vec::new();
1682 let max_token_type = self.atn.max_token_type();
1683 for config in configs.configs() {
1684 let Some(state) = self.atn.state(config.state) else {
1685 continue;
1686 };
1687 if state.is_rule_stop() {
1688 if full_context || symbol == TOKEN_EOF {
1689 skipped_stop_states.push(config.clone());
1690 }
1691 continue;
1692 }
1693 for transition in &state.transitions() {
1694 if transition.matches(symbol, 1, max_token_type) {
1695 let target =
1696 config.moved_to(transition.target(), config.context, &self.store.contexts);
1697 intermediate.add(target, &mut self.store.contexts, merge_cache);
1698 }
1699 }
1700 }
1701 let mut reach = if skipped_stop_states.is_empty() && symbol != TOKEN_EOF {
1702 if intermediate.len() == 1 || intermediate.unique_alt().is_some() {
1703 intermediate
1704 } else {
1705 self.close_intermediate_reach_set(
1706 intermediate,
1707 full_context,
1708 precedence,
1709 symbol,
1710 merge_cache,
1711 )
1712 }
1713 } else {
1714 self.close_intermediate_reach_set(
1715 intermediate,
1716 full_context,
1717 precedence,
1718 symbol,
1719 merge_cache,
1720 )
1721 };
1722 if symbol == TOKEN_EOF {
1723 reach = self.rule_stop_configs(reach, merge_cache);
1724 }
1725 if !full_context || !self.configs_contain_rule_stop(&reach) {
1726 for config in skipped_stop_states {
1727 reach.add(config, &mut self.store.contexts, merge_cache);
1728 }
1729 }
1730 #[cfg(feature = "perf-counters")]
1731 crate::perf::record_reach_set(full_context, configs.len(), reach.len());
1732 reach
1733 }
1734
1735 fn close_intermediate_reach_set(
1736 &mut self,
1737 intermediate: AtnConfigSet,
1738 full_context: bool,
1739 precedence: i32,
1740 symbol: i32,
1741 merge_cache: &mut PredictionWorkspace,
1742 ) -> AtnConfigSet {
1743 let mut reach = AtnConfigSet::new_full_context(full_context);
1744 let mut scratch = ClosureScratch::default();
1745 let params = ClosureParams {
1746 precedence,
1747 collect_predicates: false,
1748 treat_eof_as_epsilon: symbol == TOKEN_EOF,
1749 };
1750 for config in intermediate.into_configs() {
1753 self.closure(config, &mut reach, merge_cache, &mut scratch, params);
1754 }
1755 reach
1756 }
1757
1758 fn alt_that_finished_decision_entry_rule(&self, configs: &AtnConfigSet) -> Option<usize> {
1759 configs
1760 .configs()
1761 .iter()
1762 .filter(|config| self.config_finished_decision_entry_rule(config))
1763 .map(|config| config.alt)
1764 .min()
1765 }
1766
1767 fn previous_good_alt(&self, configs: &AtnConfigSet) -> Option<PreviousGoodAlt> {
1768 let alt = self.alt_that_finished_decision_entry_rule(configs)?;
1769 let configs = configs
1770 .configs()
1771 .iter()
1772 .filter(|config| config.alt == alt && self.config_finished_decision_entry_rule(config))
1773 .cloned()
1774 .collect();
1775 Some(PreviousGoodAlt { alt, configs })
1776 }
1777
1778 fn config_finished_decision_entry_rule(&self, config: &AtnConfig) -> bool {
1779 config.reaches_into_outer_context > 0
1780 || self
1781 .atn
1782 .state(config.state)
1783 .is_some_and(AtnState::is_rule_stop)
1784 && self.store.contexts.has_empty_path(config.context)
1785 }
1786
1787 fn add_previous_good_alt_target(
1788 &mut self,
1789 edge: DfaEdge,
1790 symbol: i32,
1791 fallback: &PreviousGoodAlt,
1792 merge_cache: &mut PredictionWorkspace,
1793 ) -> DfaStateId {
1794 let mut configs = AtnConfigSet::new();
1795 for config in &fallback.configs {
1796 configs.add(config.clone(), &mut self.store.contexts, merge_cache);
1797 }
1798 let has_semantic_context = configs_have_semantic_context_for_alt(&configs, fallback.alt);
1799 let mut state = DfaStateBuilder::new(configs);
1800 state.mark_accept(fallback.alt);
1801 state.set_has_semantic_context_for_alt(has_semantic_context);
1802 let target = self.add_dfa_state(edge.decision, state);
1803 self.store.decision_to_dfa[edge.decision].add_edge(edge.source_state, symbol, target);
1804 target
1805 }
1806
1807 fn prediction_reached_decision_entry_rule_stop(
1808 &mut self,
1809 edge: DfaEdge,
1810 alt: usize,
1811 precedence: i32,
1812 symbol: i32,
1813 merge_cache: &mut PredictionWorkspace,
1814 ) -> bool {
1815 let configs = self.store.decision_to_dfa[edge.decision]
1816 .configs(edge.source_state)
1817 .clone();
1818 if self.alt_that_finished_decision_entry_rule(&configs) == Some(alt) {
1819 return true;
1820 }
1821 let closed =
1822 self.close_intermediate_reach_set(configs, false, precedence, symbol, merge_cache);
1823 self.alt_that_finished_decision_entry_rule(&closed) == Some(alt)
1824 }
1825
1826 fn rule_stop_configs(
1827 &mut self,
1828 configs: AtnConfigSet,
1829 merge_cache: &mut PredictionWorkspace,
1830 ) -> AtnConfigSet {
1831 if configs.configs().iter().all(|config| {
1832 self.atn
1833 .state(config.state)
1834 .is_some_and(AtnState::is_rule_stop)
1835 }) {
1836 return configs;
1837 }
1838 let mut result = AtnConfigSet::new_full_context(configs.full_context());
1839 for config in configs.configs().iter().filter(|config| {
1840 self.atn
1841 .state(config.state)
1842 .is_some_and(AtnState::is_rule_stop)
1843 }) {
1844 result.add(config.clone(), &mut self.store.contexts, merge_cache);
1845 }
1846 result
1847 }
1848
1849 fn configs_all_reached_rule_stop(&self, configs: &AtnConfigSet) -> bool {
1850 configs.configs().iter().all(|config| {
1851 self.atn
1852 .state(config.state)
1853 .is_some_and(AtnState::is_rule_stop)
1854 })
1855 }
1856
1857 fn configs_contain_rule_stop(&self, configs: &AtnConfigSet) -> bool {
1858 configs.configs().iter().any(|config| {
1859 self.atn
1860 .state(config.state)
1861 .is_some_and(AtnState::is_rule_stop)
1862 })
1863 }
1864
1865 fn closure(
1866 &mut self,
1867 config: AtnConfig,
1868 configs: &mut AtnConfigSet,
1869 merge_cache: &mut PredictionWorkspace,
1870 scratch: &mut ClosureScratch,
1871 params: ClosureParams,
1872 ) {
1873 let ClosureParams {
1874 precedence,
1875 collect_predicates,
1876 treat_eof_as_epsilon,
1877 } = params;
1878 let max_token_type = self.atn.max_token_type();
1879 scratch.stack.clear();
1880 scratch.visited.clear();
1881 scratch.stack.push((config, collect_predicates));
1882 while let Some((config, collect_predicates)) = scratch.stack.pop() {
1883 if !scratch.visited.insert(ClosureConfigKey::from(&config)) {
1884 continue;
1885 }
1886 let Some(state) = self.atn.state(config.state) else {
1887 continue;
1888 };
1889 let at_rule_stop = state.is_rule_stop();
1890 if at_rule_stop
1891 && self.closure_at_rule_stop(
1892 config.clone(),
1893 collect_predicates,
1894 configs,
1895 merge_cache,
1896 &mut scratch.stack,
1897 )
1898 {
1899 continue;
1900 }
1901 let epsilon_only = state.epsilon_only();
1902 if !epsilon_only {
1903 configs.add(config.clone(), &mut self.store.contexts, merge_cache);
1904 }
1905 for (index, transition) in state.transitions().iter().enumerate() {
1906 if index == 0
1907 && can_drop_left_recursive_loop_entry_edge(
1908 self.atn,
1909 state,
1910 &self.store.contexts,
1911 config.context,
1912 )
1913 {
1914 continue;
1915 }
1916 let transition_kind = transition.kind();
1917 if matches!(
1918 transition_kind,
1919 ParserTransitionKind::Epsilon
1920 | ParserTransitionKind::Rule
1921 | ParserTransitionKind::Predicate
1922 | ParserTransitionKind::Action
1923 | ParserTransitionKind::Precedence
1924 ) {
1925 if let Some(mut target) = self.epsilon_target_config(
1926 &config,
1927 transition,
1928 transition_kind,
1929 precedence,
1930 collect_predicates,
1931 configs.full_context(),
1932 ) {
1933 if at_rule_stop {
1934 target.reaches_into_outer_context =
1935 target.reaches_into_outer_context.saturating_add(1);
1936 }
1937 let target_collect_predicates =
1941 collect_predicates && transition_kind != ParserTransitionKind::Action;
1942 scratch.stack.push((target, target_collect_predicates));
1943 }
1944 } else if treat_eof_as_epsilon
1945 && transition.matches_kind(transition_kind, TOKEN_EOF, 1, max_token_type)
1946 {
1947 scratch.stack.push((
1948 config.moved_to(transition.target(), config.context, &self.store.contexts),
1949 collect_predicates,
1950 ));
1951 }
1952 }
1953 }
1954 let closure_work = scratch.visited.len();
1955 if self.measure_adaptive_work {
1956 self.adaptive_closure_work = self.adaptive_closure_work.saturating_add(closure_work);
1957 }
1958 #[cfg(feature = "perf-counters")]
1959 crate::perf::record_closure(closure_work);
1960 }
1961
1962 fn closure_at_rule_stop(
1963 &mut self,
1964 config: AtnConfig,
1965 collect_predicates: bool,
1966 configs: &mut AtnConfigSet,
1967 merge_cache: &mut PredictionWorkspace,
1968 stack: &mut Vec<(AtnConfig, bool)>,
1969 ) -> bool {
1970 if self.store.contexts.is_empty(config.context) {
1971 if configs.full_context() {
1972 configs.add(config, &mut self.store.contexts, merge_cache);
1973 return true;
1974 }
1975 return false;
1976 }
1977 let mut handled_all_paths = true;
1978 for index in 0..self.store.contexts.len(config.context) {
1979 let Some(return_state) = self.store.contexts.return_state(config.context, index) else {
1980 continue;
1981 };
1982 if return_state == EMPTY_RETURN_STATE {
1983 if configs.full_context() {
1984 let mut empty_context_config = config.clone();
1985 empty_context_config.set_context(EMPTY_CONTEXT, &self.store.contexts);
1986 configs.add(empty_context_config, &mut self.store.contexts, merge_cache);
1987 } else {
1988 handled_all_paths = false;
1989 }
1990 continue;
1991 }
1992 let parent = self
1993 .store
1994 .contexts
1995 .parent(config.context, index)
1996 .unwrap_or(EMPTY_CONTEXT);
1997 let next = config.moved_to(return_state, parent, &self.store.contexts);
1998 stack.push((next, collect_predicates));
1999 }
2000 handled_all_paths
2001 }
2002
2003 #[allow(clippy::too_many_arguments)]
2004 fn epsilon_target_config(
2005 &mut self,
2006 config: &AtnConfig,
2007 transition: ParserTransition<'_>,
2008 transition_kind: ParserTransitionKind,
2009 precedence: i32,
2010 collect_predicates: bool,
2011 full_context: bool,
2012 ) -> Option<AtnConfig> {
2013 let semantic_context = match transition_kind {
2014 ParserTransitionKind::Predicate if collect_predicates => SemanticContext::and(
2015 config.semantic_context.clone(),
2016 SemanticContext::Predicate {
2017 rule_index: transition.arg0() as usize,
2018 pred_index: transition.arg1() as usize,
2019 context_dependent: transition.arg2() != 0,
2020 },
2021 ),
2022 ParserTransitionKind::Precedence
2023 if collect_predicates
2024 && i32::from_le_bytes(transition.arg0().to_le_bytes()) < precedence =>
2025 {
2026 return None;
2027 }
2028 ParserTransitionKind::Precedence if collect_predicates && !full_context => {
2029 SemanticContext::and(
2030 config.semantic_context.clone(),
2031 SemanticContext::Precedence {
2032 precedence: i32::from_le_bytes(transition.arg0().to_le_bytes()),
2033 },
2034 )
2035 }
2036 _ => config.semantic_context.clone(),
2037 };
2038 let context = if transition_kind == ParserTransitionKind::Rule {
2039 self.store
2040 .contexts
2041 .singleton(config.context, transition.arg1() as usize)
2042 } else {
2043 config.context
2044 };
2045 let mut target = config.moved_to(transition.target(), context, &self.store.contexts);
2046 target.semantic_context = semantic_context;
2047 Some(target)
2048 }
2049
2050 fn dfa_prediction_info(
2051 &self,
2052 decision: usize,
2053 state_number: DfaStateId,
2054 ) -> Option<DfaPredictionInfo> {
2055 let dfa = self.store.decision_to_dfa.get(decision)?;
2056 let state = dfa.state(state_number)?;
2057 let alt = state.prediction()?;
2058 let requires_full_context = state.requires_full_context();
2059 let conflicting_alts = if requires_full_context {
2060 let stored = dfa.conflicting_alts(state_number);
2061 if stored.is_empty() {
2062 dfa.configs(state_number).alts().into_iter().collect()
2063 } else {
2064 stored.to_vec()
2065 }
2066 } else {
2067 Vec::new()
2068 };
2069 Some(DfaPredictionInfo {
2070 prediction: ParserAtnPrediction {
2071 alt,
2072 requires_full_context,
2073 has_semantic_context: state.has_semantic_context(),
2076 diagnostic: None,
2077 },
2078 conflicting_alts,
2079 })
2080 }
2081}
2082
2083pub(crate) fn can_drop_left_recursive_loop_entry_edge(
2086 atn: &Atn,
2087 state: AtnState<'_>,
2088 contexts: &ContextArena,
2089 context: ContextId,
2090) -> bool {
2091 if state.kind() != AtnStateKind::StarLoopEntry
2092 || !state.precedence_rule_decision()
2093 || contexts.is_empty(context)
2094 || contexts.has_empty_path(context)
2095 {
2096 return false;
2097 }
2098 let Some(rule_index) = state.rule_index() else {
2099 return false;
2100 };
2101 for index in 0..contexts.len(context) {
2102 let Some(return_state_number) = contexts.return_state(context, index) else {
2103 return false;
2104 };
2105 let Some(return_state) = atn.state(return_state_number) else {
2106 return false;
2107 };
2108 if return_state.rule_index() != Some(rule_index) {
2109 return false;
2110 }
2111 }
2112 let Some(block_end_state_number) = state
2113 .transitions()
2114 .first()
2115 .and_then(|transition| atn.state(transition.target()))
2116 .and_then(AtnState::end_state)
2117 else {
2118 return false;
2119 };
2120 for index in 0..contexts.len(context) {
2121 let return_state_number = contexts
2122 .return_state(context, index)
2123 .expect("return state checked above");
2124 let return_state = atn
2125 .state(return_state_number)
2126 .expect("return state checked above");
2127 if return_state.state_number() == block_end_state_number {
2128 continue;
2129 }
2130 if return_state.transitions().len() != 1
2131 || !return_state
2132 .transitions()
2133 .first()
2134 .is_some_and(ParserTransition::is_epsilon)
2135 {
2136 return false;
2137 }
2138 let return_target = return_state
2139 .transitions()
2140 .first()
2141 .expect("single transition checked above")
2142 .target();
2143 if return_state.kind() == AtnStateKind::BlockEnd && return_target == state.state_number() {
2144 continue;
2145 }
2146 if return_target == block_end_state_number {
2147 continue;
2148 }
2149 let Some(return_target_state) = atn.state(return_target) else {
2150 return false;
2151 };
2152 if return_target_state.kind() == AtnStateKind::BlockEnd
2153 && return_target_state.transitions().len() == 1
2154 && return_target_state
2155 .transitions()
2156 .first()
2157 .is_some_and(ParserTransition::is_epsilon)
2158 && return_target_state
2159 .transitions()
2160 .first()
2161 .is_some_and(|transition| transition.target() == state.state_number())
2162 {
2163 continue;
2164 }
2165 return false;
2166 }
2167 true
2168}
2169
2170fn configs_have_semantic_context_for_alt(configs: &AtnConfigSet, alt: usize) -> bool {
2171 configs
2172 .configs()
2173 .iter()
2174 .any(|config| config.alt == alt && !config.semantic_context.is_none())
2175}
2176
2177#[derive(Clone, Debug, Eq, PartialEq)]
2178pub enum ParserAtnSimulatorError {
2179 MissingAtnState(usize),
2180 MissingDfaState(DfaStateId),
2181 NoViableAlt { symbol: i32, index: usize },
2182 PredictionRequiresMoreLookahead,
2183 UnknownDecision(usize),
2184}
2185
2186fn dfa_state_display(state: ParserDfaStateView<'_>, deferred: bool) -> String {
2188 let mut out = String::new();
2189 let is_accept = state.is_accept_state() && !deferred;
2190 if is_accept {
2191 out.push(':');
2192 }
2193 out.push('s');
2194 out.push_str(&state.id().index().to_string());
2195 if state.requires_full_context() {
2196 out.push('^');
2197 }
2198 if is_accept {
2199 out.push_str("=>");
2200 out.push_str(
2201 &state
2202 .prediction()
2203 .map(|prediction| prediction.to_string())
2204 .unwrap_or_default(),
2205 );
2206 }
2207 out
2208}
2209
2210#[cfg(test)]
2211#[allow(clippy::disallowed_methods)] mod tests {
2213 use super::*;
2214 use crate::atn::AtnStateKind;
2215
2216 fn finish_atn(builder: ParserAtnBuilder) -> Atn {
2217 builder.finish().expect("valid packed parser ATN")
2218 }
2219
2220 #[test]
2221 fn union_decision_dfa_preserves_disjoint_coverage() {
2222 fn configs(
2223 atn_state: usize,
2224 arena: &mut ContextArena,
2225 workspace: &mut PredictionWorkspace,
2226 ) -> AtnConfigSet {
2227 let mut set = AtnConfigSet::new();
2228 set.add(
2229 AtnConfig::new(atn_state, 1, EMPTY_CONTEXT, arena),
2230 arena,
2231 workspace,
2232 );
2233 set
2234 }
2235 fn state(
2236 atn_state: usize,
2237 arena: &mut ContextArena,
2238 workspace: &mut PredictionWorkspace,
2239 ) -> DfaStateBuilder {
2240 DfaStateBuilder::new(configs(atn_state, arena, workspace))
2241 }
2242 let mut arena = ContextArena::new();
2243 let mut workspace = PredictionWorkspace::default();
2244
2245 let mut shared = ParserDfa::with_max_token_type(0, 0, 8);
2249 let shared_root = shared.add_state(state(10, &mut arena, &mut workspace));
2250 let shared_a = shared.add_state(state(11, &mut arena, &mut workspace));
2251 shared.add_edge(shared_root, 1, shared_a);
2252 shared.set_start_state(shared_root);
2253
2254 let mut local = ParserDfa::with_max_token_type(0, 0, 8);
2255 let local_b = local.add_state(state(12, &mut arena, &mut workspace));
2256 let local_root = local.add_state(state(10, &mut arena, &mut workspace));
2257 local.add_edge(local_root, 2, local_b);
2258 local.set_precedence_start_state(3, local_root);
2259
2260 union_decision_dfa(&mut shared, local);
2261
2262 assert_eq!(shared.edge(shared_root, 1), Some(shared_a));
2265 let merged_b = shared
2266 .state_id_for_configs(&configs(12, &mut arena, &mut workspace))
2267 .expect("local-only state adopted");
2268 assert_eq!(shared.edge(shared_root, 2), Some(merged_b));
2269 assert_eq!(shared.states().len(), 3);
2270 assert_eq!(shared.start_state(), Some(shared_root));
2272 assert_eq!(shared.precedence_start_state(3), Some(shared_root));
2273 }
2274
2275 #[test]
2276 fn union_prediction_stores_remaps_context_ids_before_dfa_union() {
2277 let atn = two_token_decision_atn();
2278 let mut shared = PredictionStore::new(&atn);
2279 let mut local = PredictionStore::new(&atn);
2280 let mut workspace = PredictionWorkspace::default();
2281
2282 let distracting = shared.contexts.singleton(EMPTY_CONTEXT, 99);
2283 let local_context = local.contexts.singleton(EMPTY_CONTEXT, 7);
2284 assert_eq!(distracting, local_context, "both stores allocate ID 1");
2285
2286 let mut configs = AtnConfigSet::new();
2287 configs.add(
2288 AtnConfig::new(42, 1, local_context, &local.contexts),
2289 &mut local.contexts,
2290 &mut workspace,
2291 );
2292 local.decision_to_dfa[0].add_state(DfaStateBuilder::new(configs));
2293
2294 union_prediction_stores(&mut shared, local, &mut workspace);
2295
2296 let imported = shared.decision_to_dfa[0]
2297 .states()
2298 .flat_map(|state| shared.decision_to_dfa[0].configs(state.id()).configs())
2299 .find(|config| config.state == 42)
2300 .expect("local DFA config imported");
2301 assert_ne!(imported.context, local_context);
2302 assert_eq!(shared.contexts.return_state(imported.context, 0), Some(7));
2303 imported.assert_store(&shared.contexts);
2304 }
2305
2306 #[test]
2307 fn outer_context_cache_invalidates_with_rule_context_version() {
2308 let atn = two_token_decision_atn();
2309 let mut simulator = ParserAtnSimulator::new(&atn);
2310
2311 let first = simulator.intern_prediction_context(1, [7]);
2312 let cached = simulator.intern_prediction_context(1, [99]);
2313 let refreshed = simulator.intern_prediction_context(2, [99]);
2314
2315 assert_eq!(cached, first);
2316 assert_ne!(refreshed, first);
2317 assert_eq!(
2318 simulator.store.contexts.return_state(refreshed, 0),
2319 Some(99)
2320 );
2321 let stats = simulator.prediction_context_stats();
2322 assert_eq!(stats.outer_context_cache_hits, 1);
2323 assert_eq!(stats.outer_context_cache_misses, 2);
2324 }
2325
2326 #[test]
2327 fn outer_context_cache_is_simulator_local() {
2328 let atn = two_token_decision_atn();
2329 let mut first = ParserAtnSimulator::new(&atn);
2330 let mut second = ParserAtnSimulator::new(&atn);
2331
2332 let first_context = first.intern_prediction_context(1, [7]);
2333 let second_context = second.intern_prediction_context(1, [99]);
2334
2335 assert_eq!(first.store.contexts.return_state(first_context, 0), Some(7));
2336 assert_eq!(
2337 second.store.contexts.return_state(second_context, 0),
2338 Some(99)
2339 );
2340 }
2341
2342 #[test]
2343 fn adaptive_atn_preference_requires_expensive_prediction_delta() {
2344 assert!(!ParserAtnSimulator::adaptive_prediction_delta_is_expensive(
2345 (0, 0),
2346 (ADAPTIVE_ATN_PREFERENCE_MIN_CALLS - 1, usize::MAX),
2347 ));
2348 assert!(!ParserAtnSimulator::adaptive_prediction_delta_is_expensive(
2349 (5, 7),
2350 (
2351 5 + ADAPTIVE_ATN_PREFERENCE_MIN_CALLS,
2352 7 + ADAPTIVE_ATN_PREFERENCE_MIN_CALLS
2353 * ADAPTIVE_ATN_PREFERENCE_MIN_CLOSURE_WORK_PER_CALL
2354 - 1,
2355 ),
2356 ));
2357 assert!(ParserAtnSimulator::adaptive_prediction_delta_is_expensive(
2358 (5, 7),
2359 (
2360 5 + ADAPTIVE_ATN_PREFERENCE_MIN_CALLS,
2361 7 + ADAPTIVE_ATN_PREFERENCE_MIN_CALLS
2362 * ADAPTIVE_ATN_PREFERENCE_MIN_CLOSURE_WORK_PER_CALL,
2363 ),
2364 ));
2365 assert!(!ParserAtnSimulator::adaptive_prediction_delta_is_decisive(
2366 (5, 7),
2367 (
2368 5 + ADAPTIVE_ATN_PREFERENCE_MIN_CALLS,
2369 7 + ADAPTIVE_ATN_PREFERENCE_MIN_CALLS
2370 * ADAPTIVE_ATN_PREFERENCE_DECISIVE_CLOSURE_WORK_PER_CALL
2371 - 1,
2372 ),
2373 ));
2374 assert!(ParserAtnSimulator::adaptive_prediction_delta_is_decisive(
2375 (5, 7),
2376 (
2377 5 + ADAPTIVE_ATN_PREFERENCE_MIN_CALLS,
2378 7 + ADAPTIVE_ATN_PREFERENCE_MIN_CALLS
2379 * ADAPTIVE_ATN_PREFERENCE_DECISIVE_CLOSURE_WORK_PER_CALL,
2380 ),
2381 ));
2382 }
2383
2384 #[test]
2385 fn adaptive_atn_preference_excludes_first_population_per_decision() {
2386 let atn = two_independent_decisions_atn();
2387 let mut simulator = ParserAtnSimulator::new(&atn);
2388
2389 assert_eq!(simulator.adaptive_prediction_work(), None);
2390 assert_eq!(simulator.adaptive_predict(0, [1, 2]), Ok(1));
2391 let after_first_decision = simulator
2392 .adaptive_prediction_work()
2393 .expect("one decision is trained");
2394 assert_eq!(after_first_decision, (0, 0));
2395
2396 assert_eq!(simulator.adaptive_predict(1, [1, 2]), Ok(1));
2397 assert_eq!(
2398 simulator.adaptive_prediction_work(),
2399 Some(after_first_decision),
2400 "cold work for another decision must not enter the routing counters"
2401 );
2402
2403 assert_eq!(simulator.adaptive_predict(1, [1, 2]), Ok(1));
2404 let after_warm_decision = simulator
2405 .adaptive_prediction_work()
2406 .expect("trained decision work is measurable");
2407 assert_eq!(after_warm_decision.0, after_first_decision.0 + 1);
2408 }
2409
2410 #[test]
2411 fn adaptive_atn_preference_excludes_incremental_population_per_decision() {
2412 let atn = two_token_decision_atn();
2413 let mut simulator = ParserAtnSimulator::new(&atn);
2414
2415 assert_eq!(simulator.adaptive_predict(0, [1, 2]), Ok(1));
2416 let after_first_path = simulator
2417 .adaptive_prediction_work()
2418 .expect("the decision is partially trained");
2419 let transitions_after_first_path = simulator.decision_dfas()[0].stats().transitions;
2420
2421 assert_eq!(simulator.adaptive_predict(0, [1, 3]), Ok(2));
2422 assert!(
2423 simulator.decision_dfas()[0].stats().transitions > transitions_after_first_path,
2424 "the second input must extend the partially populated DFA"
2425 );
2426 assert_eq!(
2427 simulator.adaptive_prediction_work(),
2428 Some(after_first_path),
2429 "incremental DFA construction must not enter the routing counters"
2430 );
2431
2432 assert_eq!(simulator.adaptive_predict(0, [1, 3]), Ok(2));
2433 assert_eq!(
2434 simulator
2435 .adaptive_prediction_work()
2436 .expect("the repeated path is stable")
2437 .0,
2438 after_first_path.0 + 1
2439 );
2440 }
2441
2442 #[test]
2443 fn reset_retains_adaptive_training_and_clear_dfa_cools_it() {
2444 let atn = two_token_decision_atn();
2445 let mut simulator = ParserAtnSimulator::new(&atn);
2446 assert_eq!(simulator.adaptive_prediction_work(), None);
2447 assert_eq!(simulator.adaptive_predict(0, [1, 2]), Ok(1));
2448 assert_eq!(simulator.adaptive_prediction_work(), Some((0, 0)));
2449
2450 simulator.reset();
2451 assert_eq!(simulator.adaptive_calls, 0);
2452 assert_eq!(simulator.adaptive_closure_work, 0);
2453 assert_eq!(simulator.adaptive_prediction_work(), Some((0, 0)));
2454
2455 assert_eq!(simulator.adaptive_predict(0, [1, 2]), Ok(1));
2456 assert_eq!(
2457 simulator
2458 .adaptive_prediction_work()
2459 .expect("warmed counters")
2460 .0,
2461 1
2462 );
2463
2464 simulator.clear_dfa();
2465 assert_eq!(simulator.adaptive_calls, 0);
2466 assert_eq!(simulator.adaptive_closure_work, 0);
2467 assert_eq!(simulator.adaptive_prediction_work(), None);
2468 }
2469
2470 #[test]
2471 fn adaptive_predict_reuses_dense_dfa_edges() {
2472 let atn = two_token_decision_atn();
2473 let mut simulator = ParserAtnSimulator::new(&atn);
2474
2475 assert_eq!(simulator.adaptive_predict(0, [1, 2]), Ok(1));
2476 assert_eq!(simulator.adaptive_predict(0, [1, 3]), Ok(2));
2477
2478 let dfa = &simulator.decision_dfas()[0];
2479 let start = dfa.start_state().expect("start state");
2480 let after_first = dfa.state(start).and_then(|state| state.edge(1));
2481 assert!(after_first.is_some());
2482 }
2483
2484 #[test]
2485 fn shared_simulator_reuses_learned_dfa_states() {
2486 let atn = Box::leak(Box::new(two_token_decision_atn()));
2487 let learned_states = {
2488 let mut simulator = ParserAtnSimulator::new_shared(atn);
2489 assert_eq!(simulator.adaptive_predict(0, [1, 2]), Ok(1));
2490 simulator.decision_dfas()[0].states().len()
2491 };
2492
2493 let simulator = ParserAtnSimulator::new_shared(atn);
2494 assert_eq!(simulator.decision_dfas()[0].states().len(), learned_states);
2495 }
2496
2497 #[test]
2498 fn shared_simulator_preserves_and_clears_prediction_training_state() {
2499 let atn = Box::leak(Box::new(two_token_decision_atn()));
2500 {
2501 let mut simulator = ParserAtnSimulator::new_shared(atn);
2502 assert_eq!(simulator.adaptive_predict(0, [1, 2]), Ok(1));
2503 }
2504
2505 {
2506 let simulator = ParserAtnSimulator::new_shared(atn);
2507 assert_eq!(simulator.adaptive_prediction_work(), Some((0, 0)));
2508 }
2509
2510 ParserAtnSimulator::clear_shared_dfa(atn);
2511 let simulator = ParserAtnSimulator::new_shared(atn);
2512 assert_eq!(simulator.adaptive_prediction_work(), None);
2513 }
2514
2515 #[test]
2516 fn overlapping_shared_simulator_treats_an_empty_store_as_cold() {
2517 let atn = Box::leak(Box::new(two_token_decision_atn()));
2518 {
2519 let mut simulator = ParserAtnSimulator::new_shared(atn);
2520 assert_eq!(simulator.adaptive_predict(0, [1, 2]), Ok(1));
2521 }
2522
2523 let warmed = ParserAtnSimulator::new_shared(atn);
2524 assert_eq!(warmed.adaptive_prediction_work(), Some((0, 0)));
2525 let overlapping = ParserAtnSimulator::new_shared(atn);
2526 assert_eq!(overlapping.adaptive_prediction_work(), None);
2527 }
2528
2529 #[test]
2530 fn clear_shared_dfa_drops_learned_states() {
2531 let atn = Box::leak(Box::new(two_token_decision_atn()));
2532 {
2533 let mut simulator = ParserAtnSimulator::new_shared(atn);
2534 assert_eq!(simulator.adaptive_predict(0, [1, 2]), Ok(1));
2535 assert!(!simulator.decision_dfas()[0].is_empty());
2536 }
2537
2538 ParserAtnSimulator::clear_shared_dfa(atn);
2539
2540 let simulator = ParserAtnSimulator::new_shared(atn);
2541 assert!(simulator.decision_dfas()[0].is_empty());
2542 }
2543
2544 #[test]
2545 fn clear_dfa_rejects_stale_overlapping_simulator_publication() {
2546 let atn = Box::leak(Box::new(two_token_decision_atn()));
2547 let mut current = ParserAtnSimulator::new_shared(atn);
2548 let mut stale = ParserAtnSimulator::new_shared(atn);
2549 assert_eq!(stale.adaptive_predict(0, [1, 2]), Ok(1));
2550 assert!(!stale.decision_dfas()[0].is_empty());
2551
2552 current.clear_dfa();
2553 drop(stale);
2554 drop(current);
2555
2556 let simulator = ParserAtnSimulator::new_shared(atn);
2557 assert!(simulator.decision_dfas()[0].is_empty());
2558 }
2559
2560 #[test]
2561 fn adaptive_predict_reports_no_viable_alt() {
2562 let atn = two_token_decision_atn();
2563 let mut simulator = ParserAtnSimulator::new(&atn);
2564
2565 assert_eq!(
2566 simulator.adaptive_predict(0, [4]),
2567 Err(ParserAtnSimulatorError::NoViableAlt {
2568 symbol: 4,
2569 index: 0
2570 })
2571 );
2572 }
2573
2574 #[test]
2575 fn adaptive_predict_marks_sll_conflict_for_full_context() {
2576 let atn = ambiguous_single_token_decision_atn();
2577 let mut simulator = ParserAtnSimulator::new(&atn);
2578
2579 assert_eq!(simulator.adaptive_predict(0, [1]), Ok(1));
2580 let prediction = simulator
2581 .adaptive_predict_info_with_precedence(0, 0, [1])
2582 .expect("prediction");
2583 insta::assert_debug_snapshot!(
2584 "adaptive_predict_marks_sll_conflict_for_full_context",
2585 prediction
2586 );
2587
2588 let dfa = &simulator.decision_dfas()[0];
2589 let start = dfa.start_state().expect("start state");
2590 let target = dfa
2591 .state(start)
2592 .and_then(|state| state.edge(1))
2593 .expect("edge for token 1");
2594 let state = dfa.state(target).expect("target state");
2595 assert!(state.is_accept_state());
2596 assert!(state.requires_full_context());
2597 assert_eq!(state.prediction(), Some(1));
2598 }
2599
2600 #[test]
2601 fn adaptive_predict_keeps_rule_stop_configs_at_eof() {
2602 let atn = optional_token_decision_atn();
2603 let mut simulator = ParserAtnSimulator::new(&atn);
2604
2605 assert_eq!(simulator.adaptive_predict(0, [TOKEN_EOF]), Ok(2));
2606 }
2607
2608 #[test]
2609 fn adaptive_predict_treats_repeated_eof_as_epsilon_after_first_eof() {
2610 let atn = multiple_eof_decision_atn();
2611 let mut simulator = ParserAtnSimulator::new(&atn);
2612
2613 assert_eq!(simulator.adaptive_predict(0, [1, TOKEN_EOF]), Ok(1));
2614 }
2615
2616 #[test]
2617 fn adaptive_predict_uses_finished_entry_rule_alt_on_error_edge() {
2618 let atn = prefix_alt_decision_atn();
2619 let mut simulator = ParserAtnSimulator::new(&atn);
2620
2621 assert_eq!(simulator.adaptive_predict(0, [1, 3]), Ok(1));
2622 }
2623
2624 #[test]
2625 fn adaptive_predict_keeps_prefix_alt_until_longer_alt_finishes() {
2626 let atn = three_token_prefix_alt_decision_atn();
2627 let mut simulator = ParserAtnSimulator::new(&atn);
2628
2629 assert_eq!(simulator.adaptive_predict(0, [1, 2, TOKEN_EOF]), Ok(1));
2630 assert_eq!(simulator.adaptive_predict(0, [1, 2, 1, TOKEN_EOF]), Ok(2));
2631 }
2632
2633 #[test]
2634 fn sll_probe_keeps_unique_alt_early_termination() {
2635 let atn = three_token_prefix_alt_decision_atn();
2636 let mut simulator = ParserAtnSimulator::new(&atn);
2637 let mut input = VecIntStream::new(vec![1, 2, TOKEN_EOF]);
2638
2639 let prediction = simulator
2640 .adaptive_predict_stream_info_sll_probe(0, 0, &mut input)
2641 .expect("SLL prediction should succeed");
2642
2643 assert_eq!(prediction.alt, 2);
2644 }
2645
2646 #[test]
2647 fn adaptive_predict_uses_precedence_dfa_start_states() {
2648 let atn = two_token_decision_atn_with_precedence(true);
2649 let mut simulator = ParserAtnSimulator::new(&atn);
2650
2651 assert_eq!(
2652 simulator.adaptive_predict_with_precedence(0, 3, [1, 2]),
2653 Ok(1)
2654 );
2655 assert_eq!(
2656 simulator.adaptive_predict_with_precedence(0, 7, [1, 3]),
2657 Ok(2)
2658 );
2659
2660 let dfa = &simulator.decision_dfas()[0];
2661 assert!(dfa.is_precedence_dfa());
2662 assert!(dfa.precedence_start_state(3).is_some());
2663 assert!(dfa.precedence_start_state(7).is_some());
2664 }
2665
2666 #[test]
2667 fn adaptive_predict_stream_restores_input_position() {
2668 let atn = two_token_decision_atn();
2669 let mut simulator = ParserAtnSimulator::new(&atn);
2670 let mut input = VecIntStream::new(vec![1, 3, TOKEN_EOF]);
2671
2672 assert_eq!(simulator.adaptive_predict_stream(0, &mut input), Ok(2));
2673 assert_eq!(input.index(), 0);
2674 assert_eq!(input.la(1), 1);
2675 }
2676
2677 #[test]
2678 fn adaptive_predict_stream_retries_full_context_conflict() {
2679 let atn = ambiguous_single_token_decision_atn();
2680 let mut simulator = ParserAtnSimulator::new(&atn);
2681 let mut input = VecIntStream::new(vec![1, TOKEN_EOF]);
2682
2683 let prediction = simulator
2684 .adaptive_predict_stream_info_with_precedence(0, 0, &mut input)
2685 .expect("prediction");
2686
2687 insta::assert_debug_snapshot!(
2688 "adaptive_predict_stream_retries_full_context_conflict",
2689 prediction
2690 );
2691 assert_eq!(input.index(), 0);
2692 }
2693
2694 #[test]
2695 fn full_context_memo_replays_identical_retries() {
2696 let atn = ambiguous_single_token_decision_atn();
2697 let mut simulator = ParserAtnSimulator::new(&atn);
2698
2699 let mut input = VecIntStream::new(vec![1, TOKEN_EOF]);
2702 let fresh = simulator
2703 .adaptive_predict_stream_info_with_context(0, 0, &mut input, EMPTY_CONTEXT)
2704 .expect("fresh prediction");
2705 assert_eq!(simulator.full_context_memo_len, 1);
2706 assert_eq!(input.index(), 0, "cursor restored after prediction");
2707
2708 let replayed = simulator
2712 .adaptive_predict_stream_info_with_context(0, 0, &mut input, EMPTY_CONTEXT)
2713 .expect("memoized prediction");
2714 assert_eq!(replayed, fresh);
2715 assert_eq!(simulator.full_context_memo_len, 1, "no duplicate entry");
2716 assert_eq!(input.index(), 0);
2717
2718 let mut other_input = VecIntStream::new(vec![2, TOKEN_EOF]);
2721 let other = simulator.adaptive_predict_stream_info_with_context(
2722 0,
2723 0,
2724 &mut other_input,
2725 EMPTY_CONTEXT,
2726 );
2727 assert!(other.is_err(), "different window must not replay");
2730
2731 let context = simulator.store.contexts.singleton(EMPTY_CONTEXT, 6);
2733 let mut input = VecIntStream::new(vec![1, TOKEN_EOF]);
2734 let _ = simulator
2735 .adaptive_predict_stream_info_with_context(0, 0, &mut input, context)
2736 .expect("prediction under a different context");
2737 assert_eq!(
2738 simulator.full_context_memo_len, 2,
2739 "distinct context records its own entry"
2740 );
2741 }
2742
2743 #[test]
2744 fn full_context_memo_walks_multi_token_windows() {
2745 let atn = ambiguous_three_token_decision_atn();
2746 let mut simulator = ParserAtnSimulator::new(&atn);
2747
2748 let mut input = VecIntStream::new(vec![1, 2, 3, TOKEN_EOF]);
2751 let fresh = simulator
2752 .adaptive_predict_stream_info_with_context(0, 0, &mut input, EMPTY_CONTEXT)
2753 .expect("fresh prediction");
2754 assert_eq!(simulator.full_context_memo_len, 1);
2755 let recorded_window_len = simulator
2756 .full_context_memo
2757 .values()
2758 .next()
2759 .and_then(|entries| entries.first())
2760 .map(|entry| entry.window_tail.len())
2761 .expect("one recorded entry");
2762 assert!(
2763 recorded_window_len >= 1,
2764 "the LL loop consumed tokens, so the window tail must be non-empty"
2765 );
2766
2767 let replayed = simulator
2770 .adaptive_predict_stream_info_with_context(0, 0, &mut input, EMPTY_CONTEXT)
2771 .expect("memoized prediction");
2772 assert_eq!(replayed, fresh);
2773 assert_eq!(input.index(), 0, "cursor restored by the caller wrapper");
2774
2775 let mut diverging = VecIntStream::new(vec![1, 9, 9, TOKEN_EOF]);
2781 let result = simulator.adaptive_predict_stream_info_with_context(
2782 0,
2783 0,
2784 &mut diverging,
2785 EMPTY_CONTEXT,
2786 );
2787 assert!(result.is_err(), "mid-window divergence must not replay");
2788 assert_eq!(simulator.full_context_memo_len, 1);
2789 }
2790
2791 #[test]
2792 fn full_context_memo_stays_off_for_predicated_atns_and_exact_mode() {
2793 let atn = ambiguous_single_token_decision_atn();
2796 let mut simulator = ParserAtnSimulator::new(&atn);
2797 simulator.set_exact_ambig_detection(true);
2798 let mut input = VecIntStream::new(vec![1, TOKEN_EOF]);
2799 let _ = simulator
2800 .adaptive_predict_stream_info_with_context(0, 0, &mut input, EMPTY_CONTEXT)
2801 .expect("prediction");
2802 assert_eq!(simulator.full_context_memo_len, 0);
2803
2804 let mut atn = ParserAtnBuilder::new(1);
2807 add_state(&mut atn, 0, AtnStateKind::Basic);
2808 add_state(&mut atn, 1, AtnStateKind::Basic);
2809 atn.add_transition(
2810 0,
2811 ParserTransitionSpec::Predicate {
2812 target: 1,
2813 rule_index: 0,
2814 pred_index: 0,
2815 context_dependent: false,
2816 },
2817 )
2818 .expect("transition");
2819 atn.set_rule_to_start_state(vec![0])
2820 .expect("rule start states");
2821 atn.set_rule_to_stop_state(vec![1])
2822 .expect("rule stop states");
2823 let atn = finish_atn(atn);
2824 let mut simulator = ParserAtnSimulator::new(&atn);
2825 assert!(!simulator.full_context_memo_allowed());
2826 }
2827
2828 #[test]
2829 fn full_context_memo_allows_action_and_precedence_transitions() {
2830 let mut atn = ParserAtnBuilder::new(1);
2836 add_state(&mut atn, 0, AtnStateKind::Basic);
2837 add_state(&mut atn, 1, AtnStateKind::Basic);
2838 add_state(&mut atn, 2, AtnStateKind::Basic);
2839 atn.add_transition(
2840 0,
2841 ParserTransitionSpec::Action {
2842 target: 1,
2843 rule_index: 0,
2844 action_index: Some(0),
2845 context_dependent: false,
2846 },
2847 )
2848 .expect("transition");
2849 atn.add_transition(
2850 1,
2851 ParserTransitionSpec::Precedence {
2852 target: 2,
2853 precedence: 1,
2854 },
2855 )
2856 .expect("transition");
2857 atn.set_rule_to_start_state(vec![0])
2858 .expect("rule start states");
2859 atn.set_rule_to_stop_state(vec![2])
2860 .expect("rule stop states");
2861 let atn = finish_atn(atn);
2862 let mut simulator = ParserAtnSimulator::new(&atn);
2863 assert!(simulator.full_context_memo_allowed());
2864 }
2865
2866 #[test]
2867 fn context_prediction_reports_context_sensitivity_for_dfa_conflict() {
2868 let atn = two_token_decision_atn();
2869 let mut simulator = ParserAtnSimulator::new(&atn);
2870 let mut workspace = PredictionWorkspace::default();
2871 let mut start_configs = AtnConfigSet::new();
2872 start_configs.add(
2873 AtnConfig::new(2, 1, EMPTY_CONTEXT, &simulator.store.contexts),
2874 &mut simulator.store.contexts,
2875 &mut workspace,
2876 );
2877 let start =
2878 simulator.store.decision_to_dfa[0].add_state(DfaStateBuilder::new(start_configs));
2879 simulator.store.decision_to_dfa[0].set_start_state(start);
2880
2881 let mut accept_configs = AtnConfigSet::new();
2882 accept_configs.add(
2883 AtnConfig::new(3, 1, EMPTY_CONTEXT, &simulator.store.contexts).with_semantic_context(
2884 SemanticContext::Predicate {
2885 rule_index: 0,
2886 pred_index: 0,
2887 context_dependent: false,
2888 },
2889 ),
2890 &mut simulator.store.contexts,
2891 &mut workspace,
2892 );
2893 let mut accept_state = DfaStateBuilder::new(accept_configs);
2894 accept_state.mark_accept(1);
2895 accept_state.set_requires_full_context(true);
2896 accept_state.set_conflicting_alts(vec![1, 2]);
2897 let accept = simulator.store.decision_to_dfa[0].add_state(accept_state);
2898 simulator.store.decision_to_dfa[0].add_edge(start, 1, accept);
2899
2900 let mut input = VecIntStream::new(vec![1, 3, TOKEN_EOF]);
2901 let prediction = simulator
2902 .adaptive_predict_stream_info_with_context(0, 0, &mut input, EMPTY_CONTEXT)
2903 .expect("prediction");
2904
2905 insta::assert_debug_snapshot!(
2906 "context_prediction_reports_context_sensitivity_for_dfa_conflict",
2907 prediction
2908 );
2909 assert_eq!(input.index(), 0);
2910 }
2911
2912 #[test]
2913 fn full_context_reach_prefers_longer_match_over_skipped_stop_state() {
2914 let atn = prefix_alt_decision_atn();
2915 let mut simulator = ParserAtnSimulator::new(&atn);
2916 let mut configs = AtnConfigSet::new_full_context(true);
2917 let mut merge_cache = PredictionWorkspace::default();
2918 configs.add(
2919 AtnConfig::new(2, 1, EMPTY_CONTEXT, &simulator.store.contexts),
2920 &mut simulator.store.contexts,
2921 &mut merge_cache,
2922 );
2923 configs.add(
2924 AtnConfig::new(1, 2, EMPTY_CONTEXT, &simulator.store.contexts),
2925 &mut simulator.store.contexts,
2926 &mut merge_cache,
2927 );
2928
2929 let reach = simulator.compute_reach_set(&configs, 2, true, 0, &mut merge_cache);
2930
2931 assert_eq!(reach.alts(), std::iter::once(2).collect());
2932 assert!(simulator.configs_all_reached_rule_stop(&reach));
2933 }
2934
2935 #[test]
2936 fn sll_closure_follows_empty_context_rule_stop_exits() {
2937 let mut atn = ParserAtnBuilder::new(1);
2938 add_state(&mut atn, 0, AtnStateKind::RuleStop);
2939 add_state(&mut atn, 1, AtnStateKind::Basic);
2940 add_state(&mut atn, 2, AtnStateKind::Basic);
2941 atn.add_transition(0, ParserTransitionSpec::Epsilon { target: 1 })
2942 .expect("transition");
2943 atn.add_transition(
2944 1,
2945 ParserTransitionSpec::Atom {
2946 target: 2,
2947 label: 1,
2948 },
2949 )
2950 .expect("transition");
2951 atn.set_rule_to_start_state(vec![0])
2952 .expect("rule start states");
2953 atn.set_rule_to_stop_state(vec![0])
2954 .expect("rule stop states");
2955 let atn = finish_atn(atn);
2956
2957 let mut simulator = ParserAtnSimulator::new(&atn);
2958 let mut configs = AtnConfigSet::new_full_context(false);
2959 let mut merge_cache = PredictionWorkspace::default();
2960 let mut scratch = ClosureScratch::default();
2961 let config = AtnConfig::new(0, 2, EMPTY_CONTEXT, &simulator.store.contexts);
2962 simulator.closure(
2963 config,
2964 &mut configs,
2965 &mut merge_cache,
2966 &mut scratch,
2967 ClosureParams {
2968 precedence: 0,
2969 collect_predicates: true,
2970 treat_eof_as_epsilon: false,
2971 },
2972 );
2973
2974 assert_eq!(configs.len(), 1);
2975 let config = &configs.configs()[0];
2976 assert_eq!(config.state, 1);
2977 assert_eq!(config.alt, 2);
2978 assert_eq!(config.reaches_into_outer_context, 1);
2979 }
2980
2981 #[test]
2982 fn precedence_contexts_are_collected_only_for_start_closure() {
2983 let mut atn = ParserAtnBuilder::new(1);
2984 add_state(&mut atn, 0, AtnStateKind::Basic);
2985 add_state(&mut atn, 1, AtnStateKind::Basic);
2986 atn.set_rule_to_start_state(vec![0])
2987 .expect("rule start states");
2988 atn.set_rule_to_stop_state(vec![1])
2989 .expect("rule stop states");
2990 atn.add_transition(
2991 0,
2992 ParserTransitionSpec::Precedence {
2993 target: 1,
2994 precedence: 2,
2995 },
2996 )
2997 .expect("precedence transition");
2998 let atn = finish_atn(atn);
2999 let transition = atn
3000 .state(0)
3001 .expect("source state")
3002 .transitions()
3003 .first()
3004 .expect("precedence transition");
3005 let mut simulator = ParserAtnSimulator::new(&atn);
3006 let config = AtnConfig::new(0, 1, EMPTY_CONTEXT, &simulator.store.contexts);
3007
3008 let sll_start = simulator
3009 .epsilon_target_config(&config, transition, transition.kind(), 1, true, false)
3010 .expect("sll start transition");
3011 assert!(matches!(
3012 sll_start.semantic_context,
3013 SemanticContext::Precedence { precedence: 2 }
3014 ));
3015
3016 let full_context_start = simulator
3017 .epsilon_target_config(&config, transition, transition.kind(), 1, true, true)
3018 .expect("full-context start transition");
3019 assert!(full_context_start.semantic_context.is_none());
3020
3021 let reach = simulator
3022 .epsilon_target_config(&config, transition, transition.kind(), 3, false, false)
3023 .expect("reach transition");
3024 assert!(reach.semantic_context.is_none());
3025
3026 assert!(
3027 simulator
3028 .epsilon_target_config(&config, transition, transition.kind(), 3, true, false)
3029 .is_none()
3030 );
3031 }
3032
3033 #[test]
3034 fn closure_stops_collecting_predicates_after_action_edge() {
3035 let mut atn = ParserAtnBuilder::new(1);
3042 add_state(&mut atn, 0, AtnStateKind::Basic);
3043 add_state(&mut atn, 1, AtnStateKind::Basic);
3044 add_state(&mut atn, 2, AtnStateKind::Basic);
3045 add_state(&mut atn, 3, AtnStateKind::Basic);
3046 atn.add_transition(
3047 0,
3048 ParserTransitionSpec::Action {
3049 target: 1,
3050 rule_index: 0,
3051 action_index: Some(0),
3052 context_dependent: false,
3053 },
3054 )
3055 .expect("transition");
3056 atn.add_transition(
3057 1,
3058 ParserTransitionSpec::Predicate {
3059 target: 2,
3060 rule_index: 0,
3061 pred_index: 0,
3062 context_dependent: false,
3063 },
3064 )
3065 .expect("transition");
3066 atn.add_transition(
3067 2,
3068 ParserTransitionSpec::Atom {
3069 target: 3,
3070 label: 1,
3071 },
3072 )
3073 .expect("transition");
3074 atn.set_rule_to_start_state(vec![0])
3075 .expect("rule start states");
3076 atn.set_rule_to_stop_state(vec![3])
3077 .expect("rule stop states");
3078 let atn = finish_atn(atn);
3079
3080 let mut simulator = ParserAtnSimulator::new(&atn);
3081 let mut configs = AtnConfigSet::new();
3082 let mut merge_cache = PredictionWorkspace::default();
3083 let mut scratch = ClosureScratch::default();
3084 let config = AtnConfig::new(0, 1, EMPTY_CONTEXT, &simulator.store.contexts);
3085 simulator.closure(
3086 config,
3087 &mut configs,
3088 &mut merge_cache,
3089 &mut scratch,
3090 ClosureParams {
3091 precedence: 0,
3092 collect_predicates: true,
3093 treat_eof_as_epsilon: false,
3094 },
3095 );
3096
3097 let at_two = configs
3100 .configs()
3101 .iter()
3102 .find(|config| config.state == 2)
3103 .expect("config at state 2");
3104 assert!(
3105 at_two.semantic_context.is_none(),
3106 "predicate after an action edge must not be collected during prediction"
3107 );
3108
3109 let direct_config = AtnConfig::new(1, 1, EMPTY_CONTEXT, &simulator.store.contexts);
3113 let direct_transition = atn
3114 .state(1)
3115 .expect("predicate source")
3116 .transitions()
3117 .first()
3118 .expect("predicate transition");
3119 let direct = simulator
3120 .epsilon_target_config(
3121 &direct_config,
3122 direct_transition,
3123 direct_transition.kind(),
3124 0,
3125 true,
3126 false,
3127 )
3128 .expect("predicate transition");
3129 assert!(matches!(
3130 direct.semantic_context,
3131 SemanticContext::Predicate { pred_index: 0, .. }
3132 ));
3133 }
3134
3135 #[test]
3136 fn reach_set_skips_closure_for_unique_intermediate_alt() {
3137 let mut atn = ParserAtnBuilder::new(1);
3138 add_state(&mut atn, 0, AtnStateKind::Basic);
3139 add_state(&mut atn, 1, AtnStateKind::Basic);
3140 add_state(&mut atn, 2, AtnStateKind::Basic);
3141 atn.add_transition(
3142 0,
3143 ParserTransitionSpec::Atom {
3144 target: 1,
3145 label: 7,
3146 },
3147 )
3148 .expect("transition");
3149 atn.add_transition(1, ParserTransitionSpec::Epsilon { target: 2 })
3150 .expect("transition");
3151 atn.set_rule_to_start_state(vec![0])
3152 .expect("rule start states");
3153 atn.set_rule_to_stop_state(vec![2])
3154 .expect("rule stop states");
3155 let atn = finish_atn(atn);
3156
3157 let mut simulator = ParserAtnSimulator::new(&atn);
3158 let mut configs = AtnConfigSet::new_full_context(false);
3159 let mut merge_cache = PredictionWorkspace::default();
3160 configs.add(
3161 AtnConfig::new(0, 1, EMPTY_CONTEXT, &simulator.store.contexts),
3162 &mut simulator.store.contexts,
3163 &mut merge_cache,
3164 );
3165
3166 let reach = simulator.compute_reach_set(&configs, 7, false, 0, &mut merge_cache);
3167
3168 assert_eq!(reach.len(), 1);
3169 assert_eq!(reach.configs()[0].state, 1);
3170 }
3171
3172 #[test]
3173 fn semantic_context_flag_is_scoped_to_predicted_alt() {
3174 let mut arena = ContextArena::new();
3175 let mut workspace = PredictionWorkspace::default();
3176 let mut configs = AtnConfigSet::new();
3177 configs.add(
3178 AtnConfig::new(1, 1, EMPTY_CONTEXT, &arena),
3179 &mut arena,
3180 &mut workspace,
3181 );
3182 configs.add(
3183 AtnConfig::new(2, 2, EMPTY_CONTEXT, &arena).with_semantic_context(
3184 SemanticContext::Predicate {
3185 rule_index: 0,
3186 pred_index: 0,
3187 context_dependent: false,
3188 },
3189 ),
3190 &mut arena,
3191 &mut workspace,
3192 );
3193
3194 assert!(!configs_have_semantic_context_for_alt(&configs, 1));
3195 assert!(configs_have_semantic_context_for_alt(&configs, 2));
3196 }
3197
3198 #[test]
3199 fn adaptive_predict_prefers_non_greedy_exit_before_consuming() {
3200 let atn = non_greedy_optional_exit_first_atn();
3201 let mut simulator = ParserAtnSimulator::new(&atn);
3202
3203 assert_eq!(simulator.adaptive_predict(0, [1, TOKEN_EOF]), Ok(1));
3204 }
3205
3206 #[test]
3207 fn left_recursive_loop_entry_drop_requires_same_rule_return() {
3208 let atn = left_recursive_loop_entry_atn();
3209 let loop_entry = atn.state(1).expect("loop entry");
3210 let mut contexts = ContextArena::new();
3211 let same_rule_context = contexts.singleton(EMPTY_CONTEXT, 4);
3212 let other_rule_context = contexts.singleton(EMPTY_CONTEXT, 5);
3213
3214 assert!(can_drop_left_recursive_loop_entry_edge(
3215 &atn,
3216 loop_entry,
3217 &contexts,
3218 same_rule_context
3219 ));
3220 assert!(!can_drop_left_recursive_loop_entry_edge(
3221 &atn,
3222 loop_entry,
3223 &contexts,
3224 other_rule_context
3225 ));
3226 assert!(!can_drop_left_recursive_loop_entry_edge(
3227 &atn,
3228 loop_entry,
3229 &contexts,
3230 EMPTY_CONTEXT
3231 ));
3232 }
3233
3234 fn two_token_decision_atn() -> Atn {
3235 two_token_decision_atn_with_precedence(false)
3236 }
3237
3238 fn two_independent_decisions_atn() -> Atn {
3239 let mut atn = ParserAtnBuilder::new(3);
3240 add_two_token_decision_rule(&mut atn, 0, 0);
3241 add_two_token_decision_rule(&mut atn, 8, 1);
3242 atn.set_rule_to_start_state(vec![0, 8])
3243 .expect("rule start states");
3244 atn.set_rule_to_stop_state(vec![7, 15])
3245 .expect("rule stop states");
3246 finish_atn(atn)
3247 }
3248
3249 fn two_token_decision_atn_with_precedence(precedence: bool) -> Atn {
3250 let mut atn = ParserAtnBuilder::new(3);
3251 add_two_token_decision_rule(&mut atn, 0, 0);
3252 atn.set_rule_to_start_state(vec![0])
3253 .expect("rule start states");
3254 atn.set_rule_to_stop_state(vec![7])
3255 .expect("rule stop states");
3256 if precedence {
3257 atn.set_precedence_rule_decision(1)
3258 .expect("precedence decision state");
3259 }
3260 finish_atn(atn)
3261 }
3262
3263 fn add_two_token_decision_rule(atn: &mut ParserAtnBuilder, offset: usize, rule_index: usize) {
3264 assert_eq!(atn.state_count(), offset);
3265 for kind in [
3266 AtnStateKind::RuleStart,
3267 AtnStateKind::BlockStart,
3268 AtnStateKind::Basic,
3269 AtnStateKind::Basic,
3270 AtnStateKind::Basic,
3271 AtnStateKind::Basic,
3272 AtnStateKind::BlockEnd,
3273 AtnStateKind::RuleStop,
3274 ] {
3275 let expected = atn.state_count();
3276 assert_eq!(
3277 atn.add_state(kind, Some(rule_index))
3278 .expect("state")
3279 .index(),
3280 expected
3281 );
3282 }
3283 atn.add_decision_state(offset + 1).expect("decision state");
3284 atn.add_transition(offset, ParserTransitionSpec::Epsilon { target: offset + 1 })
3285 .expect("transition");
3286 atn.add_transition(
3287 offset + 1,
3288 ParserTransitionSpec::Epsilon { target: offset + 2 },
3289 )
3290 .expect("transition");
3291 atn.add_transition(
3292 offset + 1,
3293 ParserTransitionSpec::Epsilon { target: offset + 4 },
3294 )
3295 .expect("transition");
3296 atn.add_transition(
3297 offset + 2,
3298 ParserTransitionSpec::Atom {
3299 target: offset + 3,
3300 label: 1,
3301 },
3302 )
3303 .expect("transition");
3304 atn.add_transition(
3305 offset + 3,
3306 ParserTransitionSpec::Atom {
3307 target: offset + 6,
3308 label: 2,
3309 },
3310 )
3311 .expect("transition");
3312 atn.add_transition(
3313 offset + 4,
3314 ParserTransitionSpec::Atom {
3315 target: offset + 5,
3316 label: 1,
3317 },
3318 )
3319 .expect("transition");
3320 atn.add_transition(
3321 offset + 5,
3322 ParserTransitionSpec::Atom {
3323 target: offset + 6,
3324 label: 3,
3325 },
3326 )
3327 .expect("transition");
3328 atn.add_transition(
3329 offset + 6,
3330 ParserTransitionSpec::Epsilon { target: offset + 7 },
3331 )
3332 .expect("transition");
3333 }
3334
3335 fn optional_token_decision_atn() -> Atn {
3336 let mut atn = ParserAtnBuilder::new(1);
3337 add_state(&mut atn, 0, AtnStateKind::RuleStart);
3338 add_state(&mut atn, 1, AtnStateKind::BlockStart);
3339 add_state(&mut atn, 2, AtnStateKind::Basic);
3340 add_state(&mut atn, 3, AtnStateKind::BlockEnd);
3341 add_state(&mut atn, 4, AtnStateKind::RuleStop);
3342 atn.set_rule_to_start_state(vec![0])
3343 .expect("rule start states");
3344 atn.set_rule_to_stop_state(vec![4])
3345 .expect("rule stop states");
3346 atn.add_decision_state(1).expect("decision state");
3347 atn.add_transition(0, ParserTransitionSpec::Epsilon { target: 1 })
3348 .expect("transition");
3349 atn.add_transition(1, ParserTransitionSpec::Epsilon { target: 2 })
3350 .expect("transition");
3351 atn.add_transition(1, ParserTransitionSpec::Epsilon { target: 3 })
3352 .expect("transition");
3353 atn.add_transition(
3354 2,
3355 ParserTransitionSpec::Atom {
3356 target: 3,
3357 label: 1,
3358 },
3359 )
3360 .expect("transition");
3361 atn.add_transition(3, ParserTransitionSpec::Epsilon { target: 4 })
3362 .expect("transition");
3363 finish_atn(atn)
3364 }
3365
3366 fn non_greedy_optional_exit_first_atn() -> Atn {
3367 let mut atn = ParserAtnBuilder::new(1);
3368 add_state(&mut atn, 0, AtnStateKind::RuleStart);
3369 add_state(&mut atn, 1, AtnStateKind::BlockStart);
3370 add_state(&mut atn, 2, AtnStateKind::BlockEnd);
3371 add_state(&mut atn, 3, AtnStateKind::Basic);
3372 add_state(&mut atn, 4, AtnStateKind::RuleStop);
3373 atn.set_rule_to_start_state(vec![0])
3374 .expect("rule start states");
3375 atn.set_rule_to_stop_state(vec![4])
3376 .expect("rule stop states");
3377 atn.add_decision_state(1).expect("decision state");
3378 atn.set_non_greedy(1).expect("non-greedy state");
3379 atn.add_transition(0, ParserTransitionSpec::Epsilon { target: 1 })
3380 .expect("transition");
3381 atn.add_transition(1, ParserTransitionSpec::Epsilon { target: 2 })
3382 .expect("transition");
3383 atn.add_transition(1, ParserTransitionSpec::Epsilon { target: 3 })
3384 .expect("transition");
3385 atn.add_transition(2, ParserTransitionSpec::Epsilon { target: 4 })
3386 .expect("transition");
3387 atn.add_transition(
3388 3,
3389 ParserTransitionSpec::Atom {
3390 target: 4,
3391 label: 1,
3392 },
3393 )
3394 .expect("transition");
3395 finish_atn(atn)
3396 }
3397
3398 fn ambiguous_three_token_decision_atn() -> Atn {
3403 let mut atn = ParserAtnBuilder::new(3);
3404 add_state(&mut atn, 0, AtnStateKind::RuleStart);
3405 add_state(&mut atn, 1, AtnStateKind::BlockStart);
3406 add_state(&mut atn, 2, AtnStateKind::Basic);
3408 add_state(&mut atn, 3, AtnStateKind::Basic);
3409 add_state(&mut atn, 4, AtnStateKind::Basic);
3410 add_state(&mut atn, 5, AtnStateKind::Basic);
3411 add_state(&mut atn, 6, AtnStateKind::Basic);
3413 add_state(&mut atn, 7, AtnStateKind::Basic);
3414 add_state(&mut atn, 8, AtnStateKind::Basic);
3415 add_state(&mut atn, 9, AtnStateKind::Basic);
3416 add_state(&mut atn, 10, AtnStateKind::BlockEnd);
3417 add_state(&mut atn, 11, AtnStateKind::RuleStop);
3418 atn.set_rule_to_start_state(vec![0])
3419 .expect("rule start states");
3420 atn.set_rule_to_stop_state(vec![11])
3421 .expect("rule stop states");
3422 atn.add_decision_state(1).expect("decision state");
3423 atn.add_transition(0, ParserTransitionSpec::Epsilon { target: 1 })
3424 .expect("transition");
3425 atn.add_transition(1, ParserTransitionSpec::Epsilon { target: 2 })
3426 .expect("transition");
3427 atn.add_transition(1, ParserTransitionSpec::Epsilon { target: 6 })
3428 .expect("transition");
3429 for (source, target, label) in [
3430 (2, 3, 1),
3431 (3, 4, 2),
3432 (4, 5, 3),
3433 (6, 7, 1),
3434 (7, 8, 2),
3435 (8, 9, 3),
3436 ] {
3437 atn.add_transition(source, ParserTransitionSpec::Atom { target, label })
3438 .expect("transition");
3439 }
3440 atn.add_transition(5, ParserTransitionSpec::Epsilon { target: 10 })
3441 .expect("transition");
3442 atn.add_transition(9, ParserTransitionSpec::Epsilon { target: 10 })
3443 .expect("transition");
3444 atn.add_transition(10, ParserTransitionSpec::Epsilon { target: 11 })
3445 .expect("transition");
3446 finish_atn(atn)
3447 }
3448
3449 fn ambiguous_single_token_decision_atn() -> Atn {
3450 let mut atn = ParserAtnBuilder::new(1);
3451 add_state(&mut atn, 0, AtnStateKind::RuleStart);
3452 add_state(&mut atn, 1, AtnStateKind::BlockStart);
3453 add_state(&mut atn, 2, AtnStateKind::Basic);
3454 add_state(&mut atn, 3, AtnStateKind::Basic);
3455 add_state(&mut atn, 4, AtnStateKind::Basic);
3456 add_state(&mut atn, 5, AtnStateKind::Basic);
3457 add_state(&mut atn, 6, AtnStateKind::BlockEnd);
3458 add_state(&mut atn, 7, AtnStateKind::RuleStop);
3459 atn.set_rule_to_start_state(vec![0])
3460 .expect("rule start states");
3461 atn.set_rule_to_stop_state(vec![7])
3462 .expect("rule stop states");
3463 atn.add_decision_state(1).expect("decision state");
3464 atn.add_transition(0, ParserTransitionSpec::Epsilon { target: 1 })
3465 .expect("transition");
3466 atn.add_transition(1, ParserTransitionSpec::Epsilon { target: 2 })
3467 .expect("transition");
3468 atn.add_transition(1, ParserTransitionSpec::Epsilon { target: 4 })
3469 .expect("transition");
3470 atn.add_transition(
3471 2,
3472 ParserTransitionSpec::Atom {
3473 target: 3,
3474 label: 1,
3475 },
3476 )
3477 .expect("transition");
3478 atn.add_transition(3, ParserTransitionSpec::Epsilon { target: 6 })
3479 .expect("transition");
3480 atn.add_transition(
3481 4,
3482 ParserTransitionSpec::Atom {
3483 target: 5,
3484 label: 1,
3485 },
3486 )
3487 .expect("transition");
3488 atn.add_transition(5, ParserTransitionSpec::Epsilon { target: 6 })
3489 .expect("transition");
3490 atn.add_transition(6, ParserTransitionSpec::Epsilon { target: 7 })
3491 .expect("transition");
3492 finish_atn(atn)
3493 }
3494
3495 fn prefix_alt_decision_atn() -> Atn {
3496 let mut atn = ParserAtnBuilder::new(3);
3497 add_state(&mut atn, 0, AtnStateKind::BlockStart);
3498 add_state(&mut atn, 1, AtnStateKind::Basic);
3499 add_state(&mut atn, 2, AtnStateKind::RuleStop);
3500 atn.set_rule_to_start_state(vec![0])
3501 .expect("rule start states");
3502 atn.set_rule_to_stop_state(vec![2])
3503 .expect("rule stop states");
3504 atn.add_decision_state(0).expect("decision state");
3505 atn.add_transition(
3506 0,
3507 ParserTransitionSpec::Atom {
3508 target: 2,
3509 label: 1,
3510 },
3511 )
3512 .expect("transition");
3513 atn.add_transition(
3514 0,
3515 ParserTransitionSpec::Atom {
3516 target: 1,
3517 label: 1,
3518 },
3519 )
3520 .expect("transition");
3521 atn.add_transition(
3522 1,
3523 ParserTransitionSpec::Atom {
3524 target: 2,
3525 label: 2,
3526 },
3527 )
3528 .expect("transition");
3529 finish_atn(atn)
3530 }
3531
3532 fn three_token_prefix_alt_decision_atn() -> Atn {
3533 let mut atn = ParserAtnBuilder::new(2);
3534 for (state_number, kind) in [
3535 (0, AtnStateKind::BlockStart),
3536 (1, AtnStateKind::Basic),
3537 (2, AtnStateKind::Basic),
3538 (3, AtnStateKind::Basic),
3539 (4, AtnStateKind::Basic),
3540 (5, AtnStateKind::Basic),
3541 (6, AtnStateKind::RuleStop),
3542 ] {
3543 add_state(&mut atn, state_number, kind);
3544 }
3545 atn.set_rule_to_start_state(vec![0])
3546 .expect("rule start states");
3547 atn.set_rule_to_stop_state(vec![6])
3548 .expect("rule stop states");
3549 atn.add_decision_state(0).expect("decision state");
3550 atn.add_transition(0, ParserTransitionSpec::Epsilon { target: 1 })
3551 .expect("transition");
3552 atn.add_transition(0, ParserTransitionSpec::Epsilon { target: 2 })
3553 .expect("transition");
3554 atn.add_transition(
3555 1,
3556 ParserTransitionSpec::Atom {
3557 target: 6,
3558 label: 1,
3559 },
3560 )
3561 .expect("transition");
3562 atn.add_transition(
3563 2,
3564 ParserTransitionSpec::Atom {
3565 target: 3,
3566 label: 1,
3567 },
3568 )
3569 .expect("transition");
3570 atn.add_transition(
3571 3,
3572 ParserTransitionSpec::Atom {
3573 target: 4,
3574 label: 2,
3575 },
3576 )
3577 .expect("transition");
3578 atn.add_transition(
3579 4,
3580 ParserTransitionSpec::Atom {
3581 target: 5,
3582 label: 1,
3583 },
3584 )
3585 .expect("transition");
3586 atn.add_transition(5, ParserTransitionSpec::Epsilon { target: 6 })
3587 .expect("transition");
3588 finish_atn(atn)
3589 }
3590
3591 fn multiple_eof_decision_atn() -> Atn {
3592 let mut atn = ParserAtnBuilder::new(2);
3593 for state_number in 0..=10 {
3594 let kind = match state_number {
3595 0 => AtnStateKind::RuleStart,
3596 1 => AtnStateKind::BlockStart,
3597 7 => AtnStateKind::BlockEnd,
3598 10 => AtnStateKind::RuleStop,
3599 _ => AtnStateKind::Basic,
3600 };
3601 add_state(&mut atn, state_number, kind);
3602 }
3603 atn.set_rule_to_start_state(vec![0])
3604 .expect("rule start states");
3605 atn.set_rule_to_stop_state(vec![10])
3606 .expect("rule stop states");
3607 atn.add_decision_state(1).expect("decision state");
3608 atn.add_transition(0, ParserTransitionSpec::Epsilon { target: 1 })
3609 .expect("transition");
3610 atn.add_transition(1, ParserTransitionSpec::Epsilon { target: 2 })
3611 .expect("transition");
3612 atn.add_transition(1, ParserTransitionSpec::Epsilon { target: 4 })
3613 .expect("transition");
3614 atn.add_transition(
3615 2,
3616 ParserTransitionSpec::Atom {
3617 target: 3,
3618 label: 1,
3619 },
3620 )
3621 .expect("transition");
3622 atn.add_transition(3, ParserTransitionSpec::Epsilon { target: 7 })
3623 .expect("transition");
3624 atn.add_transition(
3625 4,
3626 ParserTransitionSpec::Atom {
3627 target: 5,
3628 label: 1,
3629 },
3630 )
3631 .expect("transition");
3632 atn.add_transition(
3633 5,
3634 ParserTransitionSpec::Atom {
3635 target: 6,
3636 label: 2,
3637 },
3638 )
3639 .expect("transition");
3640 atn.add_transition(6, ParserTransitionSpec::Epsilon { target: 7 })
3641 .expect("transition");
3642 atn.add_transition(7, ParserTransitionSpec::Epsilon { target: 8 })
3643 .expect("transition");
3644 atn.add_transition(
3645 8,
3646 ParserTransitionSpec::Atom {
3647 target: 9,
3648 label: TOKEN_EOF,
3649 },
3650 )
3651 .expect("transition");
3652 atn.add_transition(
3653 9,
3654 ParserTransitionSpec::Atom {
3655 target: 10,
3656 label: TOKEN_EOF,
3657 },
3658 )
3659 .expect("transition");
3660 finish_atn(atn)
3661 }
3662
3663 fn left_recursive_loop_entry_atn() -> Atn {
3664 let mut atn = ParserAtnBuilder::new(1);
3665 add_state(&mut atn, 0, AtnStateKind::RuleStart);
3666 add_state(&mut atn, 1, AtnStateKind::StarLoopEntry);
3667 add_state(&mut atn, 2, AtnStateKind::BlockStart);
3668 add_state(&mut atn, 3, AtnStateKind::BlockEnd);
3669 add_state(&mut atn, 4, AtnStateKind::Basic);
3670 assert_eq!(
3671 atn.add_state(AtnStateKind::Basic, Some(1))
3672 .expect("state")
3673 .index(),
3674 5
3675 );
3676 add_state(&mut atn, 6, AtnStateKind::LoopEnd);
3677 add_state(&mut atn, 7, AtnStateKind::RuleStop);
3678 atn.set_rule_to_start_state(vec![0, 5])
3679 .expect("rule start states");
3680 atn.set_rule_to_stop_state(vec![7, 7])
3681 .expect("rule stop states");
3682 atn.set_precedence_rule_decision(1)
3683 .expect("precedence decision state");
3684 atn.set_end_state(2, 3).expect("block end state");
3685 atn.add_transition(1, ParserTransitionSpec::Epsilon { target: 2 })
3686 .expect("transition");
3687 atn.add_transition(1, ParserTransitionSpec::Epsilon { target: 6 })
3688 .expect("transition");
3689 atn.add_transition(4, ParserTransitionSpec::Epsilon { target: 3 })
3690 .expect("transition");
3691 atn.add_transition(5, ParserTransitionSpec::Epsilon { target: 3 })
3692 .expect("transition");
3693 finish_atn(atn)
3694 }
3695
3696 fn add_state(atn: &mut ParserAtnBuilder, state_number: usize, kind: AtnStateKind) {
3697 assert_eq!(
3698 atn.add_state(kind, Some(0)).expect("state").index(),
3699 state_number
3700 );
3701 }
3702
3703 #[derive(Debug)]
3704 struct VecIntStream {
3705 symbols: Vec<i32>,
3706 index: usize,
3707 }
3708
3709 impl VecIntStream {
3710 fn new(symbols: Vec<i32>) -> Self {
3711 Self { symbols, index: 0 }
3712 }
3713 }
3714
3715 impl IntStream for VecIntStream {
3716 fn consume(&mut self) {
3717 if self.la(1) != TOKEN_EOF {
3718 self.index += 1;
3719 }
3720 }
3721
3722 fn la(&mut self, offset: isize) -> i32 {
3723 if offset <= 0 {
3724 return 0;
3725 }
3726 let offset = offset.cast_unsigned() - 1;
3727 self.symbols
3728 .get(self.index + offset)
3729 .copied()
3730 .unwrap_or(TOKEN_EOF)
3731 }
3732
3733 fn index(&self) -> usize {
3734 self.index
3735 }
3736
3737 fn seek(&mut self, index: usize) {
3738 self.index = index;
3739 }
3740
3741 fn size(&self) -> usize {
3742 self.symbols.len()
3743 }
3744 }
3745}