1use crate::atn::AtnStateKind;
4use crate::atn::parser_atn::{
5 ParserAtn as Atn, ParserAtnState as AtnState, ParserTransition, ParserTransitionKind,
6};
7#[cfg(test)]
8use crate::atn::parser_atn::{ParserAtnBuilder, ParserTransitionSpec};
9use crate::dfa::{
10 DfaStateBuilder, DfaStateId, NO_DFA_STATE, ParserDfa, ParserDfaStateView, ParserDfaStats,
11};
12use crate::int_stream::IntStream;
13use crate::prediction::{
14 AtnConfig, AtnConfigSet, ContextArena, ContextId, EMPTY_CONTEXT, EMPTY_RETURN_STATE,
15 PredictionContextStats, PredictionFxHasher, PredictionPredicateCall,
16 PredictionSemanticProvenanceArena, PredictionSemanticProvenanceId, PredictionWorkspace,
17 SemanticContext, SemanticContextArena, SemanticContextId, SllConflict, all_subsets_conflict,
18 all_subsets_equal, conflicting_alt_subsets, exact_context_sll_conflict,
19 has_sll_conflict_terminating_prediction, single_viable_alt,
20};
21use crate::token::TOKEN_EOF;
22use std::cell::RefCell;
23use std::collections::{HashMap, HashSet};
24use std::hash::BuildHasherDefault;
25
26type FxHashSet<T> = HashSet<T, BuildHasherDefault<PredictionFxHasher>>;
27
28#[derive(Debug)]
29pub struct ParserAtnSimulator<'a> {
30 atn: &'a Atn,
31 store: PredictionStore,
32 workspace: PredictionWorkspace,
33 outer_context_cache: Option<CachedOuterContext>,
34 outer_context_cache_hits: usize,
35 outer_context_cache_misses: usize,
36 deferred_accept_states: FxHashSet<(usize, DfaStateId)>,
39 shared_cache_key: Option<SharedPredictionKey>,
40 shared_cache_generation: u64,
41 has_trained_decision: bool,
42 measure_adaptive_work: bool,
43 adaptive_calls: usize,
44 adaptive_closure_work: usize,
45 tail_call_preserves_sll: bool,
48 exact_ambig_detection: bool,
52 full_context_memo: HashMap<
63 FullContextMemoKey,
64 Vec<FullContextMemoEntry>,
65 BuildHasherDefault<PredictionFxHasher>,
66 >,
67 full_context_memo_len: usize,
68 full_context_memo_gate: Option<bool>,
72 prediction_semantic_candidates: Vec<CompactParserSemanticCandidate>,
78 track_prediction_rule_calls: bool,
83 semantic_provenance: Option<Box<PredictionSemanticProvenanceArena>>,
84}
85
86#[derive(Clone, Copy, Debug)]
87struct CachedOuterContext {
88 rule_context_version: usize,
89 context: ContextId,
90}
91
92#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
103struct FullContextMemoKey {
104 decision: usize,
105 precedence: i32,
106 outer_context: ContextId,
107 first_symbol: i32,
108}
109
110#[derive(Clone, Debug)]
121struct FullContextMemoEntry {
122 window_tail: Vec<i32>,
123 prediction: FullContextPrediction,
124}
125
126const FULL_CONTEXT_MEMO_MAX_WINDOW: usize = 16;
130const FULL_CONTEXT_MEMO_MAX_ENTRIES: usize = 4096;
134
135fn atn_has_predicate_transition(atn: &Atn) -> bool {
142 thread_local! {
143 static GATES: RefCell<HashMap<usize, bool, BuildHasherDefault<PredictionFxHasher>>> =
144 RefCell::new(HashMap::default());
145 }
146 let ptr: *const Atn = atn;
147 let key = ptr as usize;
148 GATES.with(|gates| {
149 *gates.borrow_mut().entry(key).or_insert_with(|| {
150 (0..atn.state_count()).any(|state_number| {
151 atn.state(state_number).is_some_and(|state| {
152 state
153 .transitions()
154 .into_iter()
155 .any(|transition| transition.kind() == ParserTransitionKind::Predicate)
156 })
157 })
158 })
159 })
160}
161
162#[derive(Debug, Default)]
163struct PredictionStore {
164 contexts: ContextArena,
165 semantic_contexts: SemanticContextArena,
166 decision_to_dfa: Vec<ParserDfa>,
167}
168
169impl PredictionStore {
170 fn new(atn: &Atn) -> Self {
171 Self {
172 contexts: ContextArena::new(),
173 semantic_contexts: SemanticContextArena::new(),
174 decision_to_dfa: initial_decision_dfas(atn),
175 }
176 }
177}
178
179#[derive(Debug, Default)]
180struct SharedPredictionStore {
181 generation: u64,
182 store: Option<PredictionStore>,
183}
184
185#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
186struct SharedPredictionKey {
187 atn: usize,
188 tail_call_preserves_sll: bool,
189}
190
191thread_local! {
192 static SHARED_PREDICTION_STORES: RefCell<HashMap<SharedPredictionKey, SharedPredictionStore>> =
193 RefCell::new(HashMap::new());
194}
195
196fn clear_shared_prediction_store(key: SharedPredictionKey) -> u64 {
197 SHARED_PREDICTION_STORES.with(|cache| {
198 let mut cache = cache.borrow_mut();
199 let shared = cache.entry(key).or_default();
200 shared.generation = shared.generation.wrapping_add(1);
201 shared.store = None;
202 shared.generation
203 })
204}
205
206const ADAPTIVE_ATN_PREFERENCE_MIN_CALLS: usize = 32;
207const ADAPTIVE_ATN_PREFERENCE_MIN_CLOSURE_WORK_PER_CALL: usize = 256;
208const ADAPTIVE_ATN_PREFERENCE_DECISIVE_CLOSURE_WORK_PER_CALL: usize = 512;
209
210const fn adaptive_prediction_has_work_density(
211 calls: usize,
212 closure_work: usize,
213 minimum_closure_work_per_call: usize,
214) -> bool {
215 calls >= ADAPTIVE_ATN_PREFERENCE_MIN_CALLS
216 && closure_work >= calls.saturating_mul(minimum_closure_work_per_call)
217}
218
219#[derive(Clone, Debug, Eq, PartialEq)]
220pub struct ParserAtnPrediction {
221 pub alt: usize,
222 pub requires_full_context: bool,
223 pub has_semantic_context: bool,
224 pub diagnostic: Option<ParserAtnPredictionDiagnostic>,
225}
226
227#[derive(Clone, Debug, Eq, PartialEq)]
228pub struct ParserAtnPredictionDiagnostic {
229 pub kind: ParserAtnPredictionDiagnosticKind,
230 pub start_index: usize,
231 pub sll_stop_index: usize,
232 pub ll_stop_index: usize,
233 pub conflicting_alts: Vec<usize>,
234 pub exact: bool,
238}
239
240#[derive(Clone, Copy, Debug, Eq, PartialEq)]
241pub enum ParserAtnPredictionDiagnosticKind {
242 Ambiguity,
243 ContextSensitivity,
244}
245
246#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
247pub(crate) struct ParserSemanticCandidate {
248 pub(crate) alt: usize,
249 pub(crate) context: SemanticContext,
250 pub(crate) predicate_calls: Vec<PredictionPredicateCall>,
251}
252
253#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
254struct CompactParserSemanticCandidate {
255 alt: usize,
256 context: SemanticContext,
257 semantic_provenance: PredictionSemanticProvenanceId,
258}
259
260#[derive(Clone, Copy)]
261struct PredictionCheck {
262 decision: usize,
263 decision_state: usize,
264 state_number: DfaStateId,
265 start_index: usize,
266 precedence: i32,
267 outer_context: ContextId,
268 force_full_context_retry: bool,
269 sll_probe_only: bool,
270}
271
272#[derive(Clone, Copy)]
273struct AdaptivePredictRequest {
274 decision: usize,
275 precedence: usize,
276 outer_context: ContextId,
277 force_full_context_retry: bool,
278 sll_probe_only: bool,
286}
287
288#[derive(Clone, Copy)]
289struct DfaEdge {
290 decision: usize,
291 source_state: DfaStateId,
292}
293
294#[derive(Clone, Debug)]
295struct PreviousGoodAlt {
296 alt: usize,
297 configs: Vec<AtnConfig>,
298}
299
300#[derive(Clone, Debug, Eq, PartialEq)]
301struct DfaPredictionInfo {
302 prediction: ParserAtnPrediction,
303 conflicting_alts: Vec<usize>,
304 exact_conflict: bool,
305 context_containment_conflict: bool,
306}
307
308#[derive(Clone, Debug, Eq, PartialEq)]
309struct FullContextPrediction {
310 prediction: ParserAtnPrediction,
311 stop_index: usize,
312 resolution: FullContextResolution,
313 semantic_candidates: Vec<CompactParserSemanticCandidate>,
314}
315
316#[derive(Clone, Debug, Eq, PartialEq)]
321enum FullContextResolution {
322 Unique,
323 Ambiguous { exact: bool, alts: Vec<usize> },
324}
325
326fn full_context_prediction(
327 alt: usize,
328 configs: &AtnConfigSet,
329 semantic_contexts: &SemanticContextArena,
330 stop_index: usize,
331 resolution: FullContextResolution,
332) -> FullContextPrediction {
333 FullContextPrediction {
334 prediction: ParserAtnPrediction {
335 alt,
336 requires_full_context: true,
337 has_semantic_context: configs_have_semantic_context_for_alt(configs, alt),
338 diagnostic: None,
339 },
340 stop_index,
341 resolution,
342 semantic_candidates: semantic_prediction_candidates(configs, semantic_contexts),
343 }
344}
345
346fn semantic_prediction_candidates(
347 configs: &AtnConfigSet,
348 semantic_contexts: &SemanticContextArena,
349) -> Vec<CompactParserSemanticCandidate> {
350 if !configs.has_semantic_context() {
351 return Vec::new();
352 }
353 let mut candidates = configs
354 .configs()
355 .iter()
356 .map(|config| CompactParserSemanticCandidate {
357 alt: config.alt,
358 context: config.semantic_context(semantic_contexts).clone(),
359 semantic_provenance: config.semantic_provenance_id(),
360 })
361 .collect::<Vec<_>>();
362 candidates.sort();
363 candidates.dedup();
364 candidates
365}
366
367#[derive(Clone, Debug, Eq, Hash, PartialEq)]
368struct ClosureConfigKey {
369 state: usize,
370 alt: usize,
371 semantic_context: SemanticContextId,
372 context_and_provenance: u64,
373}
374
375impl From<&AtnConfig> for ClosureConfigKey {
376 fn from(config: &AtnConfig) -> Self {
377 Self {
378 state: config.state,
379 alt: config.alt,
380 semantic_context: config.semantic_context_id(),
381 context_and_provenance: u64::from(config.context.compact())
382 | (u64::from(config.semantic_provenance_and_flags()) << 32),
383 }
384 }
385}
386
387#[derive(Default)]
394struct ClosureScratch {
395 stack: Vec<(AtnConfig, bool)>,
402 visited: FxHashSet<ClosureConfigKey>,
403}
404
405#[derive(Clone, Copy)]
408struct ClosureParams {
409 precedence: i32,
410 collect_predicates: bool,
411 treat_eof_as_epsilon: bool,
412}
413
414#[derive(Debug)]
415struct LookaheadIntStream {
416 symbols: Vec<i32>,
417 index: usize,
418}
419
420impl LookaheadIntStream {
421 const fn new(symbols: Vec<i32>) -> Self {
422 Self { symbols, index: 0 }
423 }
424}
425
426impl IntStream for LookaheadIntStream {
427 fn consume(&mut self) {
428 if self.la(1) != TOKEN_EOF {
429 self.index += 1;
430 }
431 }
432
433 fn la(&mut self, offset: isize) -> i32 {
434 if offset <= 0 {
435 return 0;
436 }
437 let offset = offset.cast_unsigned() - 1;
438 self.symbols
439 .get(self.index + offset)
440 .copied()
441 .unwrap_or(TOKEN_EOF)
442 }
443
444 fn index(&self) -> usize {
445 self.index
446 }
447
448 fn seek(&mut self, index: usize) {
449 self.index = index.min(self.symbols.len());
450 }
451
452 fn size(&self) -> usize {
453 self.symbols.len()
454 }
455}
456
457fn initial_decision_dfas(atn: &Atn) -> Vec<ParserDfa> {
458 atn.decision_to_state()
459 .iter()
460 .enumerate()
461 .map(|(decision, state)| {
462 let mut dfa = ParserDfa::with_max_token_type(state, decision, atn.max_token_type());
463 if atn
464 .state(state)
465 .is_some_and(AtnState::precedence_rule_decision)
466 {
467 dfa.set_precedence_dfa(true);
468 }
469 dfa
470 })
471 .collect()
472}
473
474fn union_decision_dfas(shared: &mut Vec<ParserDfa>, local: Vec<ParserDfa>) {
484 if shared.len() != local.len() {
485 *shared = local;
486 return;
487 }
488 for (shared_dfa, local_dfa) in shared.iter_mut().zip(local) {
489 union_decision_dfa(shared_dfa, local_dfa);
490 }
491}
492
493fn union_prediction_stores(
494 shared: &mut PredictionStore,
495 mut local: PredictionStore,
496 workspace: &mut PredictionWorkspace,
497) {
498 let context_remap = shared.contexts.import_all(&local.contexts, workspace);
499 let semantic_context_remap = shared
500 .semantic_contexts
501 .import_all(&local.semantic_contexts);
502 for dfa in &mut local.decision_to_dfa {
503 dfa.remap_store_ids(
504 &context_remap,
505 &semantic_context_remap,
506 &shared.contexts,
507 &shared.semantic_contexts,
508 );
509 }
510 union_decision_dfas(&mut shared.decision_to_dfa, local.decision_to_dfa);
511}
512
513fn union_decision_dfa(shared: &mut ParserDfa, local: ParserDfa) {
514 if shared.is_precedence_dfa() != local.is_precedence_dfa() {
515 if local.state_count() > shared.state_count() {
518 *shared = local;
519 }
520 return;
521 }
522 let mut renumber = Vec::with_capacity(local.state_count());
527 for state in local.states() {
528 let configs = local.configs(state.id());
529 let number = shared.state_id_for_configs(configs).unwrap_or_else(|| {
530 let missing = local.clone_state_without_edges(state.id());
531 shared.insert_state(missing)
532 });
533 renumber.push(number);
534 }
535 for state in local.states() {
540 let mapped = renumber[state.id().index()];
541 for transition in state.transitions() {
542 let Some(&mapped_target) = renumber.get(transition.target.index()) else {
543 continue;
544 };
545 if shared.edge(mapped, transition.symbol).is_none() {
546 shared.add_edge(mapped, transition.symbol, mapped_target);
547 }
548 }
549 }
550 if shared.start_state().is_none()
551 && let Some(start) = local.start_state()
552 && let Some(&mapped) = renumber.get(start.index())
553 {
554 shared.set_start_state(mapped);
555 }
556 for (precedence, start) in local.precedence_start_states().iter().copied().enumerate() {
557 if start == NO_DFA_STATE {
558 continue;
559 }
560 if shared.precedence_start_state(precedence).is_none()
561 && let Some(&mapped) = renumber.get(start.index())
562 {
563 shared.set_precedence_start_state(precedence, mapped);
564 }
565 }
566}
567
568impl Drop for ParserAtnSimulator<'_> {
569 fn drop(&mut self) {
570 let Some(key) = self.shared_cache_key else {
571 return;
572 };
573 #[cfg(feature = "perf-counters")]
574 let publication_started = std::time::Instant::now();
575 #[cfg(feature = "perf-counters")]
576 let published_states = self
577 .store
578 .decision_to_dfa
579 .iter()
580 .map(ParserDfa::state_count)
581 .sum();
582 let store = std::mem::take(&mut self.store);
588 let published = SHARED_PREDICTION_STORES.with(|cache| {
589 let mut cache = cache.borrow_mut();
590 let shared = cache.entry(key).or_default();
591 if shared.generation != self.shared_cache_generation {
592 return false;
593 }
594 if let Some(shared_store) = shared.store.as_mut() {
595 union_prediction_stores(shared_store, store, &mut self.workspace);
596 } else {
597 shared.store = Some(store);
598 }
599 true
600 });
601 #[cfg(feature = "perf-counters")]
602 if published {
603 crate::perf::record_dfa_cache_publication(
604 publication_started.elapsed().as_nanos(),
605 published_states,
606 );
607 }
608 #[cfg(not(feature = "perf-counters"))]
609 let _ = published;
610 }
611}
612
613impl<'a> ParserAtnSimulator<'a> {
614 pub fn new(atn: &'a Atn) -> Self {
615 Self::new_with_tail_call_preserves_sll(atn, true)
616 }
617
618 pub fn new_with_tail_call_preserves_sll(atn: &'a Atn, tail_call_preserves_sll: bool) -> Self {
624 Self {
625 atn,
626 store: PredictionStore::new(atn),
627 workspace: PredictionWorkspace::default(),
628 outer_context_cache: None,
629 outer_context_cache_hits: 0,
630 outer_context_cache_misses: 0,
631 deferred_accept_states: FxHashSet::default(),
632 shared_cache_key: None,
633 shared_cache_generation: 0,
634 has_trained_decision: false,
635 measure_adaptive_work: false,
636 adaptive_calls: 0,
637 adaptive_closure_work: 0,
638 tail_call_preserves_sll,
639 exact_ambig_detection: false,
640 full_context_memo: HashMap::default(),
641 full_context_memo_len: 0,
642 full_context_memo_gate: None,
643 prediction_semantic_candidates: Vec::new(),
644 track_prediction_rule_calls: false,
645 semantic_provenance: None,
646 }
647 }
648
649 pub fn reset(&mut self) {
651 self.measure_adaptive_work = false;
652 self.adaptive_calls = 0;
653 self.adaptive_closure_work = 0;
654 self.outer_context_cache = None;
655 self.deferred_accept_states.clear();
656 self.prediction_semantic_candidates.clear();
657 self.workspace.reset();
658 }
659
660 pub fn clear_dfa(&mut self) {
665 self.store = PredictionStore::new(self.atn);
666 if let Some(semantic_provenance) = self.semantic_provenance.as_mut() {
667 **semantic_provenance = PredictionSemanticProvenanceArena::default();
668 }
669 self.full_context_memo.clear();
672 self.full_context_memo_len = 0;
673 self.reset();
674 self.has_trained_decision = false;
675 if let Some(key) = self.shared_cache_key {
676 self.shared_cache_generation = clear_shared_prediction_store(key);
677 }
678 }
679
680 pub fn clear_shared_dfa(atn: &'static Atn) {
682 let ptr: *const Atn = atn;
683 for tail_call_preserves_sll in [true, false] {
684 clear_shared_prediction_store(SharedPredictionKey {
685 atn: ptr as usize,
686 tail_call_preserves_sll,
687 });
688 }
689 }
690
691 pub const fn set_exact_ambig_detection(&mut self, exact: bool) {
694 self.exact_ambig_detection = exact;
695 }
696
697 pub fn dump_dfa_java_style(&self, vocabulary: &crate::vocabulary::Vocabulary) -> String {
715 use std::fmt::Write as _;
716 let mut out = String::new();
717 let mut seen_one = false;
718 for dfa in &self.store.decision_to_dfa {
719 if dfa.is_empty() {
720 continue;
721 }
722 if seen_one {
723 out.push('\n');
724 }
725 seen_one = true;
726 let _ = writeln!(out, "Decision {}:", dfa.decision());
727 for state in dfa.states() {
728 let source = dfa_state_display(
729 state,
730 self.deferred_accept_states
731 .contains(&(dfa.decision(), state.id())),
732 );
733 for transition in state.transitions() {
734 let Some(target_state) = dfa.state(transition.target) else {
735 continue;
736 };
737 let label = vocabulary.display_name(transition.symbol);
738 let target = dfa_state_display(
739 target_state,
740 self.deferred_accept_states
741 .contains(&(dfa.decision(), target_state.id())),
742 );
743 let _ = writeln!(out, "{source}-{label}->{target}");
744 }
745 }
746 }
747 out
748 }
749
750 pub fn new_shared(atn: &'static Atn) -> Self {
751 Self::new_shared_with_tail_call_preserves_sll(atn, true)
752 }
753
754 pub fn new_shared_with_tail_call_preserves_sll(
758 atn: &'static Atn,
759 tail_call_preserves_sll: bool,
760 ) -> Self {
761 let ptr: *const Atn = atn;
762 let key = SharedPredictionKey {
763 atn: ptr as usize,
764 tail_call_preserves_sll,
765 };
766 #[cfg(feature = "perf-counters")]
767 let import_started = std::time::Instant::now();
768 let (store, generation) = SHARED_PREDICTION_STORES.with(|cache| {
769 let mut cache = cache.borrow_mut();
770 let shared = cache.entry(key).or_default();
771 (
772 shared
773 .store
774 .take()
775 .unwrap_or_else(|| PredictionStore::new(atn)),
776 shared.generation,
777 )
778 });
779 let has_trained_decision = store.decision_to_dfa.iter().any(|dfa| !dfa.is_empty());
780 #[cfg(feature = "perf-counters")]
781 crate::perf::record_dfa_cache_import(
782 import_started.elapsed().as_nanos(),
783 store
784 .decision_to_dfa
785 .iter()
786 .map(ParserDfa::state_count)
787 .sum(),
788 );
789 Self {
790 atn,
791 store,
792 workspace: PredictionWorkspace::default(),
793 outer_context_cache: None,
794 outer_context_cache_hits: 0,
795 outer_context_cache_misses: 0,
796 deferred_accept_states: FxHashSet::default(),
797 shared_cache_key: Some(key),
798 shared_cache_generation: generation,
799 has_trained_decision,
800 measure_adaptive_work: false,
801 adaptive_calls: 0,
802 adaptive_closure_work: 0,
803 tail_call_preserves_sll,
804 exact_ambig_detection: false,
805 full_context_memo: HashMap::default(),
806 full_context_memo_len: 0,
807 full_context_memo_gate: None,
808 prediction_semantic_candidates: Vec::new(),
809 track_prediction_rule_calls: false,
810 semantic_provenance: None,
811 }
812 }
813
814 pub fn decision_dfas(&self) -> &[ParserDfa] {
815 &self.store.decision_to_dfa
816 }
817
818 pub(crate) fn prediction_semantic_candidates(&self) -> Vec<ParserSemanticCandidate> {
819 self.prediction_semantic_candidates
820 .iter()
821 .map(|candidate| ParserSemanticCandidate {
822 alt: candidate.alt,
823 context: candidate.context.clone(),
824 predicate_calls: self.semantic_provenance.as_deref().map_or_else(
825 Vec::new,
826 |arena| {
827 arena
828 .predicate_calls(candidate.semantic_provenance)
829 .to_vec()
830 },
831 ),
832 })
833 .collect()
834 }
835
836 pub(crate) fn set_track_prediction_rule_calls(&mut self, track: bool) {
837 assert!(
838 self.shared_cache_key.is_none(),
839 "shared prediction simulators use a fixed untracked rule-call mode"
840 );
841 if self.track_prediction_rule_calls != track {
842 assert!(
843 !self.has_trained_decision,
844 "prediction rule-call tracking mode cannot change after DFA construction"
845 );
846 }
847 self.track_prediction_rule_calls = track;
848 if track {
849 self.semantic_provenance
850 .get_or_insert_with(|| Box::new(PredictionSemanticProvenanceArena::default()));
851 } else {
852 self.semantic_provenance = None;
853 }
854 }
855
856 #[doc(hidden)]
862 pub const fn adaptive_prediction_work(&self) -> Option<(usize, usize)> {
863 if self.has_trained_decision {
864 Some((self.adaptive_calls, self.adaptive_closure_work))
865 } else {
866 None
867 }
868 }
869
870 #[doc(hidden)]
873 pub const fn adaptive_prediction_delta_is_expensive(
874 before: (usize, usize),
875 after: (usize, usize),
876 ) -> bool {
877 adaptive_prediction_has_work_density(
878 after.0.saturating_sub(before.0),
879 after.1.saturating_sub(before.1),
880 ADAPTIVE_ATN_PREFERENCE_MIN_CLOSURE_WORK_PER_CALL,
881 )
882 }
883
884 #[doc(hidden)]
888 pub const fn adaptive_prediction_delta_is_decisive(
889 before: (usize, usize),
890 after: (usize, usize),
891 ) -> bool {
892 adaptive_prediction_has_work_density(
893 after.0.saturating_sub(before.0),
894 after.1.saturating_sub(before.1),
895 ADAPTIVE_ATN_PREFERENCE_DECISIVE_CLOSURE_WORK_PER_CALL,
896 )
897 }
898
899 pub fn parser_dfa_stats(&self) -> ParserDfaStats {
901 let mut stats = ParserDfaStats::default();
902 for dfa in &self.store.decision_to_dfa {
903 stats.add_assign(dfa.stats());
904 }
905 stats.semantic_contexts = self.store.semantic_contexts.len();
906 stats.semantic_context_bytes = self.store.semantic_contexts.retained_bytes();
907 if let Some(provenance) = self.semantic_provenance.as_deref() {
908 stats.semantic_provenance_records = provenance.len();
909 stats.semantic_provenance_bytes = provenance.retained_bytes();
910 }
911 stats.cold_bytes = stats
912 .cold_bytes
913 .saturating_add(stats.semantic_context_bytes)
914 .saturating_add(stats.semantic_provenance_bytes);
915 stats
916 }
917
918 pub fn prediction_context_stats(&self) -> PredictionContextStats {
921 let mut stats = self.store.contexts.stats();
922 stats.retained_bytes += self.workspace.retained_bytes();
923 stats.workspace_merge_cache_entries = self.workspace.merge_cache_len();
924 stats.workspace_merge_cache_capacity = self.workspace.merge_cache_capacity();
925 stats.workspace_entry_capacity = self.workspace.entry_capacity();
926 stats.outer_context_cache_hits = self.outer_context_cache_hits;
927 stats.outer_context_cache_misses = self.outer_context_cache_misses;
928 stats
929 }
930
931 pub fn intern_prediction_context(
935 &mut self,
936 rule_context_version: usize,
937 return_states: impl IntoIterator<Item = usize>,
938 ) -> ContextId {
939 if let Some(cached) = self.outer_context_cache
940 && cached.rule_context_version == rule_context_version
941 {
942 self.outer_context_cache_hits = self.outer_context_cache_hits.saturating_add(1);
943 return cached.context;
944 }
945 self.outer_context_cache_misses = self.outer_context_cache_misses.saturating_add(1);
946 let mut context = EMPTY_CONTEXT;
947 for return_state in return_states {
948 context = self.store.contexts.singleton(context, return_state);
949 }
950 self.outer_context_cache = Some(CachedOuterContext {
951 rule_context_version,
952 context,
953 });
954 context
955 }
956
957 pub fn adaptive_predict(
958 &mut self,
959 decision: usize,
960 lookahead: impl IntoIterator<Item = i32>,
961 ) -> Result<usize, ParserAtnSimulatorError> {
962 self.adaptive_predict_with_precedence(decision, 0, lookahead)
963 }
964
965 pub fn adaptive_predict_stream<T: IntStream>(
966 &mut self,
967 decision: usize,
968 input: &mut T,
969 ) -> Result<usize, ParserAtnSimulatorError> {
970 self.adaptive_predict_stream_with_precedence(decision, 0, input)
971 }
972
973 pub fn adaptive_predict_stream_with_precedence<T: IntStream>(
974 &mut self,
975 decision: usize,
976 precedence: usize,
977 input: &mut T,
978 ) -> Result<usize, ParserAtnSimulatorError> {
979 self.adaptive_predict_stream_info_with_precedence(decision, precedence, input)
980 .map(|prediction| prediction.alt)
981 }
982
983 pub fn adaptive_predict_stream_info_with_precedence<T: IntStream>(
984 &mut self,
985 decision: usize,
986 precedence: usize,
987 input: &mut T,
988 ) -> Result<ParserAtnPrediction, ParserAtnSimulatorError> {
989 let marker = input.mark();
990 let index = input.index();
991 let mut workspace = std::mem::take(&mut self.workspace);
992 workspace.reset();
993 let result = self.adaptive_predict_stream_inner(
994 AdaptivePredictRequest {
995 decision,
996 precedence,
997 outer_context: EMPTY_CONTEXT,
998 force_full_context_retry: false,
999 sll_probe_only: false,
1000 },
1001 input,
1002 &mut workspace,
1003 );
1004 self.workspace = workspace;
1005 input.seek(index);
1006 input.release(marker);
1007 result
1008 }
1009
1010 pub fn adaptive_predict_stream_info_sll_probe<T: IntStream>(
1020 &mut self,
1021 decision: usize,
1022 precedence: usize,
1023 input: &mut T,
1024 ) -> Result<ParserAtnPrediction, ParserAtnSimulatorError> {
1025 let marker = input.mark();
1026 let index = input.index();
1027 let mut workspace = std::mem::take(&mut self.workspace);
1028 workspace.reset();
1029 let result = self.adaptive_predict_stream_inner(
1030 AdaptivePredictRequest {
1031 decision,
1032 precedence,
1033 outer_context: EMPTY_CONTEXT,
1034 force_full_context_retry: false,
1035 sll_probe_only: true,
1036 },
1037 input,
1038 &mut workspace,
1039 );
1040 self.workspace = workspace;
1041 input.seek(index);
1042 input.release(marker);
1043 result
1044 }
1045
1046 pub fn adaptive_predict_stream_info_with_context<T: IntStream>(
1047 &mut self,
1048 decision: usize,
1049 precedence: usize,
1050 input: &mut T,
1051 outer_context: ContextId,
1052 ) -> Result<ParserAtnPrediction, ParserAtnSimulatorError> {
1053 self.store.contexts.assert_valid(outer_context);
1054 let marker = input.mark();
1055 let index = input.index();
1056 let mut workspace = std::mem::take(&mut self.workspace);
1057 workspace.reset();
1058 let result = self.adaptive_predict_stream_inner(
1059 AdaptivePredictRequest {
1060 decision,
1061 precedence,
1062 outer_context,
1063 force_full_context_retry: true,
1064 sll_probe_only: false,
1065 },
1066 input,
1067 &mut workspace,
1068 );
1069 self.workspace = workspace;
1070 input.seek(index);
1071 input.release(marker);
1072 result
1073 }
1074
1075 pub fn adaptive_predict_with_precedence(
1076 &mut self,
1077 decision: usize,
1078 precedence: usize,
1079 lookahead: impl IntoIterator<Item = i32>,
1080 ) -> Result<usize, ParserAtnSimulatorError> {
1081 self.adaptive_predict_info_with_precedence(decision, precedence, lookahead)
1082 .map(|prediction| prediction.alt)
1083 }
1084
1085 pub fn adaptive_predict_info_with_precedence(
1086 &mut self,
1087 decision: usize,
1088 precedence: usize,
1089 lookahead: impl IntoIterator<Item = i32>,
1090 ) -> Result<ParserAtnPrediction, ParserAtnSimulatorError> {
1091 let mut input = LookaheadIntStream::new(lookahead.into_iter().collect());
1092 self.adaptive_predict_stream_info_with_precedence(decision, precedence, &mut input)
1093 }
1094
1095 fn adaptive_predict_stream_inner<T: IntStream>(
1096 &mut self,
1097 request: AdaptivePredictRequest,
1098 input: &mut T,
1099 merge_cache: &mut PredictionWorkspace,
1100 ) -> Result<ParserAtnPrediction, ParserAtnSimulatorError> {
1101 self.prediction_semantic_candidates.clear();
1102 let decision = request.decision;
1103 let learning_revision = self
1104 .store
1105 .decision_to_dfa
1106 .get(decision)
1107 .filter(|dfa| !dfa.is_empty())
1108 .map(ParserDfa::learning_revision);
1109 let work_start = (self.adaptive_calls, self.adaptive_closure_work);
1110 self.measure_adaptive_work = learning_revision.is_some();
1111 if self.measure_adaptive_work {
1112 self.adaptive_calls = self.adaptive_calls.saturating_add(1);
1113 }
1114 let result = self.adaptive_predict_stream_inner_impl(request, input, merge_cache);
1115 self.measure_adaptive_work = false;
1116 if let Some(learning_revision) = learning_revision
1117 && self
1118 .store
1119 .decision_to_dfa
1120 .get(decision)
1121 .map(ParserDfa::learning_revision)
1122 != Some(learning_revision)
1123 {
1124 (self.adaptive_calls, self.adaptive_closure_work) = work_start;
1125 }
1126 self.has_trained_decision |= self
1127 .store
1128 .decision_to_dfa
1129 .get(decision)
1130 .is_some_and(|dfa| !dfa.is_empty());
1131 result
1132 }
1133
1134 fn adaptive_predict_stream_inner_impl<T: IntStream>(
1135 &mut self,
1136 request: AdaptivePredictRequest,
1137 input: &mut T,
1138 merge_cache: &mut PredictionWorkspace,
1139 ) -> Result<ParserAtnPrediction, ParserAtnSimulatorError> {
1140 let AdaptivePredictRequest {
1141 decision,
1142 precedence,
1143 outer_context,
1144 force_full_context_retry,
1145 sll_probe_only,
1146 } = request;
1147 self.deferred_accept_states
1148 .retain(|(stored_decision, _)| *stored_decision != decision);
1149 #[cfg(feature = "perf-counters")]
1150 crate::perf::record_adaptive_call(decision, force_full_context_retry);
1151 let Some(decision_state) = self.atn.decision_to_state().get(decision) else {
1152 return Err(ParserAtnSimulatorError::UnknownDecision(decision));
1153 };
1154 let start_index = input.index();
1155 let precedence = i32::try_from(precedence).unwrap_or(i32::MAX);
1161 let mut state_number =
1162 self.ensure_start_state(decision, decision_state, precedence, merge_cache)?;
1163 let track_previous_good_alt = !force_full_context_retry && !sll_probe_only;
1166 let mut previous_good_alt = None;
1167 if let Some(prediction) = self.prediction_or_full_context(
1168 input,
1169 PredictionCheck {
1170 decision,
1171 decision_state,
1172 state_number,
1173 start_index,
1174 precedence,
1175 outer_context,
1176 force_full_context_retry,
1177 sll_probe_only,
1178 },
1179 merge_cache,
1180 )? {
1181 return Ok(prediction);
1182 }
1183 loop {
1184 if track_previous_good_alt {
1185 let finished = self
1186 .store
1187 .decision_to_dfa
1188 .get(decision)
1189 .map(|dfa| dfa.configs(state_number))
1190 .and_then(|configs| self.previous_good_alt(configs));
1191 if finished.is_some() {
1192 previous_good_alt = finished;
1193 }
1194 }
1195 let symbol = input.la(1);
1196 let target = self
1197 .store
1198 .decision_to_dfa
1199 .get(decision)
1200 .and_then(|dfa| dfa.edge(state_number, symbol));
1201 #[cfg(feature = "perf-counters")]
1202 crate::perf::record_dfa_edge_lookup(target.is_some());
1203 if let Some(target) = target {
1204 state_number = target;
1205 } else {
1206 let configs = self
1207 .store
1208 .decision_to_dfa
1209 .get(decision)
1210 .map(|dfa| dfa.configs(state_number).clone())
1211 .ok_or(ParserAtnSimulatorError::MissingDfaState(state_number))?;
1212 let edge = DfaEdge {
1213 decision,
1214 source_state: state_number,
1215 };
1216 let target = match self.compute_target_state(
1217 edge,
1218 &configs,
1219 symbol,
1220 precedence,
1221 merge_cache,
1222 ) {
1223 Ok(target) => target,
1224 Err(ParserAtnSimulatorError::NoViableAlt { symbol, .. }) => {
1225 if let Some(fallback) = previous_good_alt.as_ref() {
1226 self.add_previous_good_alt_target(edge, symbol, fallback, merge_cache)
1227 } else {
1228 return Err(ParserAtnSimulatorError::NoViableAlt {
1229 symbol,
1230 index: input.index(),
1231 });
1232 }
1233 }
1234 Err(error) => return Err(error),
1235 };
1236 state_number = target;
1237 }
1238 if let Some(prediction) = self.prediction_or_full_context(
1239 input,
1240 PredictionCheck {
1241 decision,
1242 decision_state,
1243 state_number,
1244 start_index,
1245 precedence,
1246 outer_context,
1247 force_full_context_retry,
1248 sll_probe_only,
1249 },
1250 merge_cache,
1251 )? {
1252 let defer_unique = track_previous_good_alt
1253 && previous_good_alt.is_some()
1254 && !prediction.requires_full_context
1255 && !self.prediction_reached_decision_entry_rule_stop(
1256 DfaEdge {
1257 decision,
1258 source_state: state_number,
1259 },
1260 prediction.alt,
1261 precedence,
1262 symbol,
1263 merge_cache,
1264 );
1265 if !defer_unique {
1266 return Ok(prediction);
1267 }
1268 self.deferred_accept_states.insert((decision, state_number));
1269 }
1270 if symbol == TOKEN_EOF {
1271 if let Some(configs) = self
1281 .store
1282 .decision_to_dfa
1283 .get(decision)
1284 .map(|dfa| dfa.configs(state_number).clone())
1285 && let Some(alt) = self.alt_that_finished_decision_entry_rule(&configs)
1286 {
1287 self.prediction_semantic_candidates =
1288 semantic_prediction_candidates(&configs, &self.store.semantic_contexts);
1289 return Ok(ParserAtnPrediction {
1290 alt,
1291 requires_full_context: false,
1292 has_semantic_context: configs_have_semantic_context_for_alt(&configs, alt),
1293 diagnostic: None,
1294 });
1295 }
1296 return Err(ParserAtnSimulatorError::PredictionRequiresMoreLookahead);
1297 }
1298 input.consume();
1299 }
1300 }
1301
1302 fn prediction_or_full_context<T: IntStream>(
1303 &mut self,
1304 input: &mut T,
1305 check: PredictionCheck,
1306 merge_cache: &mut PredictionWorkspace,
1307 ) -> Result<Option<ParserAtnPrediction>, ParserAtnSimulatorError> {
1308 let PredictionCheck {
1309 decision,
1310 decision_state,
1311 state_number,
1312 start_index,
1313 precedence,
1314 outer_context,
1315 force_full_context_retry,
1316 sll_probe_only,
1317 } = check;
1318 if self.store.contexts.is_empty(outer_context)
1319 && let Some(prediction) =
1320 self.non_greedy_exit_prediction(decision, decision_state, state_number)
1321 {
1322 self.record_prediction_semantic_candidates(decision, state_number);
1323 return Ok(Some(prediction));
1324 }
1325 let Some(info) = self.dfa_prediction_info(decision, state_number) else {
1326 return Ok(None);
1327 };
1328 let mut prediction = info.prediction;
1329 if info.exact_conflict && info.conflicting_alts.len() > 1 {
1330 let stop_index = input.index();
1331 prediction.diagnostic = Some(ParserAtnPredictionDiagnostic {
1332 kind: ParserAtnPredictionDiagnosticKind::Ambiguity,
1333 start_index,
1334 sll_stop_index: stop_index,
1335 ll_stop_index: stop_index,
1336 conflicting_alts: info.conflicting_alts.clone(),
1337 exact: true,
1338 });
1339 }
1340 let semantic_candidates = self
1341 .store
1342 .decision_to_dfa
1343 .get(decision)
1344 .map(|dfa| {
1345 semantic_prediction_candidates(
1346 dfa.configs(state_number),
1347 &self.store.semantic_contexts,
1348 )
1349 })
1350 .unwrap_or_default();
1351 self.prediction_semantic_candidates = semantic_candidates;
1352 if sll_probe_only && prediction.requires_full_context {
1359 return Ok(Some(prediction));
1360 }
1361 if prediction.requires_full_context
1362 && (force_full_context_retry || !prediction.has_semantic_context)
1363 {
1364 #[cfg(feature = "perf-counters")]
1365 crate::perf::record_full_context_retry(decision);
1366 let sll_stop_index = input.index();
1367 input.seek(start_index);
1368 let memo_allowed = self.full_context_memo_allowed();
1369 let memo_key = FullContextMemoKey {
1370 decision,
1371 precedence,
1372 outer_context,
1373 first_symbol: 0,
1374 };
1375 if memo_allowed
1378 && let Some(full_context) = self.probe_full_context_memo(memo_key, input)
1379 {
1380 #[cfg(feature = "perf-counters")]
1381 crate::perf::record_full_context_memo_hit(decision);
1382 return Ok(Some(self.full_context_retry_prediction(
1383 full_context,
1384 info.conflicting_alts,
1385 info.context_containment_conflict,
1386 start_index,
1387 sll_stop_index,
1388 )));
1389 }
1390 let full_context = self.adaptive_predict_full_context(
1391 decision_state,
1392 input,
1393 precedence,
1394 outer_context,
1395 merge_cache,
1396 )?;
1397 if memo_allowed {
1398 self.record_full_context_memo(memo_key, start_index, input, &full_context);
1399 }
1400 return Ok(Some(self.full_context_retry_prediction(
1401 full_context,
1402 info.conflicting_alts,
1403 info.context_containment_conflict,
1404 start_index,
1405 sll_stop_index,
1406 )));
1407 }
1408 Ok(Some(prediction))
1409 }
1410
1411 fn full_context_retry_prediction(
1415 &mut self,
1416 full_context: FullContextPrediction,
1417 sll_conflicting_alts: Vec<usize>,
1418 context_containment_conflict: bool,
1419 start_index: usize,
1420 sll_stop_index: usize,
1421 ) -> ParserAtnPrediction {
1422 let FullContextPrediction {
1423 mut prediction,
1424 stop_index,
1425 resolution,
1426 semantic_candidates,
1427 } = full_context;
1428 let sll_stop_index = if context_containment_conflict {
1432 stop_index
1433 } else {
1434 sll_stop_index
1435 };
1436 self.prediction_semantic_candidates = semantic_candidates;
1437 let (kind, exact, conflicting_alts) = match resolution {
1438 FullContextResolution::Ambiguous { exact, ref alts } => (
1439 ParserAtnPredictionDiagnosticKind::Ambiguity,
1440 exact,
1441 alts.clone(),
1442 ),
1443 FullContextResolution::Unique => (
1447 ParserAtnPredictionDiagnosticKind::ContextSensitivity,
1448 false,
1449 sll_conflicting_alts,
1450 ),
1451 };
1452 prediction.has_semantic_context = self
1453 .prediction_semantic_candidates
1454 .iter()
1455 .any(|candidate| candidate.alt == prediction.alt && !candidate.context.is_none());
1456 if conflicting_alts.len() > 1 {
1457 prediction.diagnostic = Some(ParserAtnPredictionDiagnostic {
1458 kind,
1459 start_index,
1460 sll_stop_index,
1461 ll_stop_index: stop_index,
1462 conflicting_alts,
1463 exact,
1464 });
1465 }
1466 prediction
1467 }
1468
1469 fn record_prediction_semantic_candidates(&mut self, decision: usize, state_number: DfaStateId) {
1470 self.prediction_semantic_candidates = self
1471 .store
1472 .decision_to_dfa
1473 .get(decision)
1474 .map(|dfa| {
1475 semantic_prediction_candidates(
1476 dfa.configs(state_number),
1477 &self.store.semantic_contexts,
1478 )
1479 })
1480 .unwrap_or_default();
1481 }
1482
1483 fn full_context_memo_allowed(&mut self) -> bool {
1500 if self.exact_ambig_detection {
1501 return false;
1502 }
1503 let atn = self.atn;
1504 *self
1505 .full_context_memo_gate
1506 .get_or_insert_with(|| !atn_has_predicate_transition(atn))
1507 }
1508
1509 fn probe_full_context_memo<T: IntStream>(
1520 &self,
1521 mut key: FullContextMemoKey,
1522 input: &mut T,
1523 ) -> Option<FullContextPrediction> {
1524 if self.full_context_memo.is_empty() {
1525 return None;
1526 }
1527 let start_index = input.index();
1528 key.first_symbol = input.la(1);
1529 let entries = self.full_context_memo.get(&key)?;
1530 'candidates: for entry in entries {
1540 for &expected in &entry.window_tail {
1541 input.consume();
1542 if input.la(1) != expected {
1543 input.seek(start_index);
1544 continue 'candidates;
1545 }
1546 }
1547 let mut replay = entry.prediction.clone();
1548 replay.stop_index = input.index();
1549 return Some(replay);
1550 }
1551 None
1552 }
1553
1554 fn record_full_context_memo<T: IntStream>(
1561 &mut self,
1562 mut key: FullContextMemoKey,
1563 start_index: usize,
1564 input: &mut T,
1565 full_context: &FullContextPrediction,
1566 ) {
1567 if self.full_context_memo_len >= FULL_CONTEXT_MEMO_MAX_ENTRIES {
1568 #[cfg(feature = "perf-counters")]
1569 crate::perf::record_full_context_memo_declined(key.decision);
1570 return;
1571 }
1572 let current = input.index();
1573 input.seek(start_index);
1574 key.first_symbol = input.la(1);
1575 let mut window_tail = Vec::new();
1576 while input.index() < full_context.stop_index
1577 && window_tail.len() < FULL_CONTEXT_MEMO_MAX_WINDOW
1578 {
1579 input.consume();
1580 window_tail.push(input.la(1));
1581 }
1582 let complete = input.index() >= full_context.stop_index;
1583 input.seek(current);
1584 if !complete {
1585 #[cfg(feature = "perf-counters")]
1586 crate::perf::record_full_context_memo_declined(key.decision);
1587 return;
1588 }
1589 self.full_context_memo
1590 .entry(key)
1591 .or_default()
1592 .push(FullContextMemoEntry {
1593 window_tail,
1594 prediction: full_context.clone(),
1595 });
1596 self.full_context_memo_len += 1;
1597 }
1598
1599 fn non_greedy_exit_prediction(
1600 &self,
1601 decision: usize,
1602 decision_state: usize,
1603 state_number: DfaStateId,
1604 ) -> Option<ParserAtnPrediction> {
1605 if !self
1606 .atn
1607 .state(decision_state)
1608 .is_some_and(AtnState::non_greedy)
1609 {
1610 return None;
1611 }
1612 let configs = &self
1613 .store
1614 .decision_to_dfa
1615 .get(decision)?
1616 .configs(state_number);
1617 let alt = configs
1618 .configs()
1619 .iter()
1620 .filter(|config| {
1621 self.atn
1622 .state(config.state)
1623 .is_some_and(AtnState::is_rule_stop)
1624 && self.store.contexts.has_empty_path(config.context)
1625 })
1626 .map(|config| config.alt)
1627 .min()?;
1628 Some(ParserAtnPrediction {
1629 alt,
1630 requires_full_context: false,
1631 has_semantic_context: configs_have_semantic_context_for_alt(configs, alt),
1632 diagnostic: None,
1633 })
1634 }
1635
1636 fn ensure_start_state(
1637 &mut self,
1638 decision: usize,
1639 decision_state: usize,
1640 precedence: i32,
1641 merge_cache: &mut PredictionWorkspace,
1642 ) -> Result<DfaStateId, ParserAtnSimulatorError> {
1643 if self.store.decision_to_dfa[decision].is_precedence_dfa() {
1644 let precedence_key = usize::try_from(precedence.max(0)).unwrap_or_default();
1645 if let Some(start) =
1646 self.store.decision_to_dfa[decision].precedence_start_state(precedence_key)
1647 {
1648 return Ok(start);
1649 }
1650 } else if let Some(start) = self.store.decision_to_dfa[decision].start_state() {
1651 return Ok(start);
1652 }
1653 let decision_state = self
1654 .atn
1655 .state(decision_state)
1656 .ok_or(ParserAtnSimulatorError::MissingAtnState(decision_state))?;
1657 let configs = self.compute_start_state(decision_state, precedence, merge_cache);
1658 let state_number = self.add_dfa_state(decision, DfaStateBuilder::new(configs));
1659 if self.store.decision_to_dfa[decision].is_precedence_dfa() {
1660 let precedence_key = usize::try_from(precedence.max(0)).unwrap_or_default();
1661 self.store.decision_to_dfa[decision]
1662 .set_precedence_start_state(precedence_key, state_number);
1663 } else {
1664 self.store.decision_to_dfa[decision].set_start_state(state_number);
1665 }
1666 Ok(state_number)
1667 }
1668
1669 fn add_dfa_state(&mut self, decision: usize, state: DfaStateBuilder) -> DfaStateId {
1670 self.store.decision_to_dfa[decision].add_state(state)
1671 }
1672
1673 fn compute_start_state(
1674 &mut self,
1675 decision_state: AtnState<'_>,
1676 precedence: i32,
1677 merge_cache: &mut PredictionWorkspace,
1678 ) -> AtnConfigSet {
1679 self.compute_start_state_with_context(
1680 decision_state,
1681 false,
1682 EMPTY_CONTEXT,
1683 precedence,
1684 merge_cache,
1685 )
1686 }
1687
1688 fn compute_start_state_with_context(
1689 &mut self,
1690 decision_state: AtnState<'_>,
1691 full_context: bool,
1692 initial_context: ContextId,
1693 precedence: i32,
1694 merge_cache: &mut PredictionWorkspace,
1695 ) -> AtnConfigSet {
1696 let mut configs = AtnConfigSet::new_full_context(full_context);
1697 let mut scratch = ClosureScratch::default();
1698 let params = ClosureParams {
1699 precedence,
1700 collect_predicates: true,
1701 treat_eof_as_epsilon: false,
1702 };
1703 for (index, transition) in decision_state.transitions().iter().enumerate() {
1704 let alt = index + 1;
1705 let config = AtnConfig::new(
1706 transition.target(),
1707 alt,
1708 initial_context,
1709 &self.store.contexts,
1710 );
1711 self.closure(config, &mut configs, merge_cache, &mut scratch, params);
1712 }
1713 configs
1714 }
1715
1716 fn adaptive_predict_full_context<T: IntStream>(
1717 &mut self,
1718 decision_state: usize,
1719 input: &mut T,
1720 precedence: i32,
1721 outer_context: ContextId,
1722 merge_cache: &mut PredictionWorkspace,
1723 ) -> Result<FullContextPrediction, ParserAtnSimulatorError> {
1724 let decision_state = self
1725 .atn
1726 .state(decision_state)
1727 .ok_or(ParserAtnSimulatorError::MissingAtnState(decision_state))?;
1728 let mut configs = self.compute_start_state_with_context(
1729 decision_state,
1730 true,
1731 outer_context,
1732 precedence,
1733 merge_cache,
1734 );
1735 loop {
1743 if let Some(alt) = configs.unique_alt() {
1744 return Ok(full_context_prediction(
1745 alt,
1746 &configs,
1747 &self.store.semantic_contexts,
1748 input.index(),
1749 FullContextResolution::Unique,
1750 ));
1751 }
1752 let symbol = input.la(1);
1753 let reach = self.compute_reach_set(&configs, symbol, true, precedence, merge_cache);
1754 if reach.is_empty() {
1755 return Err(ParserAtnSimulatorError::NoViableAlt {
1756 symbol,
1757 index: input.index(),
1758 });
1759 }
1760 configs = reach;
1761 if let Some(alt) = configs.unique_alt() {
1762 return Ok(full_context_prediction(
1763 alt,
1764 &configs,
1765 &self.store.semantic_contexts,
1766 input.index(),
1767 FullContextResolution::Unique,
1768 ));
1769 }
1770 if !configs.has_semantic_context() {
1771 let subsets = conflicting_alt_subsets(configs.configs());
1772 if self.exact_ambig_detection {
1773 let alts: Vec<usize> = configs.alts().into_iter().collect();
1774 if all_subsets_conflict(&subsets)
1778 && all_subsets_equal(&subsets)
1779 && let Some(&alt) = alts.first()
1780 {
1781 return Ok(full_context_prediction(
1782 alt,
1783 &configs,
1784 &self.store.semantic_contexts,
1785 input.index(),
1786 FullContextResolution::Ambiguous { exact: true, alts },
1787 ));
1788 }
1789 } else if let Some(alt) = single_viable_alt(&subsets) {
1790 let alts: Vec<usize> = configs.alts().into_iter().collect();
1791 return Ok(full_context_prediction(
1792 alt,
1793 &configs,
1794 &self.store.semantic_contexts,
1795 input.index(),
1796 FullContextResolution::Ambiguous { exact: false, alts },
1797 ));
1798 }
1799 }
1800 if symbol == TOKEN_EOF || self.configs_all_reached_rule_stop(&configs) {
1801 let alts: Vec<usize> = configs.alts().into_iter().collect();
1806 let alt = *alts
1807 .first()
1808 .ok_or(ParserAtnSimulatorError::PredictionRequiresMoreLookahead)?;
1809 let resolution = if alts.len() > 1 {
1810 FullContextResolution::Ambiguous {
1811 exact: self.exact_ambig_detection,
1812 alts,
1813 }
1814 } else {
1815 FullContextResolution::Unique
1816 };
1817 return Ok(full_context_prediction(
1818 alt,
1819 &configs,
1820 &self.store.semantic_contexts,
1821 input.index(),
1822 resolution,
1823 ));
1824 }
1825 input.consume();
1826 }
1827 }
1828
1829 fn compute_target_state(
1830 &mut self,
1831 edge: DfaEdge,
1832 configs: &AtnConfigSet,
1833 symbol: i32,
1834 precedence: i32,
1835 merge_cache: &mut PredictionWorkspace,
1836 ) -> Result<DfaStateId, ParserAtnSimulatorError> {
1837 let mut reach = self.compute_reach_set(configs, symbol, false, precedence, merge_cache);
1838 if reach.is_empty() {
1839 if let Some(prediction) = self.alt_that_finished_decision_entry_rule(configs) {
1840 let mut dfa_state = DfaStateBuilder::new(configs.clone());
1841 dfa_state.mark_accept(prediction);
1842 dfa_state.set_has_semantic_context_for_alt(
1845 configs.has_semantic_context()
1846 && configs_have_semantic_context_for_alt(configs, prediction),
1847 );
1848 let target_state = self.add_dfa_state(edge.decision, dfa_state);
1849 self.store.decision_to_dfa[edge.decision].add_edge(
1850 edge.source_state,
1851 symbol,
1852 target_state,
1853 );
1854 return Ok(target_state);
1855 }
1856 return Err(ParserAtnSimulatorError::NoViableAlt { symbol, index: 0 });
1857 }
1858 let prediction = reach.unique_alt();
1859 let conflict = if prediction.is_some() {
1860 None
1861 } else if has_sll_conflict_terminating_prediction(&reach, |state| {
1862 self.atn.state(state).is_some_and(AtnState::is_rule_stop)
1863 }) {
1864 let alts = reach.conflicting_alts();
1865 Some(SllConflict {
1866 alts: if alts.is_empty() { reach.alts() } else { alts },
1867 exact: false,
1868 from_context_containment: false,
1869 })
1870 } else if reach.has_semantic_context() {
1871 None
1874 } else {
1875 let atn = self.atn;
1876 exact_context_sll_conflict(&reach, &mut self.store.contexts, merge_cache, |state| {
1877 atn.state(state).is_some_and(AtnState::is_rule_stop)
1878 })
1879 };
1880 let conflict_prediction = prediction.or_else(|| {
1881 conflict
1882 .as_ref()
1883 .and_then(|conflict| conflict.alts.iter().next().copied())
1884 });
1885 let requires_full_context = prediction.is_none() && conflict_prediction.is_some();
1886 #[cfg(feature = "perf-counters")]
1887 if requires_full_context {
1888 crate::perf::record_sll_conflict(edge.decision);
1889 }
1890 let conflicting_alts = conflict
1891 .as_ref()
1892 .map(|conflict| conflict.alts.iter().copied().collect())
1893 .unwrap_or_default();
1894 let mut dfa_state = DfaStateBuilder::new(reach);
1895 if let Some(prediction) = conflict_prediction {
1896 dfa_state.mark_accept(prediction);
1897 dfa_state.set_requires_full_context(requires_full_context);
1898 dfa_state.set_exact_conflict(
1899 requires_full_context && conflict.as_ref().is_some_and(|conflict| conflict.exact),
1900 );
1901 dfa_state.set_context_containment_conflict(
1902 requires_full_context
1903 && conflict
1904 .as_ref()
1905 .is_some_and(|conflict| conflict.from_context_containment),
1906 );
1907 dfa_state.set_conflicting_alts(conflicting_alts);
1908 dfa_state.set_has_semantic_context_for_alt(
1911 dfa_state.configs.has_semantic_context()
1912 && configs_have_semantic_context_for_alt(&dfa_state.configs, prediction),
1913 );
1914 }
1915 let target_state = self.add_dfa_state(edge.decision, dfa_state);
1916 self.store.decision_to_dfa[edge.decision].add_edge(edge.source_state, symbol, target_state);
1917 Ok(target_state)
1918 }
1919
1920 fn compute_reach_set(
1921 &mut self,
1922 configs: &AtnConfigSet,
1923 symbol: i32,
1924 full_context: bool,
1925 precedence: i32,
1926 merge_cache: &mut PredictionWorkspace,
1927 ) -> AtnConfigSet {
1928 let mut intermediate = AtnConfigSet::new_full_context(full_context);
1929 let mut skipped_stop_states = Vec::new();
1930 let max_token_type = self.atn.max_token_type();
1931 for config in configs.configs() {
1932 let Some(state) = self.atn.state(config.state) else {
1933 continue;
1934 };
1935 if state.is_rule_stop() {
1936 if full_context || symbol == TOKEN_EOF {
1937 skipped_stop_states.push(config.clone());
1938 }
1939 continue;
1940 }
1941 for transition in &state.transitions() {
1942 if transition.matches(symbol, 1, max_token_type) {
1943 let target =
1944 config.moved_to(transition.target(), config.context, &self.store.contexts);
1945 intermediate.add(target, &mut self.store.contexts, merge_cache);
1946 }
1947 }
1948 }
1949 let mut reach = if skipped_stop_states.is_empty() && symbol != TOKEN_EOF {
1950 if intermediate.len() == 1 || intermediate.unique_alt().is_some() {
1951 intermediate
1952 } else {
1953 self.close_intermediate_reach_set(
1954 intermediate,
1955 full_context,
1956 precedence,
1957 symbol,
1958 merge_cache,
1959 )
1960 }
1961 } else {
1962 self.close_intermediate_reach_set(
1963 intermediate,
1964 full_context,
1965 precedence,
1966 symbol,
1967 merge_cache,
1968 )
1969 };
1970 if symbol == TOKEN_EOF {
1971 reach = self.rule_stop_configs(reach, merge_cache);
1972 }
1973 if !full_context || !self.configs_contain_rule_stop(&reach) {
1974 for config in skipped_stop_states {
1975 reach.add(config, &mut self.store.contexts, merge_cache);
1976 }
1977 }
1978 #[cfg(feature = "perf-counters")]
1979 crate::perf::record_reach_set(full_context, configs.len(), reach.len());
1980 reach
1981 }
1982
1983 fn close_intermediate_reach_set(
1984 &mut self,
1985 intermediate: AtnConfigSet,
1986 full_context: bool,
1987 precedence: i32,
1988 symbol: i32,
1989 merge_cache: &mut PredictionWorkspace,
1990 ) -> AtnConfigSet {
1991 let mut reach = AtnConfigSet::new_full_context(full_context);
1992 let mut scratch = ClosureScratch::default();
1993 let params = ClosureParams {
1994 precedence,
1995 collect_predicates: false,
1996 treat_eof_as_epsilon: symbol == TOKEN_EOF,
1997 };
1998 for config in intermediate.into_configs() {
2001 self.closure(config, &mut reach, merge_cache, &mut scratch, params);
2002 }
2003 reach
2004 }
2005
2006 fn alt_that_finished_decision_entry_rule(&self, configs: &AtnConfigSet) -> Option<usize> {
2007 configs
2008 .configs()
2009 .iter()
2010 .filter(|config| self.config_finished_decision_entry_rule(config))
2011 .map(|config| config.alt)
2012 .min()
2013 }
2014
2015 fn previous_good_alt(&self, configs: &AtnConfigSet) -> Option<PreviousGoodAlt> {
2016 let alt = self.alt_that_finished_decision_entry_rule(configs)?;
2017 let configs = configs
2018 .configs()
2019 .iter()
2020 .filter(|config| config.alt == alt && self.config_finished_decision_entry_rule(config))
2021 .cloned()
2022 .collect();
2023 Some(PreviousGoodAlt { alt, configs })
2024 }
2025
2026 fn config_finished_decision_entry_rule(&self, config: &AtnConfig) -> bool {
2027 config.reaches_into_outer_context > 0
2028 || self
2029 .atn
2030 .state(config.state)
2031 .is_some_and(AtnState::is_rule_stop)
2032 && self.store.contexts.has_empty_path(config.context)
2033 }
2034
2035 fn add_previous_good_alt_target(
2036 &mut self,
2037 edge: DfaEdge,
2038 symbol: i32,
2039 fallback: &PreviousGoodAlt,
2040 merge_cache: &mut PredictionWorkspace,
2041 ) -> DfaStateId {
2042 let mut configs = AtnConfigSet::new();
2043 for config in &fallback.configs {
2044 configs.add(config.clone(), &mut self.store.contexts, merge_cache);
2045 }
2046 let has_semantic_context = configs_have_semantic_context_for_alt(&configs, fallback.alt);
2047 let mut state = DfaStateBuilder::new(configs);
2048 state.mark_accept(fallback.alt);
2049 state.set_has_semantic_context_for_alt(has_semantic_context);
2050 let target = self.add_dfa_state(edge.decision, state);
2051 self.store.decision_to_dfa[edge.decision].add_edge(edge.source_state, symbol, target);
2052 target
2053 }
2054
2055 fn prediction_reached_decision_entry_rule_stop(
2056 &mut self,
2057 edge: DfaEdge,
2058 alt: usize,
2059 precedence: i32,
2060 symbol: i32,
2061 merge_cache: &mut PredictionWorkspace,
2062 ) -> bool {
2063 let configs = self.store.decision_to_dfa[edge.decision]
2064 .configs(edge.source_state)
2065 .clone();
2066 if self.alt_that_finished_decision_entry_rule(&configs) == Some(alt) {
2067 return true;
2068 }
2069 let closed =
2070 self.close_intermediate_reach_set(configs, false, precedence, symbol, merge_cache);
2071 self.alt_that_finished_decision_entry_rule(&closed) == Some(alt)
2072 }
2073
2074 fn rule_stop_configs(
2075 &mut self,
2076 configs: AtnConfigSet,
2077 merge_cache: &mut PredictionWorkspace,
2078 ) -> AtnConfigSet {
2079 if configs.configs().iter().all(|config| {
2080 self.atn
2081 .state(config.state)
2082 .is_some_and(AtnState::is_rule_stop)
2083 }) {
2084 return configs;
2085 }
2086 let mut result = AtnConfigSet::new_full_context(configs.full_context());
2087 for config in configs.configs().iter().filter(|config| {
2088 self.atn
2089 .state(config.state)
2090 .is_some_and(AtnState::is_rule_stop)
2091 }) {
2092 result.add(config.clone(), &mut self.store.contexts, merge_cache);
2093 }
2094 result
2095 }
2096
2097 fn configs_all_reached_rule_stop(&self, configs: &AtnConfigSet) -> bool {
2098 configs.configs().iter().all(|config| {
2099 self.atn
2100 .state(config.state)
2101 .is_some_and(AtnState::is_rule_stop)
2102 })
2103 }
2104
2105 fn configs_contain_rule_stop(&self, configs: &AtnConfigSet) -> bool {
2106 configs.configs().iter().any(|config| {
2107 self.atn
2108 .state(config.state)
2109 .is_some_and(AtnState::is_rule_stop)
2110 })
2111 }
2112
2113 fn closure(
2114 &mut self,
2115 config: AtnConfig,
2116 configs: &mut AtnConfigSet,
2117 merge_cache: &mut PredictionWorkspace,
2118 scratch: &mut ClosureScratch,
2119 params: ClosureParams,
2120 ) {
2121 let ClosureParams {
2122 precedence,
2123 collect_predicates,
2124 treat_eof_as_epsilon,
2125 } = params;
2126 let max_token_type = self.atn.max_token_type();
2127 scratch.stack.clear();
2128 scratch.visited.clear();
2129 scratch.stack.push((config, collect_predicates));
2130 while let Some((config, collect_predicates)) = scratch.stack.pop() {
2131 if !scratch.visited.insert(ClosureConfigKey::from(&config)) {
2132 continue;
2133 }
2134 let Some(state) = self.atn.state(config.state) else {
2135 continue;
2136 };
2137 let at_rule_stop = state.is_rule_stop();
2138 if at_rule_stop
2139 && self.closure_at_rule_stop(
2140 config.clone(),
2141 collect_predicates,
2142 configs,
2143 merge_cache,
2144 &mut scratch.stack,
2145 )
2146 {
2147 continue;
2148 }
2149 let epsilon_only = state.epsilon_only();
2150 if !epsilon_only {
2151 configs.add(config.clone(), &mut self.store.contexts, merge_cache);
2152 }
2153 for (index, transition) in state.transitions().iter().enumerate() {
2154 if index == 0
2155 && can_drop_left_recursive_loop_entry_edge(
2156 self.atn,
2157 state,
2158 &self.store.contexts,
2159 config.context,
2160 )
2161 {
2162 continue;
2163 }
2164 let transition_kind = transition.kind();
2165 if matches!(
2166 transition_kind,
2167 ParserTransitionKind::Epsilon
2168 | ParserTransitionKind::Rule
2169 | ParserTransitionKind::Predicate
2170 | ParserTransitionKind::Action
2171 | ParserTransitionKind::Precedence
2172 ) {
2173 if let Some(mut target) = self.epsilon_target_config(
2174 &config,
2175 transition,
2176 transition_kind,
2177 precedence,
2178 collect_predicates,
2179 configs.full_context(),
2180 ) {
2181 if at_rule_stop {
2182 target.reaches_into_outer_context =
2183 target.reaches_into_outer_context.saturating_add(1);
2184 }
2185 let target_collect_predicates =
2189 collect_predicates && transition_kind != ParserTransitionKind::Action;
2190 scratch.stack.push((target, target_collect_predicates));
2191 }
2192 } else if treat_eof_as_epsilon
2193 && transition.matches_kind(transition_kind, TOKEN_EOF, 1, max_token_type)
2194 {
2195 scratch.stack.push((
2196 config.moved_to(transition.target(), config.context, &self.store.contexts),
2197 collect_predicates,
2198 ));
2199 }
2200 }
2201 }
2202 let closure_work = scratch.visited.len();
2203 if self.measure_adaptive_work {
2204 self.adaptive_closure_work = self.adaptive_closure_work.saturating_add(closure_work);
2205 }
2206 #[cfg(feature = "perf-counters")]
2207 crate::perf::record_closure(closure_work);
2208 }
2209
2210 fn closure_at_rule_stop(
2211 &mut self,
2212 config: AtnConfig,
2213 collect_predicates: bool,
2214 configs: &mut AtnConfigSet,
2215 merge_cache: &mut PredictionWorkspace,
2216 stack: &mut Vec<(AtnConfig, bool)>,
2217 ) -> bool {
2218 if self.store.contexts.is_empty(config.context) {
2219 if configs.full_context() {
2220 configs.add(config, &mut self.store.contexts, merge_cache);
2221 return true;
2222 }
2223 return false;
2224 }
2225 let mut handled_all_paths = true;
2226 for index in 0..self.store.contexts.len(config.context) {
2227 let Some(return_state) = self.store.contexts.return_state(config.context, index) else {
2228 continue;
2229 };
2230 if return_state == EMPTY_RETURN_STATE {
2231 if configs.full_context() {
2232 let mut empty_context_config = config.clone();
2233 empty_context_config.set_context(EMPTY_CONTEXT, &self.store.contexts);
2234 configs.add(empty_context_config, &mut self.store.contexts, merge_cache);
2235 } else {
2236 handled_all_paths = false;
2237 }
2238 continue;
2239 }
2240 let parent = self
2241 .store
2242 .contexts
2243 .parent(config.context, index)
2244 .unwrap_or(EMPTY_CONTEXT);
2245 let mut next = config.moved_to(return_state, parent, &self.store.contexts);
2246 if self.track_prediction_rule_calls {
2247 next.exit_prediction_rule(
2248 self.semantic_provenance
2249 .as_deref_mut()
2250 .expect("tracked prediction has a provenance arena"),
2251 );
2252 }
2253 stack.push((next, collect_predicates));
2254 }
2255 handled_all_paths
2256 }
2257
2258 #[allow(clippy::too_many_arguments)]
2259 fn epsilon_target_config(
2260 &mut self,
2261 config: &AtnConfig,
2262 transition: ParserTransition<'_>,
2263 transition_kind: ParserTransitionKind,
2264 precedence: i32,
2265 collect_predicates: bool,
2266 full_context: bool,
2267 ) -> Option<AtnConfig> {
2268 let semantic_context = match transition_kind {
2269 ParserTransitionKind::Predicate if collect_predicates => {
2270 self.store.semantic_contexts.and(
2271 config.semantic_context_id(),
2272 SemanticContext::Predicate {
2273 rule_index: transition.arg0() as usize,
2274 pred_index: transition.arg1() as usize,
2275 context_dependent: transition.arg2() != 0,
2276 },
2277 )
2278 }
2279 ParserTransitionKind::Precedence
2280 if collect_predicates
2281 && i32::from_le_bytes(transition.arg0().to_le_bytes()) < precedence =>
2282 {
2283 return None;
2284 }
2285 ParserTransitionKind::Precedence if collect_predicates && !full_context => {
2286 self.store.semantic_contexts.and(
2287 config.semantic_context_id(),
2288 SemanticContext::Precedence {
2289 precedence: i32::from_le_bytes(transition.arg0().to_le_bytes()),
2290 },
2291 )
2292 }
2293 _ => config.semantic_context_id(),
2294 };
2295 let context_has_empty_path = self.store.contexts.has_empty_path(config.context);
2296 let elide_tail_call = transition_kind == ParserTransitionKind::Rule
2297 && transition.is_tail_call()
2298 && !self.track_prediction_rule_calls
2302 && (!context_has_empty_path || (!full_context && !self.tail_call_preserves_sll));
2305 let context = if transition_kind == ParserTransitionKind::Rule && !elide_tail_call {
2306 self.store
2307 .contexts
2308 .singleton(config.context, transition.arg1() as usize)
2309 } else {
2310 config.context
2311 };
2312 let mut target = config.moved_to(transition.target(), context, &self.store.contexts);
2313 target.set_semantic_context(semantic_context, &self.store.semantic_contexts);
2314 if self.track_prediction_rule_calls {
2315 match transition_kind {
2316 ParserTransitionKind::Rule => {
2317 target.enter_prediction_rule(
2318 self.semantic_provenance
2319 .as_deref_mut()
2320 .expect("tracked prediction has a provenance arena"),
2321 config.state,
2322 transition.arg0() as usize,
2323 );
2324 }
2325 ParserTransitionKind::Predicate if collect_predicates => {
2326 target.record_prediction_predicate(
2327 self.semantic_provenance
2328 .as_deref_mut()
2329 .expect("tracked prediction has a provenance arena"),
2330 transition.arg0() as usize,
2331 transition.arg1() as usize,
2332 );
2333 }
2334 _ => {}
2335 }
2336 }
2337 Some(target)
2338 }
2339
2340 fn dfa_prediction_info(
2341 &self,
2342 decision: usize,
2343 state_number: DfaStateId,
2344 ) -> Option<DfaPredictionInfo> {
2345 let dfa = self.store.decision_to_dfa.get(decision)?;
2346 let state = dfa.state(state_number)?;
2347 let alt = state.prediction()?;
2348 let conflict = state.requires_full_context();
2349 let exact_conflict = conflict && state.is_exact_conflict();
2350 let conflicting_alts = if conflict {
2351 let stored = dfa.conflicting_alts(state_number);
2352 if stored.is_empty() {
2353 dfa.configs(state_number).alts().into_iter().collect()
2354 } else {
2355 stored.to_vec()
2356 }
2357 } else {
2358 Vec::new()
2359 };
2360 Some(DfaPredictionInfo {
2361 prediction: ParserAtnPrediction {
2362 alt,
2363 requires_full_context: conflict && !exact_conflict,
2364 has_semantic_context: state.has_semantic_context(),
2367 diagnostic: None,
2368 },
2369 conflicting_alts,
2370 exact_conflict,
2371 context_containment_conflict: state.is_context_containment_conflict(),
2372 })
2373 }
2374}
2375
2376pub(crate) fn can_drop_left_recursive_loop_entry_edge(
2379 atn: &Atn,
2380 state: AtnState<'_>,
2381 contexts: &ContextArena,
2382 context: ContextId,
2383) -> bool {
2384 if state.kind() != AtnStateKind::StarLoopEntry
2385 || !state.precedence_rule_decision()
2386 || contexts.is_empty(context)
2387 || contexts.has_empty_path(context)
2388 {
2389 return false;
2390 }
2391 let Some(rule_index) = state.rule_index() else {
2392 return false;
2393 };
2394 for index in 0..contexts.len(context) {
2395 let Some(return_state_number) = contexts.return_state(context, index) else {
2396 return false;
2397 };
2398 let Some(return_state) = atn.state(return_state_number) else {
2399 return false;
2400 };
2401 if return_state.rule_index() != Some(rule_index) {
2402 return false;
2403 }
2404 }
2405 let Some(block_end_state_number) = state
2406 .transitions()
2407 .first()
2408 .and_then(|transition| atn.state(transition.target()))
2409 .and_then(AtnState::end_state)
2410 else {
2411 return false;
2412 };
2413 for index in 0..contexts.len(context) {
2414 let return_state_number = contexts
2415 .return_state(context, index)
2416 .expect("return state checked above");
2417 let return_state = atn
2418 .state(return_state_number)
2419 .expect("return state checked above");
2420 if return_state.state_number() == block_end_state_number {
2421 continue;
2422 }
2423 if return_state.transitions().len() != 1
2424 || !return_state
2425 .transitions()
2426 .first()
2427 .is_some_and(ParserTransition::is_epsilon)
2428 {
2429 return false;
2430 }
2431 let return_target = return_state
2432 .transitions()
2433 .first()
2434 .expect("single transition checked above")
2435 .target();
2436 if return_state.kind() == AtnStateKind::BlockEnd && return_target == state.state_number() {
2437 continue;
2438 }
2439 if return_target == block_end_state_number {
2440 continue;
2441 }
2442 let Some(return_target_state) = atn.state(return_target) else {
2443 return false;
2444 };
2445 if return_target_state.kind() == AtnStateKind::BlockEnd
2446 && return_target_state.transitions().len() == 1
2447 && return_target_state
2448 .transitions()
2449 .first()
2450 .is_some_and(ParserTransition::is_epsilon)
2451 && return_target_state
2452 .transitions()
2453 .first()
2454 .is_some_and(|transition| transition.target() == state.state_number())
2455 {
2456 continue;
2457 }
2458 return false;
2459 }
2460 true
2461}
2462
2463fn configs_have_semantic_context_for_alt(configs: &AtnConfigSet, alt: usize) -> bool {
2464 configs
2465 .configs()
2466 .iter()
2467 .any(|config| config.alt == alt && config.has_semantic_context())
2468}
2469
2470#[derive(Clone, Debug, Eq, PartialEq)]
2471pub enum ParserAtnSimulatorError {
2472 MissingAtnState(usize),
2473 MissingDfaState(DfaStateId),
2474 NoViableAlt { symbol: i32, index: usize },
2475 PredictionRequiresMoreLookahead,
2476 UnknownDecision(usize),
2477}
2478
2479fn dfa_state_display(state: ParserDfaStateView<'_>, deferred: bool) -> String {
2481 let mut out = String::new();
2482 let is_accept = state.is_accept_state() && !deferred;
2483 if is_accept {
2484 out.push(':');
2485 }
2486 out.push('s');
2487 out.push_str(&state.id().index().to_string());
2488 if state.requires_full_context() {
2489 out.push('^');
2490 }
2491 if is_accept {
2492 out.push_str("=>");
2493 out.push_str(
2494 &state
2495 .prediction()
2496 .map(|prediction| prediction.to_string())
2497 .unwrap_or_default(),
2498 );
2499 }
2500 out
2501}
2502
2503#[cfg(test)]
2504pub(crate) fn context_containment_test_atn(
2505 block_end_state: Option<usize>,
2506 state_six_transition: ParserTransitionSpec,
2507) -> Atn {
2508 let mut atn = ParserAtnBuilder::new(5);
2509 for (state_number, kind, rule_index) in [
2510 (0, AtnStateKind::RuleStart, 0),
2511 (1, AtnStateKind::BlockStart, 0),
2512 (2, AtnStateKind::Basic, 0),
2513 (3, AtnStateKind::Basic, 0),
2514 (4, AtnStateKind::Basic, 0),
2515 (5, AtnStateKind::Basic, 0),
2516 (6, AtnStateKind::BlockEnd, 0),
2517 (7, AtnStateKind::RuleStop, 0),
2518 (8, AtnStateKind::RuleStart, 1),
2519 (9, AtnStateKind::Basic, 1),
2520 (10, AtnStateKind::RuleStop, 1),
2521 ] {
2522 assert_eq!(
2523 atn.add_state(kind, Some(rule_index))
2524 .expect("state")
2525 .index(),
2526 state_number
2527 );
2528 }
2529 atn.set_rule_to_start_state(vec![0, 8])
2530 .expect("rule start states");
2531 atn.set_rule_to_stop_state(vec![7, 10])
2532 .expect("rule stop states");
2533 if let Some(block_end_state) = block_end_state {
2534 atn.set_end_state(1, block_end_state)
2535 .expect("block end state");
2536 }
2537 atn.add_decision_state(1).expect("outer decision");
2538 atn.add_decision_state(2).expect("inner decision");
2539 atn.add_transition(0, ParserTransitionSpec::Epsilon { target: 1 })
2540 .expect("transition");
2541 atn.add_transition(1, ParserTransitionSpec::Epsilon { target: 2 })
2542 .expect("transition");
2543 atn.add_transition(1, ParserTransitionSpec::Epsilon { target: 3 })
2544 .expect("transition");
2545 for follow_state in [4, 5] {
2546 atn.add_transition(
2547 2,
2548 ParserTransitionSpec::Rule {
2549 target: 8,
2550 rule_index: 1,
2551 follow_state,
2552 precedence: 0,
2553 },
2554 )
2555 .expect("transition");
2556 }
2557 atn.add_transition(
2558 3,
2559 ParserTransitionSpec::Rule {
2560 target: 8,
2561 rule_index: 1,
2562 follow_state: 4,
2563 precedence: 0,
2564 },
2565 )
2566 .expect("transition");
2567 atn.add_transition(
2568 4,
2569 ParserTransitionSpec::Atom {
2570 target: 6,
2571 label: 3,
2572 },
2573 )
2574 .expect("transition");
2575 atn.add_transition(
2576 5,
2577 ParserTransitionSpec::Atom {
2578 target: 6,
2579 label: 4,
2580 },
2581 )
2582 .expect("transition");
2583 atn.add_transition(6, state_six_transition)
2584 .expect("transition");
2585 atn.add_transition(
2586 8,
2587 ParserTransitionSpec::Atom {
2588 target: 9,
2589 label: 1,
2590 },
2591 )
2592 .expect("transition");
2593 atn.add_transition(
2594 9,
2595 ParserTransitionSpec::Atom {
2596 target: 10,
2597 label: 2,
2598 },
2599 )
2600 .expect("transition");
2601 atn.finish().expect("valid packed parser ATN")
2602}
2603
2604#[cfg(test)]
2605#[allow(clippy::disallowed_methods)] mod tests {
2607 use super::*;
2608 use crate::atn::AtnStateKind;
2609 use std::mem::size_of;
2610
2611 fn finish_atn(builder: ParserAtnBuilder) -> Atn {
2612 builder.finish().expect("valid packed parser ATN")
2613 }
2614
2615 fn tail_call_prediction_atn() -> Atn {
2616 let mut atn = ParserAtnBuilder::new(1);
2617 for (kind, rule_index) in [
2618 (AtnStateKind::RuleStart, 0),
2619 (AtnStateKind::Basic, 0),
2620 (AtnStateKind::RuleStop, 0),
2621 (AtnStateKind::RuleStart, 1),
2622 (AtnStateKind::RuleStop, 1),
2623 ] {
2624 atn.add_state(kind, Some(rule_index)).expect("state");
2625 }
2626 atn.set_rule_to_start_state(vec![0, 3])
2627 .expect("rule starts");
2628 atn.set_rule_to_stop_state(vec![2, 4]).expect("rule stops");
2629 atn.add_transition(0, ParserTransitionSpec::Epsilon { target: 1 })
2630 .expect("caller entry");
2631 atn.add_transition(
2632 1,
2633 ParserTransitionSpec::Rule {
2634 target: 3,
2635 rule_index: 1,
2636 follow_state: 2,
2637 precedence: 0,
2638 },
2639 )
2640 .expect("tail call");
2641 atn.add_transition(3, ParserTransitionSpec::Epsilon { target: 4 })
2642 .expect("callee body");
2643 atn.add_transition(4, ParserTransitionSpec::Epsilon { target: 2 })
2644 .expect("derived rule return");
2645 finish_atn(atn)
2646 }
2647
2648 fn tail_call_mismatch_atn() -> Atn {
2649 let mut atn = ParserAtnBuilder::new(2);
2650 for (kind, rule_index) in [
2651 (AtnStateKind::BlockStart, 0),
2652 (AtnStateKind::Basic, 0),
2653 (AtnStateKind::RuleStop, 0),
2654 (AtnStateKind::RuleStart, 1),
2655 (AtnStateKind::Basic, 1),
2656 (AtnStateKind::RuleStop, 1),
2657 ] {
2658 atn.add_state(kind, Some(rule_index)).expect("state");
2659 }
2660 atn.set_rule_to_start_state(vec![0, 3])
2661 .expect("rule starts");
2662 atn.set_rule_to_stop_state(vec![2, 5]).expect("rule stops");
2663 atn.add_decision_state(0).expect("decision state");
2664 atn.add_transition(0, ParserTransitionSpec::Epsilon { target: 1 })
2665 .expect("decision alternative");
2666 atn.add_transition(
2667 1,
2668 ParserTransitionSpec::Rule {
2669 target: 3,
2670 rule_index: 1,
2671 follow_state: 2,
2672 precedence: 0,
2673 },
2674 )
2675 .expect("tail call");
2676 atn.add_transition(
2677 3,
2678 ParserTransitionSpec::Atom {
2679 target: 5,
2680 label: 1,
2681 },
2682 )
2683 .expect("callee token");
2684 atn.add_transition(5, ParserTransitionSpec::Epsilon { target: 2 })
2685 .expect("derived rule return");
2686 finish_atn(atn)
2687 }
2688
2689 fn tracked_tail_call_prediction_atn() -> Atn {
2690 let mut atn = ParserAtnBuilder::new(1);
2691 for (kind, rule_index) in [
2692 (AtnStateKind::RuleStart, 0),
2693 (AtnStateKind::Basic, 0),
2694 (AtnStateKind::RuleStop, 0),
2695 (AtnStateKind::RuleStart, 1),
2696 (AtnStateKind::RuleStop, 1),
2697 (AtnStateKind::RuleStart, 2),
2698 (AtnStateKind::Basic, 2),
2699 (AtnStateKind::RuleStop, 2),
2700 ] {
2701 atn.add_state(kind, Some(rule_index)).expect("state");
2702 }
2703 atn.set_rule_to_start_state(vec![0, 3, 5])
2704 .expect("rule starts");
2705 atn.set_rule_to_stop_state(vec![2, 4, 7])
2706 .expect("rule stops");
2707 atn.add_transition(0, ParserTransitionSpec::Epsilon { target: 1 })
2708 .expect("caller entry");
2709 atn.add_transition(
2710 1,
2711 ParserTransitionSpec::Rule {
2712 target: 3,
2713 rule_index: 1,
2714 follow_state: 2,
2715 precedence: 0,
2716 },
2717 )
2718 .expect("tail call");
2719 atn.add_transition(3, ParserTransitionSpec::Epsilon { target: 4 })
2720 .expect("callee body");
2721 atn.add_transition(
2722 5,
2723 ParserTransitionSpec::Predicate {
2724 target: 6,
2725 rule_index: 2,
2726 pred_index: 0,
2727 context_dependent: false,
2728 },
2729 )
2730 .expect("caller predicate");
2731 atn.add_transition(
2732 6,
2733 ParserTransitionSpec::Atom {
2734 target: 7,
2735 label: 1,
2736 },
2737 )
2738 .expect("caller token");
2739 finish_atn(atn)
2740 }
2741
2742 #[cfg(target_pointer_width = "64")]
2743 #[test]
2744 fn parser_prediction_hot_path_layouts_stay_compact() {
2745 assert!(size_of::<ClosureConfigKey>() <= 56);
2746 assert!(size_of::<CompactParserSemanticCandidate>() <= 48);
2747 }
2748
2749 #[test]
2750 fn parser_dfa_stats_account_for_optional_config_payload_arenas() {
2751 let atn = two_token_decision_atn();
2752 let mut simulator = ParserAtnSimulator::new(&atn);
2753 simulator
2754 .store
2755 .semantic_contexts
2756 .intern(SemanticContext::Predicate {
2757 rule_index: 1,
2758 pred_index: 2,
2759 context_dependent: false,
2760 });
2761 let mut provenance = PredictionSemanticProvenanceArena::default();
2762 provenance.enter_rule(PredictionSemanticProvenanceId::default(), 3, 4);
2763 simulator.semantic_provenance = Some(Box::new(provenance));
2764
2765 let stats = simulator.parser_dfa_stats();
2766 assert_eq!(stats.semantic_contexts, 2);
2767 assert_eq!(stats.semantic_provenance_records, 1);
2768 assert!(stats.semantic_context_bytes > 0);
2769 assert!(stats.semantic_provenance_bytes > 0);
2770 assert!(
2771 stats.cold_bytes
2772 >= stats
2773 .semantic_context_bytes
2774 .saturating_add(stats.semantic_provenance_bytes)
2775 );
2776 }
2777
2778 #[test]
2779 fn union_decision_dfa_preserves_disjoint_coverage() {
2780 fn configs(
2781 atn_state: usize,
2782 arena: &mut ContextArena,
2783 workspace: &mut PredictionWorkspace,
2784 ) -> AtnConfigSet {
2785 let mut set = AtnConfigSet::new();
2786 set.add(
2787 AtnConfig::new(atn_state, 1, EMPTY_CONTEXT, arena),
2788 arena,
2789 workspace,
2790 );
2791 set
2792 }
2793 fn state(
2794 atn_state: usize,
2795 arena: &mut ContextArena,
2796 workspace: &mut PredictionWorkspace,
2797 ) -> DfaStateBuilder {
2798 DfaStateBuilder::new(configs(atn_state, arena, workspace))
2799 }
2800 let mut arena = ContextArena::new();
2801 let mut workspace = PredictionWorkspace::default();
2802
2803 let mut shared = ParserDfa::with_max_token_type(0, 0, 8);
2807 let shared_root = shared.add_state(state(10, &mut arena, &mut workspace));
2808 let shared_a = shared.add_state(state(11, &mut arena, &mut workspace));
2809 shared.add_edge(shared_root, 1, shared_a);
2810 shared.set_start_state(shared_root);
2811
2812 let mut local = ParserDfa::with_max_token_type(0, 0, 8);
2813 let local_b = local.add_state(state(12, &mut arena, &mut workspace));
2814 let local_root = local.add_state(state(10, &mut arena, &mut workspace));
2815 local.add_edge(local_root, 2, local_b);
2816 local.set_precedence_start_state(3, local_root);
2817
2818 union_decision_dfa(&mut shared, local);
2819
2820 assert_eq!(shared.edge(shared_root, 1), Some(shared_a));
2823 let merged_b = shared
2824 .state_id_for_configs(&configs(12, &mut arena, &mut workspace))
2825 .expect("local-only state adopted");
2826 assert_eq!(shared.edge(shared_root, 2), Some(merged_b));
2827 assert_eq!(shared.states().len(), 3);
2828 assert_eq!(shared.start_state(), Some(shared_root));
2830 assert_eq!(shared.precedence_start_state(3), Some(shared_root));
2831 }
2832
2833 #[test]
2834 fn union_prediction_stores_remaps_config_store_ids_before_dfa_union() {
2835 let atn = two_token_decision_atn();
2836 let mut shared = PredictionStore::new(&atn);
2837 let mut local = PredictionStore::new(&atn);
2838 let mut workspace = PredictionWorkspace::default();
2839
2840 let distracting = shared.contexts.singleton(EMPTY_CONTEXT, 99);
2841 let local_context = local.contexts.singleton(EMPTY_CONTEXT, 7);
2842 assert_eq!(distracting, local_context, "both stores allocate ID 1");
2843 let distracting_semantic = shared
2844 .semantic_contexts
2845 .intern(SemanticContext::Precedence { precedence: 99 });
2846 let local_semantic = local.semantic_contexts.intern(SemanticContext::Predicate {
2847 rule_index: 2,
2848 pred_index: 3,
2849 context_dependent: true,
2850 });
2851 assert_eq!(
2852 distracting_semantic, local_semantic,
2853 "both semantic stores allocate ID 1"
2854 );
2855
2856 let mut configs = AtnConfigSet::new();
2857 let mut config = AtnConfig::new(42, 1, local_context, &local.contexts);
2858 config.set_semantic_context(local_semantic, &local.semantic_contexts);
2859 configs.add(config, &mut local.contexts, &mut workspace);
2860 local.decision_to_dfa[0].add_state(DfaStateBuilder::new(configs));
2861
2862 union_prediction_stores(&mut shared, local, &mut workspace);
2863
2864 let imported = shared.decision_to_dfa[0]
2865 .states()
2866 .flat_map(|state| shared.decision_to_dfa[0].configs(state.id()).configs())
2867 .find(|config| config.state == 42)
2868 .expect("local DFA config imported");
2869 assert_ne!(imported.context, local_context);
2870 assert_eq!(shared.contexts.return_state(imported.context, 0), Some(7));
2871 assert_eq!(
2872 imported.semantic_context(&shared.semantic_contexts),
2873 &SemanticContext::Predicate {
2874 rule_index: 2,
2875 pred_index: 3,
2876 context_dependent: true,
2877 }
2878 );
2879 imported.assert_store(&shared.contexts);
2880 }
2881
2882 #[test]
2883 fn outer_context_cache_invalidates_with_rule_context_version() {
2884 let atn = two_token_decision_atn();
2885 let mut simulator = ParserAtnSimulator::new(&atn);
2886
2887 let first = simulator.intern_prediction_context(1, [7]);
2888 let cached = simulator.intern_prediction_context(1, [99]);
2889 let refreshed = simulator.intern_prediction_context(2, [99]);
2890
2891 assert_eq!(cached, first);
2892 assert_ne!(refreshed, first);
2893 assert_eq!(
2894 simulator.store.contexts.return_state(refreshed, 0),
2895 Some(99)
2896 );
2897 let stats = simulator.prediction_context_stats();
2898 assert_eq!(stats.outer_context_cache_hits, 1);
2899 assert_eq!(stats.outer_context_cache_misses, 2);
2900 }
2901
2902 #[test]
2903 fn outer_context_cache_is_simulator_local() {
2904 let atn = two_token_decision_atn();
2905 let mut first = ParserAtnSimulator::new(&atn);
2906 let mut second = ParserAtnSimulator::new(&atn);
2907
2908 let first_context = first.intern_prediction_context(1, [7]);
2909 let second_context = second.intern_prediction_context(1, [99]);
2910
2911 assert_eq!(first.store.contexts.return_state(first_context, 0), Some(7));
2912 assert_eq!(
2913 second.store.contexts.return_state(second_context, 0),
2914 Some(99)
2915 );
2916 }
2917
2918 #[test]
2919 fn marked_tail_calls_reuse_contexts_under_the_selected_sll_policy() {
2920 let atn = tail_call_prediction_atn();
2921 let transition = atn
2922 .state(1)
2923 .expect("call source")
2924 .transitions()
2925 .first()
2926 .expect("rule transition");
2927 assert!(transition.is_tail_call());
2928
2929 let mut conservative = ParserAtnSimulator::new(&atn);
2930 let parent = conservative.store.contexts.singleton(EMPTY_CONTEXT, 99);
2931 let before = conservative.prediction_context_stats().contexts_created;
2932 let config = AtnConfig::new(1, 1, parent, &conservative.store.contexts);
2933 let target = conservative
2934 .epsilon_target_config(&config, transition, transition.kind(), 0, true, true)
2935 .expect("tail-call target");
2936 assert_eq!(target.context, parent);
2937 assert_eq!(
2938 conservative.prediction_context_stats().contexts_created,
2939 before,
2940 "a marked tail call with a caller context must not allocate a return node"
2941 );
2942
2943 let mut workspace = PredictionWorkspace::default();
2944 let full_with_empty =
2945 conservative
2946 .store
2947 .contexts
2948 .merge(parent, EMPTY_CONTEXT, false, &mut workspace);
2949 assert!(conservative.store.contexts.has_empty_path(full_with_empty));
2950 assert!(!conservative.store.contexts.is_empty(full_with_empty));
2951 let config = AtnConfig::new(1, 1, full_with_empty, &conservative.store.contexts);
2952 let target = conservative
2953 .epsilon_target_config(&config, transition, transition.kind(), 0, true, true)
2954 .expect("full-context tail-call target");
2955 assert_ne!(
2956 target.context, full_with_empty,
2957 "full-context empty paths must retain the return frame"
2958 );
2959 assert_eq!(
2960 conservative.store.contexts.return_state(target.context, 0),
2961 Some(2)
2962 );
2963
2964 let local_with_empty =
2965 conservative
2966 .store
2967 .contexts
2968 .merge(parent, EMPTY_CONTEXT, true, &mut workspace);
2969 assert!(
2970 conservative.store.contexts.is_empty(local_with_empty),
2971 "an SLL wildcard merge must collapse an empty path to the local empty context"
2972 );
2973
2974 let local = AtnConfig::new(1, 1, EMPTY_CONTEXT, &conservative.store.contexts);
2975 let target = conservative
2976 .epsilon_target_config(&local, transition, transition.kind(), 0, true, false)
2977 .expect("conservative local target");
2978 assert_ne!(target.context, EMPTY_CONTEXT);
2979 assert_eq!(
2980 conservative.store.contexts.return_state(target.context, 0),
2981 Some(2)
2982 );
2983
2984 let mut compact = ParserAtnSimulator::new_with_tail_call_preserves_sll(&atn, false);
2985 let before = compact.prediction_context_stats().contexts_created;
2986 let local = AtnConfig::new(1, 1, EMPTY_CONTEXT, &compact.store.contexts);
2987 let target = compact
2988 .epsilon_target_config(&local, transition, transition.kind(), 0, true, false)
2989 .expect("reduced-accuracy local target");
2990 assert_eq!(target.context, EMPTY_CONTEXT);
2991 assert_eq!(target.reaches_into_outer_context, 0);
2992 assert_eq!(compact.prediction_context_stats().contexts_created, before);
2993
2994 let mut configs = AtnConfigSet::new();
2995 let mut workspace = PredictionWorkspace::default();
2996 let mut scratch = ClosureScratch::default();
2997 compact.closure(
2998 target,
2999 &mut configs,
3000 &mut workspace,
3001 &mut scratch,
3002 ClosureParams {
3003 precedence: 0,
3004 collect_predicates: true,
3005 treat_eof_as_epsilon: false,
3006 },
3007 );
3008 let returned = configs
3009 .configs()
3010 .iter()
3011 .find(|config| config.state == 2)
3012 .expect("tail call returns through the caller stop");
3013 assert_eq!(
3014 returned.reaches_into_outer_context, 1,
3015 "outer-context reach is recorded only after the callee returns"
3016 );
3017 }
3018
3019 #[test]
3020 fn reduced_sll_tail_call_does_not_accept_a_mismatching_callee() {
3021 let atn = tail_call_mismatch_atn();
3022 let mut simulator = ParserAtnSimulator::new_with_tail_call_preserves_sll(&atn, false);
3023
3024 assert_eq!(
3025 simulator.adaptive_predict(0, [2]),
3026 Err(ParserAtnSimulatorError::NoViableAlt {
3027 symbol: 2,
3028 index: 0,
3029 })
3030 );
3031 }
3032
3033 #[test]
3034 fn tracked_tail_call_preserves_balanced_rule_provenance() {
3035 let atn = tracked_tail_call_prediction_atn();
3036 let transition = atn
3037 .state(1)
3038 .expect("tail call source")
3039 .transitions()
3040 .first()
3041 .expect("tail call");
3042 assert!(transition.is_tail_call());
3043
3044 let mut simulator = ParserAtnSimulator::new(&atn);
3045 simulator.set_track_prediction_rule_calls(true);
3046 let outer_context = simulator.store.contexts.singleton(EMPTY_CONTEXT, 5);
3047 let mut config = AtnConfig::new(1, 1, outer_context, &simulator.store.contexts);
3048 config.enter_prediction_rule(
3049 simulator
3050 .semantic_provenance
3051 .as_deref_mut()
3052 .expect("tracked simulator"),
3053 99,
3054 0,
3055 );
3056 let target = simulator
3057 .epsilon_target_config(&config, transition, transition.kind(), 0, true, true)
3058 .expect("tail-call target");
3059
3060 let mut configs = AtnConfigSet::new_full_context(true);
3061 let mut workspace = PredictionWorkspace::default();
3062 let mut scratch = ClosureScratch::default();
3063 simulator.closure(
3064 target,
3065 &mut configs,
3066 &mut workspace,
3067 &mut scratch,
3068 ClosureParams {
3069 precedence: 0,
3070 collect_predicates: true,
3071 treat_eof_as_epsilon: false,
3072 },
3073 );
3074
3075 let predicate_config = configs
3076 .configs()
3077 .iter()
3078 .find(|config| config.state == 6)
3079 .expect("caller predicate reached");
3080 let predicate_calls = simulator
3081 .semantic_provenance
3082 .as_deref()
3083 .expect("tracked simulator")
3084 .predicate_calls(predicate_config.semantic_provenance_id());
3085 assert_eq!(predicate_calls.len(), 1);
3086 assert!(
3087 predicate_calls[0].rule_calls.is_empty(),
3088 "caller predicate must not inherit a tail-called rule after both returns"
3089 );
3090 }
3091
3092 #[test]
3093 fn adaptive_atn_preference_requires_expensive_prediction_delta() {
3094 assert!(!ParserAtnSimulator::adaptive_prediction_delta_is_expensive(
3095 (0, 0),
3096 (ADAPTIVE_ATN_PREFERENCE_MIN_CALLS - 1, usize::MAX),
3097 ));
3098 assert!(!ParserAtnSimulator::adaptive_prediction_delta_is_expensive(
3099 (5, 7),
3100 (
3101 5 + ADAPTIVE_ATN_PREFERENCE_MIN_CALLS,
3102 7 + ADAPTIVE_ATN_PREFERENCE_MIN_CALLS
3103 * ADAPTIVE_ATN_PREFERENCE_MIN_CLOSURE_WORK_PER_CALL
3104 - 1,
3105 ),
3106 ));
3107 assert!(ParserAtnSimulator::adaptive_prediction_delta_is_expensive(
3108 (5, 7),
3109 (
3110 5 + ADAPTIVE_ATN_PREFERENCE_MIN_CALLS,
3111 7 + ADAPTIVE_ATN_PREFERENCE_MIN_CALLS
3112 * ADAPTIVE_ATN_PREFERENCE_MIN_CLOSURE_WORK_PER_CALL,
3113 ),
3114 ));
3115 assert!(!ParserAtnSimulator::adaptive_prediction_delta_is_decisive(
3116 (5, 7),
3117 (
3118 5 + ADAPTIVE_ATN_PREFERENCE_MIN_CALLS,
3119 7 + ADAPTIVE_ATN_PREFERENCE_MIN_CALLS
3120 * ADAPTIVE_ATN_PREFERENCE_DECISIVE_CLOSURE_WORK_PER_CALL
3121 - 1,
3122 ),
3123 ));
3124 assert!(ParserAtnSimulator::adaptive_prediction_delta_is_decisive(
3125 (5, 7),
3126 (
3127 5 + ADAPTIVE_ATN_PREFERENCE_MIN_CALLS,
3128 7 + ADAPTIVE_ATN_PREFERENCE_MIN_CALLS
3129 * ADAPTIVE_ATN_PREFERENCE_DECISIVE_CLOSURE_WORK_PER_CALL,
3130 ),
3131 ));
3132 }
3133
3134 #[test]
3135 fn adaptive_atn_preference_excludes_first_population_per_decision() {
3136 let atn = two_independent_decisions_atn();
3137 let mut simulator = ParserAtnSimulator::new(&atn);
3138
3139 assert_eq!(simulator.adaptive_prediction_work(), None);
3140 assert_eq!(simulator.adaptive_predict(0, [1, 2]), Ok(1));
3141 let after_first_decision = simulator
3142 .adaptive_prediction_work()
3143 .expect("one decision is trained");
3144 assert_eq!(after_first_decision, (0, 0));
3145
3146 assert_eq!(simulator.adaptive_predict(1, [1, 2]), Ok(1));
3147 assert_eq!(
3148 simulator.adaptive_prediction_work(),
3149 Some(after_first_decision),
3150 "cold work for another decision must not enter the routing counters"
3151 );
3152
3153 assert_eq!(simulator.adaptive_predict(1, [1, 2]), Ok(1));
3154 let after_warm_decision = simulator
3155 .adaptive_prediction_work()
3156 .expect("trained decision work is measurable");
3157 assert_eq!(after_warm_decision.0, after_first_decision.0 + 1);
3158 }
3159
3160 #[test]
3161 fn adaptive_atn_preference_excludes_incremental_population_per_decision() {
3162 let atn = two_token_decision_atn();
3163 let mut simulator = ParserAtnSimulator::new(&atn);
3164
3165 assert_eq!(simulator.adaptive_predict(0, [1, 2]), Ok(1));
3166 let after_first_path = simulator
3167 .adaptive_prediction_work()
3168 .expect("the decision is partially trained");
3169 let transitions_after_first_path = simulator.decision_dfas()[0].stats().transitions;
3170
3171 assert_eq!(simulator.adaptive_predict(0, [1, 3]), Ok(2));
3172 assert!(
3173 simulator.decision_dfas()[0].stats().transitions > transitions_after_first_path,
3174 "the second input must extend the partially populated DFA"
3175 );
3176 assert_eq!(
3177 simulator.adaptive_prediction_work(),
3178 Some(after_first_path),
3179 "incremental DFA construction must not enter the routing counters"
3180 );
3181
3182 assert_eq!(simulator.adaptive_predict(0, [1, 3]), Ok(2));
3183 assert_eq!(
3184 simulator
3185 .adaptive_prediction_work()
3186 .expect("the repeated path is stable")
3187 .0,
3188 after_first_path.0 + 1
3189 );
3190 }
3191
3192 #[test]
3193 fn reset_retains_adaptive_training_and_clear_dfa_cools_it() {
3194 let atn = two_token_decision_atn();
3195 let mut simulator = ParserAtnSimulator::new(&atn);
3196 assert_eq!(simulator.adaptive_prediction_work(), None);
3197 assert_eq!(simulator.adaptive_predict(0, [1, 2]), Ok(1));
3198 assert_eq!(simulator.adaptive_prediction_work(), Some((0, 0)));
3199
3200 simulator.reset();
3201 assert_eq!(simulator.adaptive_calls, 0);
3202 assert_eq!(simulator.adaptive_closure_work, 0);
3203 assert_eq!(simulator.adaptive_prediction_work(), Some((0, 0)));
3204
3205 assert_eq!(simulator.adaptive_predict(0, [1, 2]), Ok(1));
3206 assert_eq!(
3207 simulator
3208 .adaptive_prediction_work()
3209 .expect("warmed counters")
3210 .0,
3211 1
3212 );
3213
3214 simulator.clear_dfa();
3215 assert_eq!(simulator.adaptive_calls, 0);
3216 assert_eq!(simulator.adaptive_closure_work, 0);
3217 assert_eq!(simulator.adaptive_prediction_work(), None);
3218 }
3219
3220 #[test]
3221 fn adaptive_predict_reuses_dense_dfa_edges() {
3222 let atn = two_token_decision_atn();
3223 let mut simulator = ParserAtnSimulator::new(&atn);
3224
3225 assert_eq!(simulator.adaptive_predict(0, [1, 2]), Ok(1));
3226 assert_eq!(simulator.adaptive_predict(0, [1, 3]), Ok(2));
3227
3228 let dfa = &simulator.decision_dfas()[0];
3229 let start = dfa.start_state().expect("start state");
3230 let after_first = dfa.state(start).and_then(|state| state.edge(1));
3231 assert!(after_first.is_some());
3232 }
3233
3234 #[test]
3235 fn shared_simulator_reuses_learned_dfa_states() {
3236 let atn = Box::leak(Box::new(two_token_decision_atn()));
3237 let learned_states = {
3238 let mut simulator = ParserAtnSimulator::new_shared(atn);
3239 assert_eq!(simulator.adaptive_predict(0, [1, 2]), Ok(1));
3240 simulator.decision_dfas()[0].states().len()
3241 };
3242
3243 let simulator = ParserAtnSimulator::new_shared(atn);
3244 assert_eq!(simulator.decision_dfas()[0].states().len(), learned_states);
3245 }
3246
3247 #[test]
3248 fn shared_simulator_separates_tail_call_sll_policies() {
3249 let atn = Box::leak(Box::new(two_token_decision_atn()));
3250 ParserAtnSimulator::clear_shared_dfa(atn);
3251
3252 {
3253 let mut conservative = ParserAtnSimulator::new_shared(atn);
3254 assert_eq!(conservative.adaptive_predict(0, [1, 2]), Ok(1));
3255 }
3256 {
3257 let mut compact =
3258 ParserAtnSimulator::new_shared_with_tail_call_preserves_sll(atn, false);
3259 assert_eq!(compact.adaptive_prediction_work(), None);
3260 assert_eq!(compact.adaptive_predict(0, [1, 3]), Ok(2));
3261 }
3262
3263 let conservative = ParserAtnSimulator::new_shared(atn);
3264 assert_eq!(conservative.adaptive_prediction_work(), Some((0, 0)));
3265 drop(conservative);
3266 let compact = ParserAtnSimulator::new_shared_with_tail_call_preserves_sll(atn, false);
3267 assert_eq!(compact.adaptive_prediction_work(), Some((0, 0)));
3268 }
3269
3270 #[test]
3271 #[should_panic(expected = "shared prediction simulators use a fixed untracked rule-call mode")]
3272 fn shared_simulator_rejects_rule_call_tracking_mode_changes() {
3273 let atn = Box::leak(Box::new(two_token_decision_atn()));
3274 let mut simulator = ParserAtnSimulator::new_shared(atn);
3275
3276 simulator.set_track_prediction_rule_calls(true);
3277 }
3278
3279 #[test]
3280 #[should_panic(
3281 expected = "prediction rule-call tracking mode cannot change after DFA construction"
3282 )]
3283 fn simulator_rejects_rule_call_tracking_mode_changes_after_learning() {
3284 let atn = two_token_decision_atn();
3285 let mut simulator = ParserAtnSimulator::new(&atn);
3286 assert_eq!(simulator.adaptive_predict(0, [1, 2]), Ok(1));
3287
3288 simulator.set_track_prediction_rule_calls(true);
3289 }
3290
3291 #[test]
3292 fn shared_simulator_preserves_and_clears_prediction_training_state() {
3293 let atn = Box::leak(Box::new(two_token_decision_atn()));
3294 {
3295 let mut simulator = ParserAtnSimulator::new_shared(atn);
3296 assert_eq!(simulator.adaptive_predict(0, [1, 2]), Ok(1));
3297 }
3298
3299 {
3300 let simulator = ParserAtnSimulator::new_shared(atn);
3301 assert_eq!(simulator.adaptive_prediction_work(), Some((0, 0)));
3302 }
3303
3304 ParserAtnSimulator::clear_shared_dfa(atn);
3305 let simulator = ParserAtnSimulator::new_shared(atn);
3306 assert_eq!(simulator.adaptive_prediction_work(), None);
3307 }
3308
3309 #[test]
3310 fn overlapping_shared_simulator_treats_an_empty_store_as_cold() {
3311 let atn = Box::leak(Box::new(two_token_decision_atn()));
3312 {
3313 let mut simulator = ParserAtnSimulator::new_shared(atn);
3314 assert_eq!(simulator.adaptive_predict(0, [1, 2]), Ok(1));
3315 }
3316
3317 let warmed = ParserAtnSimulator::new_shared(atn);
3318 assert_eq!(warmed.adaptive_prediction_work(), Some((0, 0)));
3319 let overlapping = ParserAtnSimulator::new_shared(atn);
3320 assert_eq!(overlapping.adaptive_prediction_work(), None);
3321 }
3322
3323 #[test]
3324 fn clear_shared_dfa_drops_learned_states() {
3325 let atn = Box::leak(Box::new(two_token_decision_atn()));
3326 {
3327 let mut simulator = ParserAtnSimulator::new_shared(atn);
3328 assert_eq!(simulator.adaptive_predict(0, [1, 2]), Ok(1));
3329 assert!(!simulator.decision_dfas()[0].is_empty());
3330 }
3331
3332 ParserAtnSimulator::clear_shared_dfa(atn);
3333
3334 let simulator = ParserAtnSimulator::new_shared(atn);
3335 assert!(simulator.decision_dfas()[0].is_empty());
3336 }
3337
3338 #[test]
3339 fn clear_dfa_rejects_stale_overlapping_simulator_publication() {
3340 let atn = Box::leak(Box::new(two_token_decision_atn()));
3341 let mut current = ParserAtnSimulator::new_shared(atn);
3342 let mut stale = ParserAtnSimulator::new_shared(atn);
3343 assert_eq!(stale.adaptive_predict(0, [1, 2]), Ok(1));
3344 assert!(!stale.decision_dfas()[0].is_empty());
3345
3346 current.clear_dfa();
3347 drop(stale);
3348 drop(current);
3349
3350 let simulator = ParserAtnSimulator::new_shared(atn);
3351 assert!(simulator.decision_dfas()[0].is_empty());
3352 }
3353
3354 #[test]
3355 fn adaptive_predict_reports_no_viable_alt() {
3356 let atn = two_token_decision_atn();
3357 let mut simulator = ParserAtnSimulator::new(&atn);
3358
3359 assert_eq!(
3360 simulator.adaptive_predict(0, [4]),
3361 Err(ParserAtnSimulatorError::NoViableAlt {
3362 symbol: 4,
3363 index: 0
3364 })
3365 );
3366 }
3367
3368 #[test]
3369 fn adaptive_predict_marks_sll_conflict_for_full_context() {
3370 let atn = ambiguous_single_token_decision_atn();
3371 let mut simulator = ParserAtnSimulator::new(&atn);
3372
3373 assert_eq!(simulator.adaptive_predict(0, [1]), Ok(1));
3374 let prediction = simulator
3375 .adaptive_predict_info_with_precedence(0, 0, [1])
3376 .expect("prediction");
3377 insta::assert_debug_snapshot!(
3378 "adaptive_predict_marks_sll_conflict_for_full_context",
3379 prediction
3380 );
3381
3382 let dfa = &simulator.decision_dfas()[0];
3383 let start = dfa.start_state().expect("start state");
3384 let target = dfa
3385 .state(start)
3386 .and_then(|state| state.edge(1))
3387 .expect("edge for token 1");
3388 let state = dfa.state(target).expect("target state");
3389 assert!(state.is_accept_state());
3390 assert!(state.requires_full_context());
3391 assert_eq!(state.prediction(), Some(1));
3392 }
3393
3394 #[test]
3395 fn adaptive_predict_stops_at_a_context_containment_conflict() {
3396 let atn = context_containment_decision_atn();
3397 let mut simulator = ParserAtnSimulator::new(&atn);
3398 let mut input = VecIntStream::new(vec![1, 2, 5, TOKEN_EOF]);
3399
3400 let prediction = simulator
3401 .adaptive_predict_stream_info_sll_probe(0, 0, &mut input)
3402 .expect("containment proves an SLL conflict before the invalid suffix");
3403
3404 assert_eq!(prediction.alt, 1);
3405 assert!(prediction.requires_full_context);
3406 let dfa = &simulator.decision_dfas()[0];
3407 let start = dfa.start_state().expect("start state");
3408 let target = dfa
3409 .state(start)
3410 .and_then(|state| state.edge(1))
3411 .expect("edge for the shared first token");
3412 let state = dfa.state(target).expect("containment conflict state");
3413 assert!(state.is_accept_state());
3414 assert!(state.requires_full_context());
3415 assert!(!state.is_exact_conflict());
3416 assert_eq!(state.prediction(), Some(1));
3417 assert!(
3418 state.edge(2).is_none(),
3419 "the outer SLL decision must stop before the shared second token"
3420 );
3421 }
3422
3423 #[test]
3424 fn context_containment_full_context_memo_replays_diagnostic() {
3425 let atn = context_containment_decision_atn();
3426 let mut simulator = ParserAtnSimulator::new(&atn);
3427 let mut input = VecIntStream::new(vec![1, 2, 3, TOKEN_EOF]);
3428
3429 let fresh = simulator
3430 .adaptive_predict_stream_info_with_context(0, 0, &mut input, EMPTY_CONTEXT)
3431 .expect("fresh full-context retry");
3432 assert_eq!(simulator.full_context_memo_len, 1);
3433
3434 let replayed = simulator
3435 .adaptive_predict_stream_info_with_context(0, 0, &mut input, EMPTY_CONTEXT)
3436 .expect("memoized full-context retry");
3437
3438 assert_eq!(replayed, fresh);
3439 assert_eq!(simulator.full_context_memo_len, 1);
3440 let diagnostic = replayed
3441 .diagnostic
3442 .expect("the common return path remains ambiguous");
3443 assert_eq!(diagnostic.sll_stop_index, diagnostic.ll_stop_index);
3444 }
3445
3446 #[test]
3447 fn context_containment_ll_retry_preserves_reference_diagnostic_stop() {
3448 let atn = context_containment_decision_atn();
3449 let mut simulator = ParserAtnSimulator::new(&atn);
3450 simulator.set_exact_ambig_detection(true);
3451 let mut input = VecIntStream::new(vec![1, 2, 3, TOKEN_EOF]);
3452
3453 let prediction = simulator
3454 .adaptive_predict_stream_info_with_context(0, 0, &mut input, EMPTY_CONTEXT)
3455 .expect("full-context retry should resolve the containment conflict");
3456 let diagnostic = prediction
3457 .diagnostic
3458 .expect("the common return path remains ambiguous");
3459
3460 assert_eq!(
3461 diagnostic.sll_stop_index, diagnostic.ll_stop_index,
3462 "LL diagnostics retain the reference stop even though SLL accepted earlier"
3463 );
3464 }
3465
3466 #[test]
3467 fn adaptive_predict_keeps_rule_stop_configs_at_eof() {
3468 let atn = optional_token_decision_atn();
3469 let mut simulator = ParserAtnSimulator::new(&atn);
3470
3471 assert_eq!(simulator.adaptive_predict(0, [TOKEN_EOF]), Ok(2));
3472 }
3473
3474 #[test]
3475 fn adaptive_predict_treats_repeated_eof_as_epsilon_after_first_eof() {
3476 let atn = multiple_eof_decision_atn();
3477 let mut simulator = ParserAtnSimulator::new(&atn);
3478
3479 assert_eq!(simulator.adaptive_predict(0, [1, TOKEN_EOF]), Ok(1));
3480 }
3481
3482 #[test]
3483 fn adaptive_predict_uses_finished_entry_rule_alt_on_error_edge() {
3484 let atn = prefix_alt_decision_atn();
3485 let mut simulator = ParserAtnSimulator::new(&atn);
3486
3487 assert_eq!(simulator.adaptive_predict(0, [1, 3]), Ok(1));
3488 }
3489
3490 #[test]
3491 fn adaptive_predict_keeps_prefix_alt_until_longer_alt_finishes() {
3492 let atn = three_token_prefix_alt_decision_atn();
3493 let mut simulator = ParserAtnSimulator::new(&atn);
3494
3495 assert_eq!(simulator.adaptive_predict(0, [1, 2, TOKEN_EOF]), Ok(1));
3496 assert_eq!(simulator.adaptive_predict(0, [1, 2, 1, TOKEN_EOF]), Ok(2));
3497 }
3498
3499 #[test]
3500 fn sll_probe_keeps_unique_alt_early_termination() {
3501 let atn = three_token_prefix_alt_decision_atn();
3502 let mut simulator = ParserAtnSimulator::new(&atn);
3503 let mut input = VecIntStream::new(vec![1, 2, TOKEN_EOF]);
3504
3505 let prediction = simulator
3506 .adaptive_predict_stream_info_sll_probe(0, 0, &mut input)
3507 .expect("SLL prediction should succeed");
3508
3509 assert_eq!(prediction.alt, 2);
3510 }
3511
3512 #[test]
3513 fn adaptive_predict_uses_precedence_dfa_start_states() {
3514 let atn = two_token_decision_atn_with_precedence(true);
3515 let mut simulator = ParserAtnSimulator::new(&atn);
3516
3517 assert_eq!(
3518 simulator.adaptive_predict_with_precedence(0, 3, [1, 2]),
3519 Ok(1)
3520 );
3521 assert_eq!(
3522 simulator.adaptive_predict_with_precedence(0, 7, [1, 3]),
3523 Ok(2)
3524 );
3525
3526 let dfa = &simulator.decision_dfas()[0];
3527 assert!(dfa.is_precedence_dfa());
3528 assert!(dfa.precedence_start_state(3).is_some());
3529 assert!(dfa.precedence_start_state(7).is_some());
3530 }
3531
3532 #[test]
3533 fn adaptive_predict_stream_restores_input_position() {
3534 let atn = two_token_decision_atn();
3535 let mut simulator = ParserAtnSimulator::new(&atn);
3536 let mut input = VecIntStream::new(vec![1, 3, TOKEN_EOF]);
3537
3538 assert_eq!(simulator.adaptive_predict_stream(0, &mut input), Ok(2));
3539 assert_eq!(input.index(), 0);
3540 assert_eq!(input.la(1), 1);
3541 }
3542
3543 #[test]
3544 fn adaptive_predict_stream_retries_full_context_conflict() {
3545 let atn = ambiguous_single_token_decision_atn();
3546 let mut simulator = ParserAtnSimulator::new(&atn);
3547 let mut input = VecIntStream::new(vec![1, TOKEN_EOF]);
3548
3549 let prediction = simulator
3550 .adaptive_predict_stream_info_with_precedence(0, 0, &mut input)
3551 .expect("prediction");
3552
3553 insta::assert_debug_snapshot!(
3554 "adaptive_predict_stream_retries_full_context_conflict",
3555 prediction
3556 );
3557 assert_eq!(input.index(), 0);
3558 }
3559
3560 #[test]
3561 fn full_context_memo_replays_identical_retries() {
3562 let atn = ambiguous_single_token_decision_atn();
3563 let mut simulator = ParserAtnSimulator::new(&atn);
3564
3565 let mut input = VecIntStream::new(vec![1, TOKEN_EOF]);
3568 let fresh = simulator
3569 .adaptive_predict_stream_info_with_context(0, 0, &mut input, EMPTY_CONTEXT)
3570 .expect("fresh prediction");
3571 assert_eq!(simulator.full_context_memo_len, 1);
3572 assert_eq!(input.index(), 0, "cursor restored after prediction");
3573
3574 let replayed = simulator
3578 .adaptive_predict_stream_info_with_context(0, 0, &mut input, EMPTY_CONTEXT)
3579 .expect("memoized prediction");
3580 assert_eq!(replayed, fresh);
3581 assert_eq!(simulator.full_context_memo_len, 1, "no duplicate entry");
3582 assert_eq!(input.index(), 0);
3583
3584 let mut other_input = VecIntStream::new(vec![2, TOKEN_EOF]);
3587 let other = simulator.adaptive_predict_stream_info_with_context(
3588 0,
3589 0,
3590 &mut other_input,
3591 EMPTY_CONTEXT,
3592 );
3593 assert!(other.is_err(), "different window must not replay");
3596
3597 let context = simulator.store.contexts.singleton(EMPTY_CONTEXT, 6);
3599 let mut input = VecIntStream::new(vec![1, TOKEN_EOF]);
3600 let _ = simulator
3601 .adaptive_predict_stream_info_with_context(0, 0, &mut input, context)
3602 .expect("prediction under a different context");
3603 assert_eq!(
3604 simulator.full_context_memo_len, 2,
3605 "distinct context records its own entry"
3606 );
3607 }
3608
3609 #[test]
3610 fn full_context_memo_walks_multi_token_windows() {
3611 let atn = ambiguous_three_token_decision_atn();
3612 let mut simulator = ParserAtnSimulator::new(&atn);
3613
3614 let mut input = VecIntStream::new(vec![1, 2, 3, TOKEN_EOF]);
3617 let fresh = simulator
3618 .adaptive_predict_stream_info_with_context(0, 0, &mut input, EMPTY_CONTEXT)
3619 .expect("fresh prediction");
3620 assert_eq!(simulator.full_context_memo_len, 1);
3621 let recorded_window_len = simulator
3622 .full_context_memo
3623 .values()
3624 .next()
3625 .and_then(|entries| entries.first())
3626 .map(|entry| entry.window_tail.len())
3627 .expect("one recorded entry");
3628 assert!(
3629 recorded_window_len >= 1,
3630 "the LL loop consumed tokens, so the window tail must be non-empty"
3631 );
3632
3633 let replayed = simulator
3636 .adaptive_predict_stream_info_with_context(0, 0, &mut input, EMPTY_CONTEXT)
3637 .expect("memoized prediction");
3638 assert_eq!(replayed, fresh);
3639 assert_eq!(input.index(), 0, "cursor restored by the caller wrapper");
3640
3641 let mut diverging = VecIntStream::new(vec![1, 9, 9, TOKEN_EOF]);
3647 let result = simulator.adaptive_predict_stream_info_with_context(
3648 0,
3649 0,
3650 &mut diverging,
3651 EMPTY_CONTEXT,
3652 );
3653 assert!(result.is_err(), "mid-window divergence must not replay");
3654 assert_eq!(simulator.full_context_memo_len, 1);
3655 }
3656
3657 #[test]
3658 fn full_context_memo_stays_off_for_predicated_atns_and_exact_mode() {
3659 let atn = ambiguous_single_token_decision_atn();
3662 let mut simulator = ParserAtnSimulator::new(&atn);
3663 simulator.set_exact_ambig_detection(true);
3664 let mut input = VecIntStream::new(vec![1, TOKEN_EOF]);
3665 let _ = simulator
3666 .adaptive_predict_stream_info_with_context(0, 0, &mut input, EMPTY_CONTEXT)
3667 .expect("prediction");
3668 assert_eq!(simulator.full_context_memo_len, 0);
3669
3670 let mut atn = ParserAtnBuilder::new(1);
3673 add_state(&mut atn, 0, AtnStateKind::Basic);
3674 add_state(&mut atn, 1, AtnStateKind::Basic);
3675 atn.add_transition(
3676 0,
3677 ParserTransitionSpec::Predicate {
3678 target: 1,
3679 rule_index: 0,
3680 pred_index: 0,
3681 context_dependent: false,
3682 },
3683 )
3684 .expect("transition");
3685 atn.set_rule_to_start_state(vec![0])
3686 .expect("rule start states");
3687 atn.set_rule_to_stop_state(vec![1])
3688 .expect("rule stop states");
3689 let atn = finish_atn(atn);
3690 let mut simulator = ParserAtnSimulator::new(&atn);
3691 assert!(!simulator.full_context_memo_allowed());
3692 }
3693
3694 #[test]
3695 fn full_context_memo_allows_action_and_precedence_transitions() {
3696 let mut atn = ParserAtnBuilder::new(1);
3702 add_state(&mut atn, 0, AtnStateKind::Basic);
3703 add_state(&mut atn, 1, AtnStateKind::Basic);
3704 add_state(&mut atn, 2, AtnStateKind::Basic);
3705 atn.add_transition(
3706 0,
3707 ParserTransitionSpec::Action {
3708 target: 1,
3709 rule_index: 0,
3710 action_index: Some(0),
3711 context_dependent: false,
3712 },
3713 )
3714 .expect("transition");
3715 atn.add_transition(
3716 1,
3717 ParserTransitionSpec::Precedence {
3718 target: 2,
3719 precedence: 1,
3720 },
3721 )
3722 .expect("transition");
3723 atn.set_rule_to_start_state(vec![0])
3724 .expect("rule start states");
3725 atn.set_rule_to_stop_state(vec![2])
3726 .expect("rule stop states");
3727 let atn = finish_atn(atn);
3728 let mut simulator = ParserAtnSimulator::new(&atn);
3729 assert!(simulator.full_context_memo_allowed());
3730 }
3731
3732 #[test]
3733 fn context_prediction_reports_context_sensitivity_for_dfa_conflict() {
3734 let atn = two_token_decision_atn();
3735 let mut simulator = ParserAtnSimulator::new(&atn);
3736 let mut workspace = PredictionWorkspace::default();
3737 let mut start_configs = AtnConfigSet::new();
3738 start_configs.add(
3739 AtnConfig::new(2, 1, EMPTY_CONTEXT, &simulator.store.contexts),
3740 &mut simulator.store.contexts,
3741 &mut workspace,
3742 );
3743 let start =
3744 simulator.store.decision_to_dfa[0].add_state(DfaStateBuilder::new(start_configs));
3745 simulator.store.decision_to_dfa[0].set_start_state(start);
3746
3747 let mut accept_configs = AtnConfigSet::new();
3748 accept_configs.add(
3749 AtnConfig::new(3, 1, EMPTY_CONTEXT, &simulator.store.contexts).with_semantic_context(
3750 SemanticContext::Predicate {
3751 rule_index: 0,
3752 pred_index: 0,
3753 context_dependent: false,
3754 },
3755 &mut simulator.store.semantic_contexts,
3756 ),
3757 &mut simulator.store.contexts,
3758 &mut workspace,
3759 );
3760 let mut accept_state = DfaStateBuilder::new(accept_configs);
3761 accept_state.mark_accept(1);
3762 accept_state.set_requires_full_context(true);
3763 accept_state.set_conflicting_alts(vec![1, 2]);
3764 let accept = simulator.store.decision_to_dfa[0].add_state(accept_state);
3765 simulator.store.decision_to_dfa[0].add_edge(start, 1, accept);
3766
3767 let mut input = VecIntStream::new(vec![1, 3, TOKEN_EOF]);
3768 let prediction = simulator
3769 .adaptive_predict_stream_info_with_context(0, 0, &mut input, EMPTY_CONTEXT)
3770 .expect("prediction");
3771
3772 insta::assert_debug_snapshot!(
3773 "context_prediction_reports_context_sensitivity_for_dfa_conflict",
3774 prediction
3775 );
3776 assert_eq!(input.index(), 0);
3777 }
3778
3779 #[test]
3780 fn exact_sll_conflict_skips_full_context_retry() {
3781 let atn = two_token_decision_atn();
3782 let mut simulator = ParserAtnSimulator::new(&atn);
3783 let mut workspace = PredictionWorkspace::default();
3784 let mut start_configs = AtnConfigSet::new();
3785 start_configs.add(
3786 AtnConfig::new(2, 1, EMPTY_CONTEXT, &simulator.store.contexts),
3787 &mut simulator.store.contexts,
3788 &mut workspace,
3789 );
3790 let start =
3791 simulator.store.decision_to_dfa[0].add_state(DfaStateBuilder::new(start_configs));
3792 simulator.store.decision_to_dfa[0].set_start_state(start);
3793
3794 let mut accept_configs = AtnConfigSet::new();
3795 for alt in [1, 2] {
3796 accept_configs.add(
3797 AtnConfig::new(3, alt, EMPTY_CONTEXT, &simulator.store.contexts),
3798 &mut simulator.store.contexts,
3799 &mut workspace,
3800 );
3801 }
3802 let mut accept_state = DfaStateBuilder::new(accept_configs);
3803 accept_state.mark_accept(1);
3804 accept_state.set_requires_full_context(true);
3805 accept_state.set_exact_conflict(true);
3806 accept_state.set_context_containment_conflict(true);
3807 accept_state.set_conflicting_alts(vec![1, 2]);
3808 let accept = simulator.store.decision_to_dfa[0].add_state(accept_state);
3809 simulator.store.decision_to_dfa[0].add_edge(start, 1, accept);
3810
3811 let mut input = VecIntStream::new(vec![1, 3, TOKEN_EOF]);
3812 let prediction = simulator
3813 .adaptive_predict_stream_info_with_context(0, 0, &mut input, EMPTY_CONTEXT)
3814 .expect("exact SLL conflict");
3815
3816 insta::assert_debug_snapshot!("exact_sll_conflict_skips_full_context_retry", prediction);
3817 assert_eq!(simulator.full_context_memo_len, 0);
3818 assert_eq!(input.index(), 0);
3819 }
3820
3821 #[test]
3822 fn full_context_reach_prefers_longer_match_over_skipped_stop_state() {
3823 let atn = prefix_alt_decision_atn();
3824 let mut simulator = ParserAtnSimulator::new(&atn);
3825 let mut configs = AtnConfigSet::new_full_context(true);
3826 let mut merge_cache = PredictionWorkspace::default();
3827 configs.add(
3828 AtnConfig::new(2, 1, EMPTY_CONTEXT, &simulator.store.contexts),
3829 &mut simulator.store.contexts,
3830 &mut merge_cache,
3831 );
3832 configs.add(
3833 AtnConfig::new(1, 2, EMPTY_CONTEXT, &simulator.store.contexts),
3834 &mut simulator.store.contexts,
3835 &mut merge_cache,
3836 );
3837
3838 let reach = simulator.compute_reach_set(&configs, 2, true, 0, &mut merge_cache);
3839
3840 assert_eq!(reach.alts(), std::iter::once(2).collect());
3841 assert!(simulator.configs_all_reached_rule_stop(&reach));
3842 }
3843
3844 #[test]
3845 fn sll_closure_follows_empty_context_rule_stop_exits() {
3846 let mut atn = ParserAtnBuilder::new(1);
3847 add_state(&mut atn, 0, AtnStateKind::RuleStop);
3848 add_state(&mut atn, 1, AtnStateKind::Basic);
3849 add_state(&mut atn, 2, AtnStateKind::Basic);
3850 atn.add_transition(0, ParserTransitionSpec::Epsilon { target: 1 })
3851 .expect("transition");
3852 atn.add_transition(
3853 1,
3854 ParserTransitionSpec::Atom {
3855 target: 2,
3856 label: 1,
3857 },
3858 )
3859 .expect("transition");
3860 atn.set_rule_to_start_state(vec![0])
3861 .expect("rule start states");
3862 atn.set_rule_to_stop_state(vec![0])
3863 .expect("rule stop states");
3864 let atn = finish_atn(atn);
3865
3866 let mut simulator = ParserAtnSimulator::new(&atn);
3867 let mut configs = AtnConfigSet::new_full_context(false);
3868 let mut merge_cache = PredictionWorkspace::default();
3869 let mut scratch = ClosureScratch::default();
3870 let config = AtnConfig::new(0, 2, EMPTY_CONTEXT, &simulator.store.contexts);
3871 simulator.closure(
3872 config,
3873 &mut configs,
3874 &mut merge_cache,
3875 &mut scratch,
3876 ClosureParams {
3877 precedence: 0,
3878 collect_predicates: true,
3879 treat_eof_as_epsilon: false,
3880 },
3881 );
3882
3883 assert_eq!(configs.len(), 1);
3884 let config = &configs.configs()[0];
3885 assert_eq!(config.state, 1);
3886 assert_eq!(config.alt, 2);
3887 assert_eq!(config.reaches_into_outer_context, 1);
3888 }
3889
3890 #[test]
3891 fn precedence_contexts_are_collected_only_for_start_closure() {
3892 let mut atn = ParserAtnBuilder::new(1);
3893 add_state(&mut atn, 0, AtnStateKind::Basic);
3894 add_state(&mut atn, 1, AtnStateKind::Basic);
3895 atn.set_rule_to_start_state(vec![0])
3896 .expect("rule start states");
3897 atn.set_rule_to_stop_state(vec![1])
3898 .expect("rule stop states");
3899 atn.add_transition(
3900 0,
3901 ParserTransitionSpec::Precedence {
3902 target: 1,
3903 precedence: 2,
3904 },
3905 )
3906 .expect("precedence transition");
3907 let atn = finish_atn(atn);
3908 let transition = atn
3909 .state(0)
3910 .expect("source state")
3911 .transitions()
3912 .first()
3913 .expect("precedence transition");
3914 let mut simulator = ParserAtnSimulator::new(&atn);
3915 let config = AtnConfig::new(0, 1, EMPTY_CONTEXT, &simulator.store.contexts);
3916
3917 let sll_start = simulator
3918 .epsilon_target_config(&config, transition, transition.kind(), 1, true, false)
3919 .expect("sll start transition");
3920 assert!(matches!(
3921 sll_start.semantic_context(&simulator.store.semantic_contexts),
3922 SemanticContext::Precedence { precedence: 2 }
3923 ));
3924
3925 let full_context_start = simulator
3926 .epsilon_target_config(&config, transition, transition.kind(), 1, true, true)
3927 .expect("full-context start transition");
3928 assert!(
3929 full_context_start
3930 .semantic_context(&simulator.store.semantic_contexts)
3931 .is_none()
3932 );
3933
3934 let reach = simulator
3935 .epsilon_target_config(&config, transition, transition.kind(), 3, false, false)
3936 .expect("reach transition");
3937 assert!(
3938 reach
3939 .semantic_context(&simulator.store.semantic_contexts)
3940 .is_none()
3941 );
3942
3943 assert!(
3944 simulator
3945 .epsilon_target_config(&config, transition, transition.kind(), 3, true, false)
3946 .is_none()
3947 );
3948 }
3949
3950 #[test]
3951 fn closure_stops_collecting_predicates_after_action_edge() {
3952 let mut atn = ParserAtnBuilder::new(1);
3959 add_state(&mut atn, 0, AtnStateKind::Basic);
3960 add_state(&mut atn, 1, AtnStateKind::Basic);
3961 add_state(&mut atn, 2, AtnStateKind::Basic);
3962 add_state(&mut atn, 3, AtnStateKind::Basic);
3963 atn.add_transition(
3964 0,
3965 ParserTransitionSpec::Action {
3966 target: 1,
3967 rule_index: 0,
3968 action_index: Some(0),
3969 context_dependent: false,
3970 },
3971 )
3972 .expect("transition");
3973 atn.add_transition(
3974 1,
3975 ParserTransitionSpec::Predicate {
3976 target: 2,
3977 rule_index: 0,
3978 pred_index: 0,
3979 context_dependent: false,
3980 },
3981 )
3982 .expect("transition");
3983 atn.add_transition(
3984 2,
3985 ParserTransitionSpec::Atom {
3986 target: 3,
3987 label: 1,
3988 },
3989 )
3990 .expect("transition");
3991 atn.set_rule_to_start_state(vec![0])
3992 .expect("rule start states");
3993 atn.set_rule_to_stop_state(vec![3])
3994 .expect("rule stop states");
3995 let atn = finish_atn(atn);
3996
3997 let mut simulator = ParserAtnSimulator::new(&atn);
3998 let mut configs = AtnConfigSet::new();
3999 let mut merge_cache = PredictionWorkspace::default();
4000 let mut scratch = ClosureScratch::default();
4001 let config = AtnConfig::new(0, 1, EMPTY_CONTEXT, &simulator.store.contexts);
4002 simulator.closure(
4003 config,
4004 &mut configs,
4005 &mut merge_cache,
4006 &mut scratch,
4007 ClosureParams {
4008 precedence: 0,
4009 collect_predicates: true,
4010 treat_eof_as_epsilon: false,
4011 },
4012 );
4013
4014 let at_two = configs
4017 .configs()
4018 .iter()
4019 .find(|config| config.state == 2)
4020 .expect("config at state 2");
4021 assert!(
4022 at_two
4023 .semantic_context(&simulator.store.semantic_contexts)
4024 .is_none(),
4025 "predicate after an action edge must not be collected during prediction"
4026 );
4027
4028 let direct_config = AtnConfig::new(1, 1, EMPTY_CONTEXT, &simulator.store.contexts);
4032 let direct_transition = atn
4033 .state(1)
4034 .expect("predicate source")
4035 .transitions()
4036 .first()
4037 .expect("predicate transition");
4038 let direct = simulator
4039 .epsilon_target_config(
4040 &direct_config,
4041 direct_transition,
4042 direct_transition.kind(),
4043 0,
4044 true,
4045 false,
4046 )
4047 .expect("predicate transition");
4048 assert!(matches!(
4049 direct.semantic_context(&simulator.store.semantic_contexts),
4050 SemanticContext::Predicate { pred_index: 0, .. }
4051 ));
4052 }
4053
4054 #[test]
4055 fn reach_set_skips_closure_for_unique_intermediate_alt() {
4056 let mut atn = ParserAtnBuilder::new(1);
4057 add_state(&mut atn, 0, AtnStateKind::Basic);
4058 add_state(&mut atn, 1, AtnStateKind::Basic);
4059 add_state(&mut atn, 2, AtnStateKind::Basic);
4060 atn.add_transition(
4061 0,
4062 ParserTransitionSpec::Atom {
4063 target: 1,
4064 label: 7,
4065 },
4066 )
4067 .expect("transition");
4068 atn.add_transition(1, ParserTransitionSpec::Epsilon { target: 2 })
4069 .expect("transition");
4070 atn.set_rule_to_start_state(vec![0])
4071 .expect("rule start states");
4072 atn.set_rule_to_stop_state(vec![2])
4073 .expect("rule stop states");
4074 let atn = finish_atn(atn);
4075
4076 let mut simulator = ParserAtnSimulator::new(&atn);
4077 let mut configs = AtnConfigSet::new_full_context(false);
4078 let mut merge_cache = PredictionWorkspace::default();
4079 configs.add(
4080 AtnConfig::new(0, 1, EMPTY_CONTEXT, &simulator.store.contexts),
4081 &mut simulator.store.contexts,
4082 &mut merge_cache,
4083 );
4084
4085 let reach = simulator.compute_reach_set(&configs, 7, false, 0, &mut merge_cache);
4086
4087 assert_eq!(reach.len(), 1);
4088 assert_eq!(reach.configs()[0].state, 1);
4089 }
4090
4091 #[test]
4092 fn semantic_context_flag_is_scoped_to_predicted_alt() {
4093 let mut arena = ContextArena::new();
4094 let mut semantic_contexts = SemanticContextArena::new();
4095 let mut workspace = PredictionWorkspace::default();
4096 let mut configs = AtnConfigSet::new();
4097 configs.add(
4098 AtnConfig::new(1, 1, EMPTY_CONTEXT, &arena),
4099 &mut arena,
4100 &mut workspace,
4101 );
4102 configs.add(
4103 AtnConfig::new(2, 2, EMPTY_CONTEXT, &arena).with_semantic_context(
4104 SemanticContext::Predicate {
4105 rule_index: 0,
4106 pred_index: 0,
4107 context_dependent: false,
4108 },
4109 &mut semantic_contexts,
4110 ),
4111 &mut arena,
4112 &mut workspace,
4113 );
4114
4115 assert!(!configs_have_semantic_context_for_alt(&configs, 1));
4116 assert!(configs_have_semantic_context_for_alt(&configs, 2));
4117 }
4118
4119 #[test]
4120 fn adaptive_predict_prefers_non_greedy_exit_before_consuming() {
4121 let atn = non_greedy_optional_exit_first_atn();
4122 let mut simulator = ParserAtnSimulator::new(&atn);
4123
4124 assert_eq!(simulator.adaptive_predict(0, [1, TOKEN_EOF]), Ok(1));
4125 }
4126
4127 #[test]
4128 fn left_recursive_loop_entry_drop_requires_same_rule_return() {
4129 let atn = left_recursive_loop_entry_atn();
4130 let loop_entry = atn.state(1).expect("loop entry");
4131 let mut contexts = ContextArena::new();
4132 let same_rule_context = contexts.singleton(EMPTY_CONTEXT, 4);
4133 let other_rule_context = contexts.singleton(EMPTY_CONTEXT, 5);
4134
4135 assert!(can_drop_left_recursive_loop_entry_edge(
4136 &atn,
4137 loop_entry,
4138 &contexts,
4139 same_rule_context
4140 ));
4141 assert!(!can_drop_left_recursive_loop_entry_edge(
4142 &atn,
4143 loop_entry,
4144 &contexts,
4145 other_rule_context
4146 ));
4147 assert!(!can_drop_left_recursive_loop_entry_edge(
4148 &atn,
4149 loop_entry,
4150 &contexts,
4151 EMPTY_CONTEXT
4152 ));
4153 }
4154
4155 fn two_token_decision_atn() -> Atn {
4156 two_token_decision_atn_with_precedence(false)
4157 }
4158
4159 fn two_independent_decisions_atn() -> Atn {
4160 let mut atn = ParserAtnBuilder::new(3);
4161 add_two_token_decision_rule(&mut atn, 0, 0);
4162 add_two_token_decision_rule(&mut atn, 8, 1);
4163 atn.set_rule_to_start_state(vec![0, 8])
4164 .expect("rule start states");
4165 atn.set_rule_to_stop_state(vec![7, 15])
4166 .expect("rule stop states");
4167 finish_atn(atn)
4168 }
4169
4170 fn two_token_decision_atn_with_precedence(precedence: bool) -> Atn {
4171 let mut atn = ParserAtnBuilder::new(3);
4172 add_two_token_decision_rule(&mut atn, 0, 0);
4173 atn.set_rule_to_start_state(vec![0])
4174 .expect("rule start states");
4175 atn.set_rule_to_stop_state(vec![7])
4176 .expect("rule stop states");
4177 if precedence {
4178 atn.set_precedence_rule_decision(1)
4179 .expect("precedence decision state");
4180 }
4181 finish_atn(atn)
4182 }
4183
4184 fn add_two_token_decision_rule(atn: &mut ParserAtnBuilder, offset: usize, rule_index: usize) {
4185 assert_eq!(atn.state_count(), offset);
4186 for kind in [
4187 AtnStateKind::RuleStart,
4188 AtnStateKind::BlockStart,
4189 AtnStateKind::Basic,
4190 AtnStateKind::Basic,
4191 AtnStateKind::Basic,
4192 AtnStateKind::Basic,
4193 AtnStateKind::BlockEnd,
4194 AtnStateKind::RuleStop,
4195 ] {
4196 let expected = atn.state_count();
4197 assert_eq!(
4198 atn.add_state(kind, Some(rule_index))
4199 .expect("state")
4200 .index(),
4201 expected
4202 );
4203 }
4204 atn.add_decision_state(offset + 1).expect("decision state");
4205 atn.add_transition(offset, ParserTransitionSpec::Epsilon { target: offset + 1 })
4206 .expect("transition");
4207 atn.add_transition(
4208 offset + 1,
4209 ParserTransitionSpec::Epsilon { target: offset + 2 },
4210 )
4211 .expect("transition");
4212 atn.add_transition(
4213 offset + 1,
4214 ParserTransitionSpec::Epsilon { target: offset + 4 },
4215 )
4216 .expect("transition");
4217 atn.add_transition(
4218 offset + 2,
4219 ParserTransitionSpec::Atom {
4220 target: offset + 3,
4221 label: 1,
4222 },
4223 )
4224 .expect("transition");
4225 atn.add_transition(
4226 offset + 3,
4227 ParserTransitionSpec::Atom {
4228 target: offset + 6,
4229 label: 2,
4230 },
4231 )
4232 .expect("transition");
4233 atn.add_transition(
4234 offset + 4,
4235 ParserTransitionSpec::Atom {
4236 target: offset + 5,
4237 label: 1,
4238 },
4239 )
4240 .expect("transition");
4241 atn.add_transition(
4242 offset + 5,
4243 ParserTransitionSpec::Atom {
4244 target: offset + 6,
4245 label: 3,
4246 },
4247 )
4248 .expect("transition");
4249 atn.add_transition(
4250 offset + 6,
4251 ParserTransitionSpec::Epsilon { target: offset + 7 },
4252 )
4253 .expect("transition");
4254 }
4255
4256 fn optional_token_decision_atn() -> Atn {
4257 let mut atn = ParserAtnBuilder::new(1);
4258 add_state(&mut atn, 0, AtnStateKind::RuleStart);
4259 add_state(&mut atn, 1, AtnStateKind::BlockStart);
4260 add_state(&mut atn, 2, AtnStateKind::Basic);
4261 add_state(&mut atn, 3, AtnStateKind::BlockEnd);
4262 add_state(&mut atn, 4, AtnStateKind::RuleStop);
4263 atn.set_rule_to_start_state(vec![0])
4264 .expect("rule start states");
4265 atn.set_rule_to_stop_state(vec![4])
4266 .expect("rule stop states");
4267 atn.add_decision_state(1).expect("decision state");
4268 atn.add_transition(0, ParserTransitionSpec::Epsilon { target: 1 })
4269 .expect("transition");
4270 atn.add_transition(1, ParserTransitionSpec::Epsilon { target: 2 })
4271 .expect("transition");
4272 atn.add_transition(1, ParserTransitionSpec::Epsilon { target: 3 })
4273 .expect("transition");
4274 atn.add_transition(
4275 2,
4276 ParserTransitionSpec::Atom {
4277 target: 3,
4278 label: 1,
4279 },
4280 )
4281 .expect("transition");
4282 atn.add_transition(3, ParserTransitionSpec::Epsilon { target: 4 })
4283 .expect("transition");
4284 finish_atn(atn)
4285 }
4286
4287 fn non_greedy_optional_exit_first_atn() -> Atn {
4288 let mut atn = ParserAtnBuilder::new(1);
4289 add_state(&mut atn, 0, AtnStateKind::RuleStart);
4290 add_state(&mut atn, 1, AtnStateKind::BlockStart);
4291 add_state(&mut atn, 2, AtnStateKind::BlockEnd);
4292 add_state(&mut atn, 3, AtnStateKind::Basic);
4293 add_state(&mut atn, 4, AtnStateKind::RuleStop);
4294 atn.set_rule_to_start_state(vec![0])
4295 .expect("rule start states");
4296 atn.set_rule_to_stop_state(vec![4])
4297 .expect("rule stop states");
4298 atn.add_decision_state(1).expect("decision state");
4299 atn.set_non_greedy(1).expect("non-greedy state");
4300 atn.add_transition(0, ParserTransitionSpec::Epsilon { target: 1 })
4301 .expect("transition");
4302 atn.add_transition(1, ParserTransitionSpec::Epsilon { target: 2 })
4303 .expect("transition");
4304 atn.add_transition(1, ParserTransitionSpec::Epsilon { target: 3 })
4305 .expect("transition");
4306 atn.add_transition(2, ParserTransitionSpec::Epsilon { target: 4 })
4307 .expect("transition");
4308 atn.add_transition(
4309 3,
4310 ParserTransitionSpec::Atom {
4311 target: 4,
4312 label: 1,
4313 },
4314 )
4315 .expect("transition");
4316 finish_atn(atn)
4317 }
4318
4319 fn ambiguous_three_token_decision_atn() -> Atn {
4324 let mut atn = ParserAtnBuilder::new(3);
4325 add_state(&mut atn, 0, AtnStateKind::RuleStart);
4326 add_state(&mut atn, 1, AtnStateKind::BlockStart);
4327 add_state(&mut atn, 2, AtnStateKind::Basic);
4329 add_state(&mut atn, 3, AtnStateKind::Basic);
4330 add_state(&mut atn, 4, AtnStateKind::Basic);
4331 add_state(&mut atn, 5, AtnStateKind::Basic);
4332 add_state(&mut atn, 6, AtnStateKind::Basic);
4334 add_state(&mut atn, 7, AtnStateKind::Basic);
4335 add_state(&mut atn, 8, AtnStateKind::Basic);
4336 add_state(&mut atn, 9, AtnStateKind::Basic);
4337 add_state(&mut atn, 10, AtnStateKind::BlockEnd);
4338 add_state(&mut atn, 11, AtnStateKind::RuleStop);
4339 atn.set_rule_to_start_state(vec![0])
4340 .expect("rule start states");
4341 atn.set_rule_to_stop_state(vec![11])
4342 .expect("rule stop states");
4343 atn.add_decision_state(1).expect("decision state");
4344 atn.add_transition(0, ParserTransitionSpec::Epsilon { target: 1 })
4345 .expect("transition");
4346 atn.add_transition(1, ParserTransitionSpec::Epsilon { target: 2 })
4347 .expect("transition");
4348 atn.add_transition(1, ParserTransitionSpec::Epsilon { target: 6 })
4349 .expect("transition");
4350 for (source, target, label) in [
4351 (2, 3, 1),
4352 (3, 4, 2),
4353 (4, 5, 3),
4354 (6, 7, 1),
4355 (7, 8, 2),
4356 (8, 9, 3),
4357 ] {
4358 atn.add_transition(source, ParserTransitionSpec::Atom { target, label })
4359 .expect("transition");
4360 }
4361 atn.add_transition(5, ParserTransitionSpec::Epsilon { target: 10 })
4362 .expect("transition");
4363 atn.add_transition(9, ParserTransitionSpec::Epsilon { target: 10 })
4364 .expect("transition");
4365 atn.add_transition(10, ParserTransitionSpec::Epsilon { target: 11 })
4366 .expect("transition");
4367 finish_atn(atn)
4368 }
4369
4370 fn ambiguous_single_token_decision_atn() -> Atn {
4371 let mut atn = ParserAtnBuilder::new(1);
4372 add_state(&mut atn, 0, AtnStateKind::RuleStart);
4373 add_state(&mut atn, 1, AtnStateKind::BlockStart);
4374 add_state(&mut atn, 2, AtnStateKind::Basic);
4375 add_state(&mut atn, 3, AtnStateKind::Basic);
4376 add_state(&mut atn, 4, AtnStateKind::Basic);
4377 add_state(&mut atn, 5, AtnStateKind::Basic);
4378 add_state(&mut atn, 6, AtnStateKind::BlockEnd);
4379 add_state(&mut atn, 7, AtnStateKind::RuleStop);
4380 atn.set_rule_to_start_state(vec![0])
4381 .expect("rule start states");
4382 atn.set_rule_to_stop_state(vec![7])
4383 .expect("rule stop states");
4384 atn.add_decision_state(1).expect("decision state");
4385 atn.add_transition(0, ParserTransitionSpec::Epsilon { target: 1 })
4386 .expect("transition");
4387 atn.add_transition(1, ParserTransitionSpec::Epsilon { target: 2 })
4388 .expect("transition");
4389 atn.add_transition(1, ParserTransitionSpec::Epsilon { target: 4 })
4390 .expect("transition");
4391 atn.add_transition(
4392 2,
4393 ParserTransitionSpec::Atom {
4394 target: 3,
4395 label: 1,
4396 },
4397 )
4398 .expect("transition");
4399 atn.add_transition(3, ParserTransitionSpec::Epsilon { target: 6 })
4400 .expect("transition");
4401 atn.add_transition(
4402 4,
4403 ParserTransitionSpec::Atom {
4404 target: 5,
4405 label: 1,
4406 },
4407 )
4408 .expect("transition");
4409 atn.add_transition(5, ParserTransitionSpec::Epsilon { target: 6 })
4410 .expect("transition");
4411 atn.add_transition(6, ParserTransitionSpec::Epsilon { target: 7 })
4412 .expect("transition");
4413 finish_atn(atn)
4414 }
4415
4416 fn context_containment_decision_atn() -> Atn {
4420 context_containment_test_atn(None, ParserTransitionSpec::Epsilon { target: 7 })
4421 }
4422
4423 fn prefix_alt_decision_atn() -> Atn {
4424 let mut atn = ParserAtnBuilder::new(3);
4425 add_state(&mut atn, 0, AtnStateKind::BlockStart);
4426 add_state(&mut atn, 1, AtnStateKind::Basic);
4427 add_state(&mut atn, 2, AtnStateKind::RuleStop);
4428 atn.set_rule_to_start_state(vec![0])
4429 .expect("rule start states");
4430 atn.set_rule_to_stop_state(vec![2])
4431 .expect("rule stop states");
4432 atn.add_decision_state(0).expect("decision state");
4433 atn.add_transition(
4434 0,
4435 ParserTransitionSpec::Atom {
4436 target: 2,
4437 label: 1,
4438 },
4439 )
4440 .expect("transition");
4441 atn.add_transition(
4442 0,
4443 ParserTransitionSpec::Atom {
4444 target: 1,
4445 label: 1,
4446 },
4447 )
4448 .expect("transition");
4449 atn.add_transition(
4450 1,
4451 ParserTransitionSpec::Atom {
4452 target: 2,
4453 label: 2,
4454 },
4455 )
4456 .expect("transition");
4457 finish_atn(atn)
4458 }
4459
4460 fn three_token_prefix_alt_decision_atn() -> Atn {
4461 let mut atn = ParserAtnBuilder::new(2);
4462 for (state_number, kind) in [
4463 (0, AtnStateKind::BlockStart),
4464 (1, AtnStateKind::Basic),
4465 (2, AtnStateKind::Basic),
4466 (3, AtnStateKind::Basic),
4467 (4, AtnStateKind::Basic),
4468 (5, AtnStateKind::Basic),
4469 (6, AtnStateKind::RuleStop),
4470 ] {
4471 add_state(&mut atn, state_number, kind);
4472 }
4473 atn.set_rule_to_start_state(vec![0])
4474 .expect("rule start states");
4475 atn.set_rule_to_stop_state(vec![6])
4476 .expect("rule stop states");
4477 atn.add_decision_state(0).expect("decision state");
4478 atn.add_transition(0, ParserTransitionSpec::Epsilon { target: 1 })
4479 .expect("transition");
4480 atn.add_transition(0, ParserTransitionSpec::Epsilon { target: 2 })
4481 .expect("transition");
4482 atn.add_transition(
4483 1,
4484 ParserTransitionSpec::Atom {
4485 target: 6,
4486 label: 1,
4487 },
4488 )
4489 .expect("transition");
4490 atn.add_transition(
4491 2,
4492 ParserTransitionSpec::Atom {
4493 target: 3,
4494 label: 1,
4495 },
4496 )
4497 .expect("transition");
4498 atn.add_transition(
4499 3,
4500 ParserTransitionSpec::Atom {
4501 target: 4,
4502 label: 2,
4503 },
4504 )
4505 .expect("transition");
4506 atn.add_transition(
4507 4,
4508 ParserTransitionSpec::Atom {
4509 target: 5,
4510 label: 1,
4511 },
4512 )
4513 .expect("transition");
4514 atn.add_transition(5, ParserTransitionSpec::Epsilon { target: 6 })
4515 .expect("transition");
4516 finish_atn(atn)
4517 }
4518
4519 fn multiple_eof_decision_atn() -> Atn {
4520 let mut atn = ParserAtnBuilder::new(2);
4521 for state_number in 0..=10 {
4522 let kind = match state_number {
4523 0 => AtnStateKind::RuleStart,
4524 1 => AtnStateKind::BlockStart,
4525 7 => AtnStateKind::BlockEnd,
4526 10 => AtnStateKind::RuleStop,
4527 _ => AtnStateKind::Basic,
4528 };
4529 add_state(&mut atn, state_number, kind);
4530 }
4531 atn.set_rule_to_start_state(vec![0])
4532 .expect("rule start states");
4533 atn.set_rule_to_stop_state(vec![10])
4534 .expect("rule stop states");
4535 atn.add_decision_state(1).expect("decision state");
4536 atn.add_transition(0, ParserTransitionSpec::Epsilon { target: 1 })
4537 .expect("transition");
4538 atn.add_transition(1, ParserTransitionSpec::Epsilon { target: 2 })
4539 .expect("transition");
4540 atn.add_transition(1, ParserTransitionSpec::Epsilon { target: 4 })
4541 .expect("transition");
4542 atn.add_transition(
4543 2,
4544 ParserTransitionSpec::Atom {
4545 target: 3,
4546 label: 1,
4547 },
4548 )
4549 .expect("transition");
4550 atn.add_transition(3, ParserTransitionSpec::Epsilon { target: 7 })
4551 .expect("transition");
4552 atn.add_transition(
4553 4,
4554 ParserTransitionSpec::Atom {
4555 target: 5,
4556 label: 1,
4557 },
4558 )
4559 .expect("transition");
4560 atn.add_transition(
4561 5,
4562 ParserTransitionSpec::Atom {
4563 target: 6,
4564 label: 2,
4565 },
4566 )
4567 .expect("transition");
4568 atn.add_transition(6, ParserTransitionSpec::Epsilon { target: 7 })
4569 .expect("transition");
4570 atn.add_transition(7, ParserTransitionSpec::Epsilon { target: 8 })
4571 .expect("transition");
4572 atn.add_transition(
4573 8,
4574 ParserTransitionSpec::Atom {
4575 target: 9,
4576 label: TOKEN_EOF,
4577 },
4578 )
4579 .expect("transition");
4580 atn.add_transition(
4581 9,
4582 ParserTransitionSpec::Atom {
4583 target: 10,
4584 label: TOKEN_EOF,
4585 },
4586 )
4587 .expect("transition");
4588 finish_atn(atn)
4589 }
4590
4591 fn left_recursive_loop_entry_atn() -> Atn {
4592 let mut atn = ParserAtnBuilder::new(1);
4593 add_state(&mut atn, 0, AtnStateKind::RuleStart);
4594 add_state(&mut atn, 1, AtnStateKind::StarLoopEntry);
4595 add_state(&mut atn, 2, AtnStateKind::BlockStart);
4596 add_state(&mut atn, 3, AtnStateKind::BlockEnd);
4597 add_state(&mut atn, 4, AtnStateKind::Basic);
4598 assert_eq!(
4599 atn.add_state(AtnStateKind::Basic, Some(1))
4600 .expect("state")
4601 .index(),
4602 5
4603 );
4604 add_state(&mut atn, 6, AtnStateKind::LoopEnd);
4605 add_state(&mut atn, 7, AtnStateKind::RuleStop);
4606 atn.set_rule_to_start_state(vec![0, 5])
4607 .expect("rule start states");
4608 atn.set_rule_to_stop_state(vec![7, 7])
4609 .expect("rule stop states");
4610 atn.set_precedence_rule_decision(1)
4611 .expect("precedence decision state");
4612 atn.set_end_state(2, 3).expect("block end state");
4613 atn.add_transition(1, ParserTransitionSpec::Epsilon { target: 2 })
4614 .expect("transition");
4615 atn.add_transition(1, ParserTransitionSpec::Epsilon { target: 6 })
4616 .expect("transition");
4617 atn.add_transition(4, ParserTransitionSpec::Epsilon { target: 3 })
4618 .expect("transition");
4619 atn.add_transition(5, ParserTransitionSpec::Epsilon { target: 3 })
4620 .expect("transition");
4621 finish_atn(atn)
4622 }
4623
4624 fn add_state(atn: &mut ParserAtnBuilder, state_number: usize, kind: AtnStateKind) {
4625 assert_eq!(
4626 atn.add_state(kind, Some(0)).expect("state").index(),
4627 state_number
4628 );
4629 }
4630
4631 #[derive(Debug)]
4632 struct VecIntStream {
4633 symbols: Vec<i32>,
4634 index: usize,
4635 }
4636
4637 impl VecIntStream {
4638 fn new(symbols: Vec<i32>) -> Self {
4639 Self { symbols, index: 0 }
4640 }
4641 }
4642
4643 impl IntStream for VecIntStream {
4644 fn consume(&mut self) {
4645 if self.la(1) != TOKEN_EOF {
4646 self.index += 1;
4647 }
4648 }
4649
4650 fn la(&mut self, offset: isize) -> i32 {
4651 if offset <= 0 {
4652 return 0;
4653 }
4654 let offset = offset.cast_unsigned() - 1;
4655 self.symbols
4656 .get(self.index + offset)
4657 .copied()
4658 .unwrap_or(TOKEN_EOF)
4659 }
4660
4661 fn index(&self) -> usize {
4662 self.index
4663 }
4664
4665 fn seek(&mut self, index: usize) {
4666 self.index = index;
4667 }
4668
4669 fn size(&self) -> usize {
4670 self.symbols.len()
4671 }
4672 }
4673}