Skip to main content

antlr4_runtime/atn/
parser.rs

1use crate::atn::AtnStateKind;
2use crate::atn::parser_atn::{
3    ParserAtn as Atn, ParserAtnState as AtnState, ParserTransition, ParserTransitionKind,
4};
5#[cfg(test)]
6use crate::atn::parser_atn::{ParserAtnBuilder, ParserTransitionSpec};
7use crate::dfa::{
8    DfaStateBuilder, DfaStateId, NO_DFA_STATE, ParserDfa, ParserDfaStateView, ParserDfaStats,
9};
10use crate::int_stream::IntStream;
11use crate::prediction::{
12    AtnConfig, AtnConfigSet, ContextArena, ContextId, EMPTY_CONTEXT, EMPTY_RETURN_STATE,
13    PredictionContextStats, PredictionFxHasher, PredictionWorkspace, SemanticContext,
14    all_subsets_conflict, all_subsets_equal, conflicting_alt_subsets,
15    has_sll_conflict_terminating_prediction, single_viable_alt,
16};
17use crate::token::TOKEN_EOF;
18use std::cell::RefCell;
19use std::collections::{HashMap, HashSet};
20use std::hash::BuildHasherDefault;
21
22type FxHashSet<T> = HashSet<T, BuildHasherDefault<PredictionFxHasher>>;
23
24#[derive(Debug)]
25pub struct ParserAtnSimulator<'a> {
26    atn: &'a Atn,
27    store: PredictionStore,
28    workspace: PredictionWorkspace,
29    outer_context_cache: Option<CachedOuterContext>,
30    outer_context_cache_hits: usize,
31    outer_context_cache_misses: usize,
32    /// Accept states treated as provisional by the latest direct prediction.
33    /// Generated SLL still uses their stored accept metadata.
34    deferred_accept_states: FxHashSet<(usize, DfaStateId)>,
35    shared_cache_key: Option<usize>,
36    shared_cache_generation: u64,
37    /// Java's `LL_EXACT_AMBIG_DETECTION`: the full-context loop keeps
38    /// consuming past "resolves to one viable alt" conflicts until every
39    /// `(state, context)` subset conflicts over the same alt set.
40    exact_ambig_detection: bool,
41}
42
43#[derive(Clone, Copy, Debug)]
44struct CachedOuterContext {
45    rule_context_version: usize,
46    context: ContextId,
47}
48
49#[derive(Debug, Default)]
50struct PredictionStore {
51    contexts: ContextArena,
52    decision_to_dfa: Vec<ParserDfa>,
53}
54
55impl PredictionStore {
56    fn new(atn: &Atn) -> Self {
57        Self {
58            contexts: ContextArena::new(),
59            decision_to_dfa: initial_decision_dfas(atn),
60        }
61    }
62}
63
64#[derive(Debug, Default)]
65struct SharedPredictionStore {
66    generation: u64,
67    store: Option<PredictionStore>,
68}
69
70thread_local! {
71    static SHARED_PREDICTION_STORES: RefCell<HashMap<usize, SharedPredictionStore>> =
72        RefCell::new(HashMap::new());
73}
74
75fn clear_shared_prediction_store(key: usize) -> u64 {
76    SHARED_PREDICTION_STORES.with(|cache| {
77        let mut cache = cache.borrow_mut();
78        let shared = cache.entry(key).or_default();
79        shared.generation = shared.generation.wrapping_add(1);
80        shared.store = None;
81        shared.generation
82    })
83}
84
85#[derive(Clone, Debug, Eq, PartialEq)]
86pub struct ParserAtnPrediction {
87    pub alt: usize,
88    pub requires_full_context: bool,
89    pub has_semantic_context: bool,
90    pub diagnostic: Option<ParserAtnPredictionDiagnostic>,
91}
92
93#[derive(Clone, Debug, Eq, PartialEq)]
94pub struct ParserAtnPredictionDiagnostic {
95    pub kind: ParserAtnPredictionDiagnosticKind,
96    pub start_index: usize,
97    pub sll_stop_index: usize,
98    pub ll_stop_index: usize,
99    pub conflicting_alts: Vec<usize>,
100    /// For [`ParserAtnPredictionDiagnosticKind::Ambiguity`]: whether the
101    /// full-context loop proved an exact ambiguity (Java's `exact` flag —
102    /// the default `DiagnosticErrorListener` only reports exact ones).
103    pub exact: bool,
104}
105
106#[derive(Clone, Copy, Debug, Eq, PartialEq)]
107pub enum ParserAtnPredictionDiagnosticKind {
108    Ambiguity,
109    ContextSensitivity,
110}
111
112#[derive(Clone, Copy)]
113struct PredictionCheck {
114    decision: usize,
115    decision_state: usize,
116    state_number: DfaStateId,
117    start_index: usize,
118    precedence: i32,
119    outer_context: ContextId,
120    force_full_context_retry: bool,
121    sll_probe_only: bool,
122}
123
124#[derive(Clone, Copy)]
125struct AdaptivePredictRequest {
126    decision: usize,
127    precedence: usize,
128    outer_context: ContextId,
129    force_full_context_retry: bool,
130    /// When set, the SLL walk stops at the first full-context-requiring conflict
131    /// and returns the SLL prediction (carrying `requires_full_context = true`)
132    /// WITHOUT running the expensive full-context LL loop. The generated
133    /// two-stage prediction uses only that boolean to decide whether to re-run
134    /// with the real outer context, so the empty-context LL pass this skips is
135    /// discarded work. Mirrors Go's execATN, which returns "needs LL" from the
136    /// SLL stage rather than computing LL twice.
137    sll_probe_only: bool,
138}
139
140#[derive(Clone, Copy)]
141struct DfaEdge {
142    decision: usize,
143    source_state: DfaStateId,
144}
145
146#[derive(Clone, Debug)]
147struct PreviousGoodAlt {
148    alt: usize,
149    configs: Vec<AtnConfig>,
150}
151
152#[derive(Clone, Debug, Eq, PartialEq)]
153struct DfaPredictionInfo {
154    prediction: ParserAtnPrediction,
155    conflicting_alts: Vec<usize>,
156}
157
158#[derive(Clone, Debug, Eq, PartialEq)]
159struct FullContextPrediction {
160    prediction: ParserAtnPrediction,
161    stop_index: usize,
162    resolution: FullContextResolution,
163}
164
165/// How the full-context loop settled, mirroring the two exits of Java's
166/// `execATNWithFullContext`: a truly unique alt (reported as context
167/// sensitivity) or a conflict resolution (reported as ambiguity, exact or
168/// not).
169#[derive(Clone, Debug, Eq, PartialEq)]
170enum FullContextResolution {
171    Unique,
172    Ambiguous { exact: bool, alts: Vec<usize> },
173}
174
175fn full_context_prediction(
176    alt: usize,
177    configs: &AtnConfigSet,
178    stop_index: usize,
179    resolution: FullContextResolution,
180) -> FullContextPrediction {
181    FullContextPrediction {
182        prediction: ParserAtnPrediction {
183            alt,
184            requires_full_context: true,
185            has_semantic_context: configs_have_semantic_context_for_alt(configs, alt),
186            diagnostic: None,
187        },
188        stop_index,
189        resolution,
190    }
191}
192
193#[derive(Clone, Debug, Eq, Hash, PartialEq)]
194struct ClosureConfigKey {
195    state: usize,
196    alt: usize,
197    context: ContextId,
198    semantic_context: SemanticContext,
199    precedence_filter_suppressed: bool,
200}
201
202impl From<&AtnConfig> for ClosureConfigKey {
203    fn from(config: &AtnConfig) -> Self {
204        Self {
205            state: config.state,
206            alt: config.alt,
207            context: config.context,
208            semantic_context: config.semantic_context.clone(),
209            precedence_filter_suppressed: config.precedence_filter_suppressed,
210        }
211    }
212}
213
214/// Reusable scratch buffers for `closure`. ANTLR's reference runtimes allocate a
215/// fresh work stack and "closure busy" visited set per `closure` call (millions
216/// of allocations on large parses); reusing one buffer across the per-config
217/// calls of a single reach/start-state computation removes that churn. Each
218/// `closure` call clears the buffers first, so the visited scope stays per-call
219/// — behaviour-identical to allocating fresh sets.
220#[derive(Default)]
221struct ClosureScratch {
222    /// Work stack of `(config, collect_predicates)`. The per-config
223    /// `collect_predicates` flag mirrors ANTLR's
224    /// `continueCollecting = collectPredicates && !ActionTransition`: once an
225    /// action edge is crossed, predicates on the far side are NOT collected into
226    /// the config's semantic context, so they are deferred to parse time rather
227    /// than evaluated during prediction (the "action hides predicates" rule).
228    stack: Vec<(AtnConfig, bool)>,
229    visited: FxHashSet<ClosureConfigKey>,
230}
231
232/// Per-closure-tree invariants, grouped so `closure` stays within Clippy's
233/// argument-count budget while threading the reusable [`ClosureScratch`].
234#[derive(Clone, Copy)]
235struct ClosureParams {
236    precedence: i32,
237    collect_predicates: bool,
238    treat_eof_as_epsilon: bool,
239}
240
241#[derive(Debug)]
242struct LookaheadIntStream {
243    symbols: Vec<i32>,
244    index: usize,
245}
246
247impl LookaheadIntStream {
248    const fn new(symbols: Vec<i32>) -> Self {
249        Self { symbols, index: 0 }
250    }
251}
252
253impl IntStream for LookaheadIntStream {
254    fn consume(&mut self) {
255        if self.la(1) != TOKEN_EOF {
256            self.index += 1;
257        }
258    }
259
260    fn la(&mut self, offset: isize) -> i32 {
261        if offset <= 0 {
262            return 0;
263        }
264        let offset = offset.cast_unsigned() - 1;
265        self.symbols
266            .get(self.index + offset)
267            .copied()
268            .unwrap_or(TOKEN_EOF)
269    }
270
271    fn index(&self) -> usize {
272        self.index
273    }
274
275    fn seek(&mut self, index: usize) {
276        self.index = index.min(self.symbols.len());
277    }
278
279    fn size(&self) -> usize {
280        self.symbols.len()
281    }
282}
283
284fn initial_decision_dfas(atn: &Atn) -> Vec<ParserDfa> {
285    atn.decision_to_state()
286        .iter()
287        .enumerate()
288        .map(|(decision, state)| {
289            let mut dfa = ParserDfa::with_max_token_type(state, decision, atn.max_token_type());
290            if atn
291                .state(state)
292                .is_some_and(AtnState::precedence_rule_decision)
293            {
294                dfa.set_precedence_dfa(true);
295            }
296            dfa
297        })
298        .collect()
299}
300
301/// Merges a dropping simulator's DFAs into tables that another simulator
302/// checked in first, losslessly. The two evolved independently (the
303/// later-constructed one started cold), so numeric state ids are not
304/// comparable — but DFA states ARE comparable by their ATN config set, the
305/// same identity `ParserDfa::add_state` dedups on. Re-keying `local`'s states into
306/// `shared`'s numbering and unioning edges/starts means overlapping
307/// simulators never lose learned coverage, however it is distributed.
308/// Walking every state is fine here: this only runs on the rare
309/// overlapping-simulators drop path.
310fn union_decision_dfas(shared: &mut Vec<ParserDfa>, local: Vec<ParserDfa>) {
311    if shared.len() != local.len() {
312        *shared = local;
313        return;
314    }
315    for (shared_dfa, local_dfa) in shared.iter_mut().zip(local) {
316        union_decision_dfa(shared_dfa, local_dfa);
317    }
318}
319
320fn union_prediction_stores(
321    shared: &mut PredictionStore,
322    mut local: PredictionStore,
323    workspace: &mut PredictionWorkspace,
324) {
325    let remap = shared.contexts.import_all(&local.contexts, workspace);
326    for dfa in &mut local.decision_to_dfa {
327        dfa.remap_contexts(&remap, &shared.contexts);
328    }
329    union_decision_dfas(&mut shared.decision_to_dfa, local.decision_to_dfa);
330}
331
332fn union_decision_dfa(shared: &mut ParserDfa, local: ParserDfa) {
333    if shared.is_precedence_dfa() != local.is_precedence_dfa() {
334        // A mode flip resets the tables (`set_precedence_dfa`), so the two are
335        // not unionable; keep whichever learned more states.
336        if local.state_count() > shared.state_count() {
337            *shared = local;
338        }
339        return;
340    }
341    // Pass 1: map every local state number to a shared state number by
342    // config-set identity, inserting the states shared has not learned.
343    // Their edges reference local numbering, so they are cleared here and
344    // re-added in pass 2 under the shared numbering.
345    let mut renumber = Vec::with_capacity(local.state_count());
346    for state in local.states() {
347        let configs = local.configs(state.id());
348        let number = shared.state_id_for_configs(configs).unwrap_or_else(|| {
349            let missing = local.clone_state_without_edges(state.id());
350            shared.insert_state(missing)
351        });
352        renumber.push(number);
353    }
354    // Pass 2: union edges, translating targets into shared numbering. The
355    // incumbent's entries win; only gaps are filled. Accept metadata needs no
356    // reconciliation: it is a pure function of the config set, and equal
357    // config sets produced it through the same accept-time computation.
358    for state in local.states() {
359        let mapped = renumber[state.id().index()];
360        for transition in state.transitions() {
361            let Some(&mapped_target) = renumber.get(transition.target.index()) else {
362                continue;
363            };
364            if shared.edge(mapped, transition.symbol).is_none() {
365                shared.add_edge(mapped, transition.symbol, mapped_target);
366            }
367        }
368    }
369    if shared.start_state().is_none()
370        && let Some(start) = local.start_state()
371        && let Some(&mapped) = renumber.get(start.index())
372    {
373        shared.set_start_state(mapped);
374    }
375    for (precedence, start) in local.precedence_start_states().iter().copied().enumerate() {
376        if start == NO_DFA_STATE {
377            continue;
378        }
379        if shared.precedence_start_state(precedence).is_none()
380            && let Some(&mapped) = renumber.get(start.index())
381        {
382            shared.set_precedence_start_state(precedence, mapped);
383        }
384    }
385}
386
387impl Drop for ParserAtnSimulator<'_> {
388    fn drop(&mut self) {
389        let Some(key) = self.shared_cache_key else {
390            return;
391        };
392        #[cfg(feature = "perf-counters")]
393        let publication_started = std::time::Instant::now();
394        #[cfg(feature = "perf-counters")]
395        let published_states = self
396            .store
397            .decision_to_dfa
398            .iter()
399            .map(ParserDfa::state_count)
400            .sum();
401        // Check the DFAs back IN by move. The slot is normally vacant because
402        // `new_shared` checked them out; it is occupied only when another
403        // simulator for the same ATN was created while this one was alive
404        // (that one started cold and checked its copy in first) — then union
405        // the two by config-set identity so neither side's learning is lost.
406        let store = std::mem::take(&mut self.store);
407        let published = SHARED_PREDICTION_STORES.with(|cache| {
408            let mut cache = cache.borrow_mut();
409            let shared = cache.entry(key).or_default();
410            if shared.generation != self.shared_cache_generation {
411                return false;
412            }
413            if let Some(shared_store) = shared.store.as_mut() {
414                union_prediction_stores(shared_store, store, &mut self.workspace);
415            } else {
416                shared.store = Some(store);
417            }
418            true
419        });
420        #[cfg(feature = "perf-counters")]
421        if published {
422            crate::perf::record_dfa_cache_publication(
423                publication_started.elapsed().as_nanos(),
424                published_states,
425            );
426        }
427        #[cfg(not(feature = "perf-counters"))]
428        let _ = published;
429    }
430}
431
432impl<'a> ParserAtnSimulator<'a> {
433    pub fn new(atn: &'a Atn) -> Self {
434        Self {
435            atn,
436            store: PredictionStore::new(atn),
437            workspace: PredictionWorkspace::default(),
438            outer_context_cache: None,
439            outer_context_cache_hits: 0,
440            outer_context_cache_misses: 0,
441            deferred_accept_states: FxHashSet::default(),
442            shared_cache_key: None,
443            shared_cache_generation: 0,
444            exact_ambig_detection: false,
445        }
446    }
447
448    /// Resets transient simulator state while retaining learned decision DFAs.
449    pub fn reset(&mut self) {
450        self.outer_context_cache = None;
451        self.deferred_accept_states.clear();
452        self.workspace.reset();
453    }
454
455    /// Clears this simulator's learned decision DFAs.
456    ///
457    /// Shared simulators also invalidate the thread-local cache generation so
458    /// an overlapping stale simulator cannot republish pre-clear states later.
459    pub fn clear_dfa(&mut self) {
460        self.store = PredictionStore::new(self.atn);
461        self.reset();
462        if let Some(key) = self.shared_cache_key {
463            self.shared_cache_generation = clear_shared_prediction_store(key);
464        }
465    }
466
467    /// Clears the thread-local learned DFA store for a generated parser ATN.
468    pub fn clear_shared_dfa(atn: &'static Atn) {
469        let ptr: *const Atn = atn;
470        clear_shared_prediction_store(ptr as usize);
471    }
472
473    /// Switches the full-context resolution strategy (Java's
474    /// `LL_EXACT_AMBIG_DETECTION` versus plain `LL`).
475    pub const fn set_exact_ambig_detection(&mut self, exact: bool) {
476        self.exact_ambig_detection = exact;
477    }
478
479    /// Creates a simulator that starts from, and publishes back into, a
480    /// thread-local DFA cache keyed by a generated parser's static ATN.
481    ///
482    /// Generated parsers usually create a fresh parser object per parse. Without
483    /// this cache every parse relearns the same adaptive DFA; with it, later
484    /// parser instances reuse the SLL cache learned by earlier instances while
485    /// still keeping mutable simulator state local to the parser during a parse.
486    ///
487    /// The DFAs are checked OUT of the cache by move (and back in on drop):
488    /// cloning a warm DFA per parser instance costs O(learned states) — ~10%
489    /// of a small parse. A second simulator created for the same ATN while one
490    /// is alive finds the slot empty and starts cold; the drop-time check-in
491    /// then remaps its context IDs and unions both independently learned stores.
492    /// Renders every non-empty learned decision DFA in the format of Java's
493    /// `Parser.dumpDFA()` / `DFASerializer` — `Decision N:` headers followed
494    /// by `s0-'else'->:s1^=>1` edge lines — which the runtime testsuite's
495    /// `showDFA` descriptors byte-compare.
496    pub fn dump_dfa_java_style(&self, vocabulary: &crate::vocabulary::Vocabulary) -> String {
497        use std::fmt::Write as _;
498        let mut out = String::new();
499        let mut seen_one = false;
500        for dfa in &self.store.decision_to_dfa {
501            if dfa.is_empty() {
502                continue;
503            }
504            if seen_one {
505                out.push('\n');
506            }
507            seen_one = true;
508            let _ = writeln!(out, "Decision {}:", dfa.decision());
509            for state in dfa.states() {
510                let source = dfa_state_display(
511                    state,
512                    self.deferred_accept_states
513                        .contains(&(dfa.decision(), state.id())),
514                );
515                for transition in state.transitions() {
516                    let Some(target_state) = dfa.state(transition.target) else {
517                        continue;
518                    };
519                    let label = vocabulary.display_name(transition.symbol);
520                    let target = dfa_state_display(
521                        target_state,
522                        self.deferred_accept_states
523                            .contains(&(dfa.decision(), target_state.id())),
524                    );
525                    let _ = writeln!(out, "{source}-{label}->{target}");
526                }
527            }
528        }
529        out
530    }
531
532    pub fn new_shared(atn: &'static Atn) -> Self {
533        let ptr: *const Atn = atn;
534        let key = ptr as usize;
535        #[cfg(feature = "perf-counters")]
536        let import_started = std::time::Instant::now();
537        let (store, generation) = SHARED_PREDICTION_STORES.with(|cache| {
538            let mut cache = cache.borrow_mut();
539            let shared = cache.entry(key).or_default();
540            (
541                shared
542                    .store
543                    .take()
544                    .unwrap_or_else(|| PredictionStore::new(atn)),
545                shared.generation,
546            )
547        });
548        #[cfg(feature = "perf-counters")]
549        crate::perf::record_dfa_cache_import(
550            import_started.elapsed().as_nanos(),
551            store
552                .decision_to_dfa
553                .iter()
554                .map(ParserDfa::state_count)
555                .sum(),
556        );
557        Self {
558            atn,
559            store,
560            workspace: PredictionWorkspace::default(),
561            outer_context_cache: None,
562            outer_context_cache_hits: 0,
563            outer_context_cache_misses: 0,
564            deferred_accept_states: FxHashSet::default(),
565            shared_cache_key: Some(key),
566            shared_cache_generation: generation,
567            exact_ambig_detection: false,
568        }
569    }
570
571    pub fn decision_dfas(&self) -> &[ParserDfa] {
572        &self.store.decision_to_dfa
573    }
574
575    /// Returns aggregate learned parser-DFA storage and interning measurements.
576    pub fn parser_dfa_stats(&self) -> ParserDfaStats {
577        let mut stats = ParserDfaStats::default();
578        for dfa in &self.store.decision_to_dfa {
579            stats.add_assign(dfa.stats());
580        }
581        stats
582    }
583
584    /// Returns compact prediction-context allocation and interning totals for
585    /// this simulator's learned store.
586    pub fn prediction_context_stats(&self) -> PredictionContextStats {
587        let mut stats = self.store.contexts.stats();
588        stats.retained_bytes += self.workspace.retained_bytes();
589        stats.workspace_merge_cache_entries = self.workspace.merge_cache_len();
590        stats.workspace_merge_cache_capacity = self.workspace.merge_cache_capacity();
591        stats.workspace_entry_capacity = self.workspace.entry_capacity();
592        stats.outer_context_cache_hits = self.outer_context_cache_hits;
593        stats.outer_context_cache_misses = self.outer_context_cache_misses;
594        stats
595    }
596
597    /// Interns a generated parser's outer call stack in this simulator's
598    /// context arena. Return states must be supplied outermost to innermost,
599    /// and `rule_context_version` must change whenever that stack changes.
600    pub fn intern_prediction_context(
601        &mut self,
602        rule_context_version: usize,
603        return_states: impl IntoIterator<Item = usize>,
604    ) -> ContextId {
605        if let Some(cached) = self.outer_context_cache
606            && cached.rule_context_version == rule_context_version
607        {
608            self.outer_context_cache_hits = self.outer_context_cache_hits.saturating_add(1);
609            return cached.context;
610        }
611        self.outer_context_cache_misses = self.outer_context_cache_misses.saturating_add(1);
612        let mut context = EMPTY_CONTEXT;
613        for return_state in return_states {
614            context = self.store.contexts.singleton(context, return_state);
615        }
616        self.outer_context_cache = Some(CachedOuterContext {
617            rule_context_version,
618            context,
619        });
620        context
621    }
622
623    pub fn adaptive_predict(
624        &mut self,
625        decision: usize,
626        lookahead: impl IntoIterator<Item = i32>,
627    ) -> Result<usize, ParserAtnSimulatorError> {
628        self.adaptive_predict_with_precedence(decision, 0, lookahead)
629    }
630
631    pub fn adaptive_predict_stream<T: IntStream>(
632        &mut self,
633        decision: usize,
634        input: &mut T,
635    ) -> Result<usize, ParserAtnSimulatorError> {
636        self.adaptive_predict_stream_with_precedence(decision, 0, input)
637    }
638
639    pub fn adaptive_predict_stream_with_precedence<T: IntStream>(
640        &mut self,
641        decision: usize,
642        precedence: usize,
643        input: &mut T,
644    ) -> Result<usize, ParserAtnSimulatorError> {
645        self.adaptive_predict_stream_info_with_precedence(decision, precedence, input)
646            .map(|prediction| prediction.alt)
647    }
648
649    pub fn adaptive_predict_stream_info_with_precedence<T: IntStream>(
650        &mut self,
651        decision: usize,
652        precedence: usize,
653        input: &mut T,
654    ) -> Result<ParserAtnPrediction, ParserAtnSimulatorError> {
655        let marker = input.mark();
656        let index = input.index();
657        let mut workspace = std::mem::take(&mut self.workspace);
658        workspace.reset();
659        let result = self.adaptive_predict_stream_inner(
660            AdaptivePredictRequest {
661                decision,
662                precedence,
663                outer_context: EMPTY_CONTEXT,
664                force_full_context_retry: false,
665                sll_probe_only: false,
666            },
667            input,
668            &mut workspace,
669        );
670        self.workspace = workspace;
671        input.seek(index);
672        input.release(marker);
673        result
674    }
675
676    /// SLL-probe variant of [`Self::adaptive_predict_stream_info_with_precedence`].
677    ///
678    /// Identical to the precedence entry except that, when the SLL walk reaches
679    /// a conflict state requiring full context, it returns the SLL prediction
680    /// (carrying `requires_full_context = true`) WITHOUT running the
681    /// full-context LL loop. The generated two-stage prediction calls this for
682    /// stage 1 and only consults `requires_full_context` to decide whether to
683    /// re-run with the real outer context, so the empty-context LL pass this
684    /// skips would be discarded anyway. Avoids the double LL pass per escalation.
685    pub fn adaptive_predict_stream_info_sll_probe<T: IntStream>(
686        &mut self,
687        decision: usize,
688        precedence: usize,
689        input: &mut T,
690    ) -> Result<ParserAtnPrediction, ParserAtnSimulatorError> {
691        let marker = input.mark();
692        let index = input.index();
693        let mut workspace = std::mem::take(&mut self.workspace);
694        workspace.reset();
695        let result = self.adaptive_predict_stream_inner(
696            AdaptivePredictRequest {
697                decision,
698                precedence,
699                outer_context: EMPTY_CONTEXT,
700                force_full_context_retry: false,
701                sll_probe_only: true,
702            },
703            input,
704            &mut workspace,
705        );
706        self.workspace = workspace;
707        input.seek(index);
708        input.release(marker);
709        result
710    }
711
712    pub fn adaptive_predict_stream_info_with_context<T: IntStream>(
713        &mut self,
714        decision: usize,
715        precedence: usize,
716        input: &mut T,
717        outer_context: ContextId,
718    ) -> Result<ParserAtnPrediction, ParserAtnSimulatorError> {
719        self.store.contexts.assert_valid(outer_context);
720        let marker = input.mark();
721        let index = input.index();
722        let mut workspace = std::mem::take(&mut self.workspace);
723        workspace.reset();
724        let result = self.adaptive_predict_stream_inner(
725            AdaptivePredictRequest {
726                decision,
727                precedence,
728                outer_context,
729                force_full_context_retry: true,
730                sll_probe_only: false,
731            },
732            input,
733            &mut workspace,
734        );
735        self.workspace = workspace;
736        input.seek(index);
737        input.release(marker);
738        result
739    }
740
741    pub fn adaptive_predict_with_precedence(
742        &mut self,
743        decision: usize,
744        precedence: usize,
745        lookahead: impl IntoIterator<Item = i32>,
746    ) -> Result<usize, ParserAtnSimulatorError> {
747        self.adaptive_predict_info_with_precedence(decision, precedence, lookahead)
748            .map(|prediction| prediction.alt)
749    }
750
751    pub fn adaptive_predict_info_with_precedence(
752        &mut self,
753        decision: usize,
754        precedence: usize,
755        lookahead: impl IntoIterator<Item = i32>,
756    ) -> Result<ParserAtnPrediction, ParserAtnSimulatorError> {
757        let mut input = LookaheadIntStream::new(lookahead.into_iter().collect());
758        self.adaptive_predict_stream_info_with_precedence(decision, precedence, &mut input)
759    }
760
761    fn adaptive_predict_stream_inner<T: IntStream>(
762        &mut self,
763        request: AdaptivePredictRequest,
764        input: &mut T,
765        merge_cache: &mut PredictionWorkspace,
766    ) -> Result<ParserAtnPrediction, ParserAtnSimulatorError> {
767        let AdaptivePredictRequest {
768            decision,
769            precedence,
770            outer_context,
771            force_full_context_retry,
772            sll_probe_only,
773        } = request;
774        self.deferred_accept_states
775            .retain(|(stored_decision, _)| *stored_decision != decision);
776        #[cfg(feature = "perf-counters")]
777        crate::perf::record_adaptive_call(decision, force_full_context_retry);
778        let Some(decision_state) = self.atn.decision_to_state().get(decision) else {
779            return Err(ParserAtnSimulatorError::UnknownDecision(decision));
780        };
781        let start_index = input.index();
782        // Precedence originates from the parser's precedence stack (rule nesting
783        // depth), so it is always small in practice. A value above `i32::MAX`
784        // would be clamped here; the clamp only ever affects pathological inputs
785        // and at worst over-filters precedence transitions, never miscomputing a
786        // real parse.
787        let precedence = i32::try_from(precedence).unwrap_or(i32::MAX);
788        let mut state_number =
789            self.ensure_start_state(decision, decision_state, precedence, merge_cache)?;
790        // The direct interpreter API can continue past a completed prefix, but
791        // generated parsers retain standard SLL early termination.
792        let track_previous_good_alt = !force_full_context_retry && !sll_probe_only;
793        let mut previous_good_alt = None;
794        if let Some(prediction) = self.prediction_or_full_context(
795            input,
796            PredictionCheck {
797                decision,
798                decision_state,
799                state_number,
800                start_index,
801                precedence,
802                outer_context,
803                force_full_context_retry,
804                sll_probe_only,
805            },
806            merge_cache,
807        )? {
808            return Ok(prediction);
809        }
810        loop {
811            if track_previous_good_alt {
812                let finished = self
813                    .store
814                    .decision_to_dfa
815                    .get(decision)
816                    .map(|dfa| dfa.configs(state_number))
817                    .and_then(|configs| self.previous_good_alt(configs));
818                if finished.is_some() {
819                    previous_good_alt = finished;
820                }
821            }
822            let symbol = input.la(1);
823            let target = self
824                .store
825                .decision_to_dfa
826                .get(decision)
827                .and_then(|dfa| dfa.edge(state_number, symbol));
828            #[cfg(feature = "perf-counters")]
829            crate::perf::record_dfa_edge_lookup(target.is_some());
830            if let Some(target) = target {
831                state_number = target;
832            } else {
833                let configs = self
834                    .store
835                    .decision_to_dfa
836                    .get(decision)
837                    .map(|dfa| dfa.configs(state_number).clone())
838                    .ok_or(ParserAtnSimulatorError::MissingDfaState(state_number))?;
839                let edge = DfaEdge {
840                    decision,
841                    source_state: state_number,
842                };
843                let target = match self.compute_target_state(
844                    edge,
845                    &configs,
846                    symbol,
847                    precedence,
848                    merge_cache,
849                ) {
850                    Ok(target) => target,
851                    Err(ParserAtnSimulatorError::NoViableAlt { symbol, .. }) => {
852                        if let Some(fallback) = previous_good_alt.as_ref() {
853                            self.add_previous_good_alt_target(edge, symbol, fallback, merge_cache)
854                        } else {
855                            return Err(ParserAtnSimulatorError::NoViableAlt {
856                                symbol,
857                                index: input.index(),
858                            });
859                        }
860                    }
861                    Err(error) => return Err(error),
862                };
863                state_number = target;
864            }
865            if let Some(prediction) = self.prediction_or_full_context(
866                input,
867                PredictionCheck {
868                    decision,
869                    decision_state,
870                    state_number,
871                    start_index,
872                    precedence,
873                    outer_context,
874                    force_full_context_retry,
875                    sll_probe_only,
876                },
877                merge_cache,
878            )? {
879                let defer_unique = track_previous_good_alt
880                    && previous_good_alt.is_some()
881                    && !prediction.requires_full_context
882                    && !self.prediction_reached_decision_entry_rule_stop(
883                        DfaEdge {
884                            decision,
885                            source_state: state_number,
886                        },
887                        prediction.alt,
888                        precedence,
889                        symbol,
890                        merge_cache,
891                    );
892                if !defer_unique {
893                    return Ok(prediction);
894                }
895                self.deferred_accept_states.insert((decision, state_number));
896            }
897            if symbol == TOKEN_EOF {
898                // We ran out of input while still inside the decision and the
899                // current state is not a clean accept. ANTLR's execATN takes one
900                // more step on EOF, reaches an empty reach set, and falls back to
901                // getSynValidOrSemInvalidAltThatFinishedDecisionEntryRule: any alt
902                // whose configs already reached the decision's rule-stop (i.e. an
903                // exit alt of a `(...)*`/`(...)+`/precedence loop) is a valid
904                // prediction, not a syntax error. Mirror that fallback here so we
905                // exit the loop cleanly instead of reporting a spurious
906                // "no viable alternative at input '<EOF>'".
907                if let Some(configs) = self
908                    .store
909                    .decision_to_dfa
910                    .get(decision)
911                    .map(|dfa| dfa.configs(state_number).clone())
912                    && let Some(alt) = self.alt_that_finished_decision_entry_rule(&configs)
913                {
914                    return Ok(ParserAtnPrediction {
915                        alt,
916                        requires_full_context: false,
917                        has_semantic_context: configs_have_semantic_context_for_alt(&configs, alt),
918                        diagnostic: None,
919                    });
920                }
921                return Err(ParserAtnSimulatorError::PredictionRequiresMoreLookahead);
922            }
923            input.consume();
924        }
925    }
926
927    fn prediction_or_full_context<T: IntStream>(
928        &mut self,
929        input: &mut T,
930        check: PredictionCheck,
931        merge_cache: &mut PredictionWorkspace,
932    ) -> Result<Option<ParserAtnPrediction>, ParserAtnSimulatorError> {
933        let PredictionCheck {
934            decision,
935            decision_state,
936            state_number,
937            start_index,
938            precedence,
939            outer_context,
940            force_full_context_retry,
941            sll_probe_only,
942        } = check;
943        if self.store.contexts.is_empty(outer_context)
944            && let Some(prediction) =
945                self.non_greedy_exit_prediction(decision, decision_state, state_number)
946        {
947            return Ok(Some(prediction));
948        }
949        let Some(info) = self.dfa_prediction_info(decision, state_number) else {
950            return Ok(None);
951        };
952        let prediction = info.prediction;
953        // SLL-probe stage: the caller only needs to know that this conflict
954        // requires full context; it will re-run with the real outer context.
955        // Returning the SLL prediction here (with requires_full_context set)
956        // avoids running the full-context LL loop with the empty probe context,
957        // whose result the generated two-stage code discards. Mirrors Go's
958        // execATN, which signals "needs LL" instead of computing LL twice.
959        if sll_probe_only && prediction.requires_full_context {
960            return Ok(Some(prediction));
961        }
962        if prediction.requires_full_context
963            && (force_full_context_retry || !prediction.has_semantic_context)
964        {
965            #[cfg(feature = "perf-counters")]
966            crate::perf::record_full_context_retry(decision);
967            let sll_stop_index = input.index();
968            input.seek(start_index);
969            let full_context = self.adaptive_predict_full_context(
970                decision_state,
971                input,
972                precedence,
973                outer_context,
974                merge_cache,
975            )?;
976            let (kind, exact, conflicting_alts) = match full_context.resolution {
977                FullContextResolution::Ambiguous { exact, ref alts } => (
978                    ParserAtnPredictionDiagnosticKind::Ambiguity,
979                    exact,
980                    alts.clone(),
981                ),
982                // A unique full-context alt after an SLL conflict is Java's
983                // reportContextSensitivity; the SLL state's conflicting alts
984                // describe the conflict that forced the retry.
985                FullContextResolution::Unique => (
986                    ParserAtnPredictionDiagnosticKind::ContextSensitivity,
987                    false,
988                    info.conflicting_alts,
989                ),
990            };
991            let mut prediction = full_context.prediction;
992            if conflicting_alts.len() > 1 {
993                prediction.diagnostic = Some(ParserAtnPredictionDiagnostic {
994                    kind,
995                    start_index,
996                    sll_stop_index,
997                    ll_stop_index: full_context.stop_index,
998                    conflicting_alts,
999                    exact,
1000                });
1001            }
1002            return Ok(Some(prediction));
1003        }
1004        Ok(Some(prediction))
1005    }
1006
1007    fn non_greedy_exit_prediction(
1008        &self,
1009        decision: usize,
1010        decision_state: usize,
1011        state_number: DfaStateId,
1012    ) -> Option<ParserAtnPrediction> {
1013        if !self
1014            .atn
1015            .state(decision_state)
1016            .is_some_and(AtnState::non_greedy)
1017        {
1018            return None;
1019        }
1020        let configs = &self
1021            .store
1022            .decision_to_dfa
1023            .get(decision)?
1024            .configs(state_number);
1025        let alt = configs
1026            .configs()
1027            .iter()
1028            .filter(|config| {
1029                self.atn
1030                    .state(config.state)
1031                    .is_some_and(AtnState::is_rule_stop)
1032                    && self.store.contexts.has_empty_path(config.context)
1033            })
1034            .map(|config| config.alt)
1035            .min()?;
1036        Some(ParserAtnPrediction {
1037            alt,
1038            requires_full_context: false,
1039            has_semantic_context: configs_have_semantic_context_for_alt(configs, alt),
1040            diagnostic: None,
1041        })
1042    }
1043
1044    fn ensure_start_state(
1045        &mut self,
1046        decision: usize,
1047        decision_state: usize,
1048        precedence: i32,
1049        merge_cache: &mut PredictionWorkspace,
1050    ) -> Result<DfaStateId, ParserAtnSimulatorError> {
1051        if self.store.decision_to_dfa[decision].is_precedence_dfa() {
1052            let precedence_key = usize::try_from(precedence.max(0)).unwrap_or_default();
1053            if let Some(start) =
1054                self.store.decision_to_dfa[decision].precedence_start_state(precedence_key)
1055            {
1056                return Ok(start);
1057            }
1058        } else if let Some(start) = self.store.decision_to_dfa[decision].start_state() {
1059            return Ok(start);
1060        }
1061        let decision_state = self
1062            .atn
1063            .state(decision_state)
1064            .ok_or(ParserAtnSimulatorError::MissingAtnState(decision_state))?;
1065        let configs = self.compute_start_state(decision_state, precedence, merge_cache);
1066        let state_number = self.add_dfa_state(decision, DfaStateBuilder::new(configs));
1067        if self.store.decision_to_dfa[decision].is_precedence_dfa() {
1068            let precedence_key = usize::try_from(precedence.max(0)).unwrap_or_default();
1069            self.store.decision_to_dfa[decision]
1070                .set_precedence_start_state(precedence_key, state_number);
1071        } else {
1072            self.store.decision_to_dfa[decision].set_start_state(state_number);
1073        }
1074        Ok(state_number)
1075    }
1076
1077    fn add_dfa_state(&mut self, decision: usize, state: DfaStateBuilder) -> DfaStateId {
1078        self.store.decision_to_dfa[decision].add_state(state)
1079    }
1080
1081    fn compute_start_state(
1082        &mut self,
1083        decision_state: AtnState<'_>,
1084        precedence: i32,
1085        merge_cache: &mut PredictionWorkspace,
1086    ) -> AtnConfigSet {
1087        self.compute_start_state_with_context(
1088            decision_state,
1089            false,
1090            EMPTY_CONTEXT,
1091            precedence,
1092            merge_cache,
1093        )
1094    }
1095
1096    fn compute_start_state_with_context(
1097        &mut self,
1098        decision_state: AtnState<'_>,
1099        full_context: bool,
1100        initial_context: ContextId,
1101        precedence: i32,
1102        merge_cache: &mut PredictionWorkspace,
1103    ) -> AtnConfigSet {
1104        let mut configs = AtnConfigSet::new_full_context(full_context);
1105        let mut scratch = ClosureScratch::default();
1106        let params = ClosureParams {
1107            precedence,
1108            collect_predicates: true,
1109            treat_eof_as_epsilon: false,
1110        };
1111        for (index, transition) in decision_state.transitions().iter().enumerate() {
1112            let alt = index + 1;
1113            let config = AtnConfig::new(
1114                transition.target(),
1115                alt,
1116                initial_context,
1117                &self.store.contexts,
1118            );
1119            self.closure(config, &mut configs, merge_cache, &mut scratch, params);
1120        }
1121        configs
1122    }
1123
1124    fn adaptive_predict_full_context<T: IntStream>(
1125        &mut self,
1126        decision_state: usize,
1127        input: &mut T,
1128        precedence: i32,
1129        outer_context: ContextId,
1130        merge_cache: &mut PredictionWorkspace,
1131    ) -> Result<FullContextPrediction, ParserAtnSimulatorError> {
1132        let decision_state = self
1133            .atn
1134            .state(decision_state)
1135            .ok_or(ParserAtnSimulatorError::MissingAtnState(decision_state))?;
1136        let mut configs = self.compute_start_state_with_context(
1137            decision_state,
1138            true,
1139            outer_context,
1140            precedence,
1141            merge_cache,
1142        );
1143        // Java's `execATNWithFullContext`: after each reach set a truly
1144        // unique alt resolves as context sensitivity. Otherwise default LL
1145        // mode stops at the first "resolves to just one viable alt" conflict
1146        // — reported as a NON-exact ambiguity, which the exactOnly listener
1147        // suppresses — while LL_EXACT_AMBIG_DETECTION keeps consuming until
1148        // every (state, context) subset conflicts over the same alt set: an
1149        // exact ambiguity.
1150        loop {
1151            if let Some(alt) = configs.unique_alt() {
1152                return Ok(full_context_prediction(
1153                    alt,
1154                    &configs,
1155                    input.index(),
1156                    FullContextResolution::Unique,
1157                ));
1158            }
1159            let symbol = input.la(1);
1160            let reach = self.compute_reach_set(&configs, symbol, true, precedence, merge_cache);
1161            if reach.is_empty() {
1162                return Err(ParserAtnSimulatorError::NoViableAlt {
1163                    symbol,
1164                    index: input.index(),
1165                });
1166            }
1167            configs = reach;
1168            if let Some(alt) = configs.unique_alt() {
1169                return Ok(full_context_prediction(
1170                    alt,
1171                    &configs,
1172                    input.index(),
1173                    FullContextResolution::Unique,
1174                ));
1175            }
1176            if !configs.has_semantic_context() {
1177                let subsets = conflicting_alt_subsets(configs.configs());
1178                if self.exact_ambig_detection {
1179                    let alts: Vec<usize> = configs.alts().into_iter().collect();
1180                    // Both subset checks hold vacuously for an empty list; a
1181                    // real exact ambiguity always carries alternatives, so
1182                    // guard the pick instead of indexing.
1183                    if all_subsets_conflict(&subsets)
1184                        && all_subsets_equal(&subsets)
1185                        && let Some(&alt) = alts.first()
1186                    {
1187                        return Ok(full_context_prediction(
1188                            alt,
1189                            &configs,
1190                            input.index(),
1191                            FullContextResolution::Ambiguous { exact: true, alts },
1192                        ));
1193                    }
1194                } else if let Some(alt) = single_viable_alt(&subsets) {
1195                    let alts: Vec<usize> = configs.alts().into_iter().collect();
1196                    return Ok(full_context_prediction(
1197                        alt,
1198                        &configs,
1199                        input.index(),
1200                        FullContextResolution::Ambiguous { exact: false, alts },
1201                    ));
1202                }
1203            }
1204            if symbol == TOKEN_EOF || self.configs_all_reached_rule_stop(&configs) {
1205                // Safety net Java reaches implicitly: at EOF every surviving
1206                // path sits in a rule-stop config, so the checks above
1207                // resolve; guard against pathological sets instead of
1208                // spinning on an unconsumable EOF.
1209                let alts: Vec<usize> = configs.alts().into_iter().collect();
1210                let alt = *alts
1211                    .first()
1212                    .ok_or(ParserAtnSimulatorError::PredictionRequiresMoreLookahead)?;
1213                let resolution = if alts.len() > 1 {
1214                    FullContextResolution::Ambiguous {
1215                        exact: self.exact_ambig_detection,
1216                        alts,
1217                    }
1218                } else {
1219                    FullContextResolution::Unique
1220                };
1221                return Ok(full_context_prediction(
1222                    alt,
1223                    &configs,
1224                    input.index(),
1225                    resolution,
1226                ));
1227            }
1228            input.consume();
1229        }
1230    }
1231
1232    fn compute_target_state(
1233        &mut self,
1234        edge: DfaEdge,
1235        configs: &AtnConfigSet,
1236        symbol: i32,
1237        precedence: i32,
1238        merge_cache: &mut PredictionWorkspace,
1239    ) -> Result<DfaStateId, ParserAtnSimulatorError> {
1240        let mut reach = self.compute_reach_set(configs, symbol, false, precedence, merge_cache);
1241        if reach.is_empty() {
1242            if let Some(prediction) = self.alt_that_finished_decision_entry_rule(configs) {
1243                let mut dfa_state = DfaStateBuilder::new(configs.clone());
1244                dfa_state.mark_accept(prediction);
1245                // The set-wide flag gates the per-alt scan: if no config in the
1246                // set carries a semantic context, no alt can either.
1247                dfa_state.set_has_semantic_context_for_alt(
1248                    configs.has_semantic_context()
1249                        && configs_have_semantic_context_for_alt(configs, prediction),
1250                );
1251                let target_state = self.add_dfa_state(edge.decision, dfa_state);
1252                self.store.decision_to_dfa[edge.decision].add_edge(
1253                    edge.source_state,
1254                    symbol,
1255                    target_state,
1256                );
1257                return Ok(target_state);
1258            }
1259            return Err(ParserAtnSimulatorError::NoViableAlt { symbol, index: 0 });
1260        }
1261        let prediction = reach.unique_alt();
1262        let conflict_prediction = prediction.or_else(|| {
1263            if !has_sll_conflict_terminating_prediction(&reach, |state| {
1264                self.atn.state(state).is_some_and(AtnState::is_rule_stop)
1265            }) {
1266                return None;
1267            }
1268            reach
1269                .conflicting_alts()
1270                .into_iter()
1271                .next()
1272                .or_else(|| reach.alts().into_iter().next())
1273        });
1274        let requires_full_context = prediction.is_none() && conflict_prediction.is_some();
1275        #[cfg(feature = "perf-counters")]
1276        if requires_full_context {
1277            crate::perf::record_sll_conflict(edge.decision);
1278        }
1279        let conflicting_alts = if requires_full_context {
1280            let alts = reach.conflicting_alts();
1281            if alts.is_empty() { reach.alts() } else { alts }
1282                .into_iter()
1283                .collect()
1284        } else {
1285            Vec::new()
1286        };
1287        let mut dfa_state = DfaStateBuilder::new(reach);
1288        if let Some(prediction) = conflict_prediction {
1289            dfa_state.mark_accept(prediction);
1290            dfa_state.set_requires_full_context(requires_full_context);
1291            dfa_state.set_conflicting_alts(conflicting_alts);
1292            // The set-wide flag gates the per-alt scan: if no config in the set
1293            // carries a semantic context, no alt can either.
1294            dfa_state.set_has_semantic_context_for_alt(
1295                dfa_state.configs.has_semantic_context()
1296                    && configs_have_semantic_context_for_alt(&dfa_state.configs, prediction),
1297            );
1298        }
1299        let target_state = self.add_dfa_state(edge.decision, dfa_state);
1300        self.store.decision_to_dfa[edge.decision].add_edge(edge.source_state, symbol, target_state);
1301        Ok(target_state)
1302    }
1303
1304    fn compute_reach_set(
1305        &mut self,
1306        configs: &AtnConfigSet,
1307        symbol: i32,
1308        full_context: bool,
1309        precedence: i32,
1310        merge_cache: &mut PredictionWorkspace,
1311    ) -> AtnConfigSet {
1312        let mut intermediate = AtnConfigSet::new_full_context(full_context);
1313        let mut skipped_stop_states = Vec::new();
1314        let max_token_type = self.atn.max_token_type();
1315        for config in configs.configs() {
1316            let Some(state) = self.atn.state(config.state) else {
1317                continue;
1318            };
1319            if state.is_rule_stop() {
1320                if full_context || symbol == TOKEN_EOF {
1321                    skipped_stop_states.push(config.clone());
1322                }
1323                continue;
1324            }
1325            for transition in &state.transitions() {
1326                if transition.matches(symbol, 1, max_token_type) {
1327                    let target =
1328                        config.moved_to(transition.target(), config.context, &self.store.contexts);
1329                    intermediate.add(target, &mut self.store.contexts, merge_cache);
1330                }
1331            }
1332        }
1333        let mut reach = if skipped_stop_states.is_empty() && symbol != TOKEN_EOF {
1334            if intermediate.len() == 1 || intermediate.unique_alt().is_some() {
1335                intermediate
1336            } else {
1337                self.close_intermediate_reach_set(
1338                    intermediate,
1339                    full_context,
1340                    precedence,
1341                    symbol,
1342                    merge_cache,
1343                )
1344            }
1345        } else {
1346            self.close_intermediate_reach_set(
1347                intermediate,
1348                full_context,
1349                precedence,
1350                symbol,
1351                merge_cache,
1352            )
1353        };
1354        if symbol == TOKEN_EOF {
1355            reach = self.rule_stop_configs(reach, merge_cache);
1356        }
1357        if !full_context || !self.configs_contain_rule_stop(&reach) {
1358            for config in skipped_stop_states {
1359                reach.add(config, &mut self.store.contexts, merge_cache);
1360            }
1361        }
1362        #[cfg(feature = "perf-counters")]
1363        crate::perf::record_reach_set(full_context, configs.len(), reach.len());
1364        reach
1365    }
1366
1367    fn close_intermediate_reach_set(
1368        &mut self,
1369        intermediate: AtnConfigSet,
1370        full_context: bool,
1371        precedence: i32,
1372        symbol: i32,
1373        merge_cache: &mut PredictionWorkspace,
1374    ) -> AtnConfigSet {
1375        let mut reach = AtnConfigSet::new_full_context(full_context);
1376        let mut scratch = ClosureScratch::default();
1377        let params = ClosureParams {
1378            precedence,
1379            collect_predicates: false,
1380            treat_eof_as_epsilon: symbol == TOKEN_EOF,
1381        };
1382        // `closure` takes `AtnConfig` by value, so drain the intermediate set by
1383        // move instead of cloning each config.
1384        for config in intermediate.into_configs() {
1385            self.closure(config, &mut reach, merge_cache, &mut scratch, params);
1386        }
1387        reach
1388    }
1389
1390    fn alt_that_finished_decision_entry_rule(&self, configs: &AtnConfigSet) -> Option<usize> {
1391        configs
1392            .configs()
1393            .iter()
1394            .filter(|config| self.config_finished_decision_entry_rule(config))
1395            .map(|config| config.alt)
1396            .min()
1397    }
1398
1399    fn previous_good_alt(&self, configs: &AtnConfigSet) -> Option<PreviousGoodAlt> {
1400        let alt = self.alt_that_finished_decision_entry_rule(configs)?;
1401        let configs = configs
1402            .configs()
1403            .iter()
1404            .filter(|config| config.alt == alt && self.config_finished_decision_entry_rule(config))
1405            .cloned()
1406            .collect();
1407        Some(PreviousGoodAlt { alt, configs })
1408    }
1409
1410    fn config_finished_decision_entry_rule(&self, config: &AtnConfig) -> bool {
1411        config.reaches_into_outer_context > 0
1412            || self
1413                .atn
1414                .state(config.state)
1415                .is_some_and(AtnState::is_rule_stop)
1416                && self.store.contexts.has_empty_path(config.context)
1417    }
1418
1419    fn add_previous_good_alt_target(
1420        &mut self,
1421        edge: DfaEdge,
1422        symbol: i32,
1423        fallback: &PreviousGoodAlt,
1424        merge_cache: &mut PredictionWorkspace,
1425    ) -> DfaStateId {
1426        let mut configs = AtnConfigSet::new();
1427        for config in &fallback.configs {
1428            configs.add(config.clone(), &mut self.store.contexts, merge_cache);
1429        }
1430        let has_semantic_context = configs_have_semantic_context_for_alt(&configs, fallback.alt);
1431        let mut state = DfaStateBuilder::new(configs);
1432        state.mark_accept(fallback.alt);
1433        state.set_has_semantic_context_for_alt(has_semantic_context);
1434        let target = self.add_dfa_state(edge.decision, state);
1435        self.store.decision_to_dfa[edge.decision].add_edge(edge.source_state, symbol, target);
1436        target
1437    }
1438
1439    fn prediction_reached_decision_entry_rule_stop(
1440        &mut self,
1441        edge: DfaEdge,
1442        alt: usize,
1443        precedence: i32,
1444        symbol: i32,
1445        merge_cache: &mut PredictionWorkspace,
1446    ) -> bool {
1447        let configs = self.store.decision_to_dfa[edge.decision]
1448            .configs(edge.source_state)
1449            .clone();
1450        if self.alt_that_finished_decision_entry_rule(&configs) == Some(alt) {
1451            return true;
1452        }
1453        let closed =
1454            self.close_intermediate_reach_set(configs, false, precedence, symbol, merge_cache);
1455        self.alt_that_finished_decision_entry_rule(&closed) == Some(alt)
1456    }
1457
1458    fn rule_stop_configs(
1459        &mut self,
1460        configs: AtnConfigSet,
1461        merge_cache: &mut PredictionWorkspace,
1462    ) -> AtnConfigSet {
1463        if configs.configs().iter().all(|config| {
1464            self.atn
1465                .state(config.state)
1466                .is_some_and(AtnState::is_rule_stop)
1467        }) {
1468            return configs;
1469        }
1470        let mut result = AtnConfigSet::new_full_context(configs.full_context());
1471        for config in configs.configs().iter().filter(|config| {
1472            self.atn
1473                .state(config.state)
1474                .is_some_and(AtnState::is_rule_stop)
1475        }) {
1476            result.add(config.clone(), &mut self.store.contexts, merge_cache);
1477        }
1478        result
1479    }
1480
1481    fn configs_all_reached_rule_stop(&self, configs: &AtnConfigSet) -> bool {
1482        configs.configs().iter().all(|config| {
1483            self.atn
1484                .state(config.state)
1485                .is_some_and(AtnState::is_rule_stop)
1486        })
1487    }
1488
1489    fn configs_contain_rule_stop(&self, configs: &AtnConfigSet) -> bool {
1490        configs.configs().iter().any(|config| {
1491            self.atn
1492                .state(config.state)
1493                .is_some_and(AtnState::is_rule_stop)
1494        })
1495    }
1496
1497    fn closure(
1498        &mut self,
1499        config: AtnConfig,
1500        configs: &mut AtnConfigSet,
1501        merge_cache: &mut PredictionWorkspace,
1502        scratch: &mut ClosureScratch,
1503        params: ClosureParams,
1504    ) {
1505        let ClosureParams {
1506            precedence,
1507            collect_predicates,
1508            treat_eof_as_epsilon,
1509        } = params;
1510        let max_token_type = self.atn.max_token_type();
1511        scratch.stack.clear();
1512        scratch.visited.clear();
1513        scratch.stack.push((config, collect_predicates));
1514        while let Some((config, collect_predicates)) = scratch.stack.pop() {
1515            if !scratch.visited.insert(ClosureConfigKey::from(&config)) {
1516                continue;
1517            }
1518            let Some(state) = self.atn.state(config.state) else {
1519                continue;
1520            };
1521            let at_rule_stop = state.is_rule_stop();
1522            if at_rule_stop
1523                && self.closure_at_rule_stop(
1524                    config.clone(),
1525                    collect_predicates,
1526                    configs,
1527                    merge_cache,
1528                    &mut scratch.stack,
1529                )
1530            {
1531                continue;
1532            }
1533            let epsilon_only = state.epsilon_only();
1534            if !epsilon_only {
1535                configs.add(config.clone(), &mut self.store.contexts, merge_cache);
1536            }
1537            for (index, transition) in state.transitions().iter().enumerate() {
1538                if index == 0
1539                    && can_drop_left_recursive_loop_entry_edge(
1540                        self.atn,
1541                        state,
1542                        &self.store.contexts,
1543                        config.context,
1544                    )
1545                {
1546                    continue;
1547                }
1548                let transition_kind = transition.kind();
1549                if matches!(
1550                    transition_kind,
1551                    ParserTransitionKind::Epsilon
1552                        | ParserTransitionKind::Rule
1553                        | ParserTransitionKind::Predicate
1554                        | ParserTransitionKind::Action
1555                        | ParserTransitionKind::Precedence
1556                ) {
1557                    if let Some(mut target) = self.epsilon_target_config(
1558                        &config,
1559                        transition,
1560                        transition_kind,
1561                        precedence,
1562                        collect_predicates,
1563                        configs.full_context(),
1564                    ) {
1565                        if at_rule_stop {
1566                            target.reaches_into_outer_context =
1567                                target.reaches_into_outer_context.saturating_add(1);
1568                        }
1569                        // ANTLR: stop collecting predicates once an action edge is
1570                        // crossed, so a predicate after an action is deferred to
1571                        // parse time rather than evaluated during prediction.
1572                        let target_collect_predicates =
1573                            collect_predicates && transition_kind != ParserTransitionKind::Action;
1574                        scratch.stack.push((target, target_collect_predicates));
1575                    }
1576                } else if treat_eof_as_epsilon
1577                    && transition.matches_kind(transition_kind, TOKEN_EOF, 1, max_token_type)
1578                {
1579                    scratch.stack.push((
1580                        config.moved_to(transition.target(), config.context, &self.store.contexts),
1581                        collect_predicates,
1582                    ));
1583                }
1584            }
1585        }
1586        #[cfg(feature = "perf-counters")]
1587        crate::perf::record_closure(scratch.visited.len());
1588    }
1589
1590    fn closure_at_rule_stop(
1591        &mut self,
1592        config: AtnConfig,
1593        collect_predicates: bool,
1594        configs: &mut AtnConfigSet,
1595        merge_cache: &mut PredictionWorkspace,
1596        stack: &mut Vec<(AtnConfig, bool)>,
1597    ) -> bool {
1598        if self.store.contexts.is_empty(config.context) {
1599            if configs.full_context() {
1600                configs.add(config, &mut self.store.contexts, merge_cache);
1601                return true;
1602            }
1603            return false;
1604        }
1605        let mut handled_all_paths = true;
1606        for index in 0..self.store.contexts.len(config.context) {
1607            let Some(return_state) = self.store.contexts.return_state(config.context, index) else {
1608                continue;
1609            };
1610            if return_state == EMPTY_RETURN_STATE {
1611                if configs.full_context() {
1612                    let mut empty_context_config = config.clone();
1613                    empty_context_config.set_context(EMPTY_CONTEXT, &self.store.contexts);
1614                    configs.add(empty_context_config, &mut self.store.contexts, merge_cache);
1615                } else {
1616                    handled_all_paths = false;
1617                }
1618                continue;
1619            }
1620            let parent = self
1621                .store
1622                .contexts
1623                .parent(config.context, index)
1624                .unwrap_or(EMPTY_CONTEXT);
1625            let next = config.moved_to(return_state, parent, &self.store.contexts);
1626            stack.push((next, collect_predicates));
1627        }
1628        handled_all_paths
1629    }
1630
1631    #[allow(clippy::too_many_arguments)]
1632    fn epsilon_target_config(
1633        &mut self,
1634        config: &AtnConfig,
1635        transition: ParserTransition<'_>,
1636        transition_kind: ParserTransitionKind,
1637        precedence: i32,
1638        collect_predicates: bool,
1639        full_context: bool,
1640    ) -> Option<AtnConfig> {
1641        let semantic_context = match transition_kind {
1642            ParserTransitionKind::Predicate if collect_predicates => SemanticContext::and(
1643                config.semantic_context.clone(),
1644                SemanticContext::Predicate {
1645                    rule_index: transition.arg0() as usize,
1646                    pred_index: transition.arg1() as usize,
1647                    context_dependent: transition.arg2() != 0,
1648                },
1649            ),
1650            ParserTransitionKind::Precedence
1651                if collect_predicates
1652                    && i32::from_le_bytes(transition.arg0().to_le_bytes()) < precedence =>
1653            {
1654                return None;
1655            }
1656            ParserTransitionKind::Precedence if collect_predicates && !full_context => {
1657                SemanticContext::and(
1658                    config.semantic_context.clone(),
1659                    SemanticContext::Precedence {
1660                        precedence: i32::from_le_bytes(transition.arg0().to_le_bytes()),
1661                    },
1662                )
1663            }
1664            _ => config.semantic_context.clone(),
1665        };
1666        let context = if transition_kind == ParserTransitionKind::Rule {
1667            self.store
1668                .contexts
1669                .singleton(config.context, transition.arg1() as usize)
1670        } else {
1671            config.context
1672        };
1673        let mut target = config.moved_to(transition.target(), context, &self.store.contexts);
1674        target.semantic_context = semantic_context;
1675        Some(target)
1676    }
1677
1678    fn dfa_prediction_info(
1679        &self,
1680        decision: usize,
1681        state_number: DfaStateId,
1682    ) -> Option<DfaPredictionInfo> {
1683        let dfa = self.store.decision_to_dfa.get(decision)?;
1684        let state = dfa.state(state_number)?;
1685        let alt = state.prediction()?;
1686        let requires_full_context = state.requires_full_context();
1687        let conflicting_alts = if requires_full_context {
1688            let stored = dfa.conflicting_alts(state_number);
1689            if stored.is_empty() {
1690                dfa.configs(state_number).alts().into_iter().collect()
1691            } else {
1692                stored.to_vec()
1693            }
1694        } else {
1695            Vec::new()
1696        };
1697        Some(DfaPredictionInfo {
1698            prediction: ParserAtnPrediction {
1699                alt,
1700                requires_full_context,
1701                // Precomputed at accept time (see compute_target_state) so
1702                // warm accept lookup does not rescan the cold config set.
1703                has_semantic_context: state.has_semantic_context(),
1704                diagnostic: None,
1705            },
1706            conflicting_alts,
1707        })
1708    }
1709}
1710
1711/// Reports whether closure should skip the loop-entry branch for a
1712/// left-recursive rule under the current caller context.
1713pub(crate) fn can_drop_left_recursive_loop_entry_edge(
1714    atn: &Atn,
1715    state: AtnState<'_>,
1716    contexts: &ContextArena,
1717    context: ContextId,
1718) -> bool {
1719    if state.kind() != AtnStateKind::StarLoopEntry
1720        || !state.precedence_rule_decision()
1721        || contexts.is_empty(context)
1722        || contexts.has_empty_path(context)
1723    {
1724        return false;
1725    }
1726    let Some(rule_index) = state.rule_index() else {
1727        return false;
1728    };
1729    for index in 0..contexts.len(context) {
1730        let Some(return_state_number) = contexts.return_state(context, index) else {
1731            return false;
1732        };
1733        let Some(return_state) = atn.state(return_state_number) else {
1734            return false;
1735        };
1736        if return_state.rule_index() != Some(rule_index) {
1737            return false;
1738        }
1739    }
1740    let Some(block_end_state_number) = state
1741        .transitions()
1742        .first()
1743        .and_then(|transition| atn.state(transition.target()))
1744        .and_then(AtnState::end_state)
1745    else {
1746        return false;
1747    };
1748    for index in 0..contexts.len(context) {
1749        let return_state_number = contexts
1750            .return_state(context, index)
1751            .expect("return state checked above");
1752        let return_state = atn
1753            .state(return_state_number)
1754            .expect("return state checked above");
1755        if return_state.state_number() == block_end_state_number {
1756            continue;
1757        }
1758        if return_state.transitions().len() != 1
1759            || !return_state
1760                .transitions()
1761                .first()
1762                .is_some_and(ParserTransition::is_epsilon)
1763        {
1764            return false;
1765        }
1766        let return_target = return_state
1767            .transitions()
1768            .first()
1769            .expect("single transition checked above")
1770            .target();
1771        if return_state.kind() == AtnStateKind::BlockEnd && return_target == state.state_number() {
1772            continue;
1773        }
1774        if return_target == block_end_state_number {
1775            continue;
1776        }
1777        let Some(return_target_state) = atn.state(return_target) else {
1778            return false;
1779        };
1780        if return_target_state.kind() == AtnStateKind::BlockEnd
1781            && return_target_state.transitions().len() == 1
1782            && return_target_state
1783                .transitions()
1784                .first()
1785                .is_some_and(ParserTransition::is_epsilon)
1786            && return_target_state
1787                .transitions()
1788                .first()
1789                .is_some_and(|transition| transition.target() == state.state_number())
1790        {
1791            continue;
1792        }
1793        return false;
1794    }
1795    true
1796}
1797
1798fn configs_have_semantic_context_for_alt(configs: &AtnConfigSet, alt: usize) -> bool {
1799    configs
1800        .configs()
1801        .iter()
1802        .any(|config| config.alt == alt && !config.semantic_context.is_none())
1803}
1804
1805#[derive(Clone, Debug, Eq, PartialEq)]
1806pub enum ParserAtnSimulatorError {
1807    MissingAtnState(usize),
1808    MissingDfaState(DfaStateId),
1809    NoViableAlt { symbol: i32, index: usize },
1810    PredictionRequiresMoreLookahead,
1811    UnknownDecision(usize),
1812}
1813
1814/// Java `DFASerializer.getStateString`: `:sN^=>alt` for accept states.
1815fn dfa_state_display(state: ParserDfaStateView<'_>, deferred: bool) -> String {
1816    let mut out = String::new();
1817    let is_accept = state.is_accept_state() && !deferred;
1818    if is_accept {
1819        out.push(':');
1820    }
1821    out.push('s');
1822    out.push_str(&state.id().index().to_string());
1823    if state.requires_full_context() {
1824        out.push('^');
1825    }
1826    if is_accept {
1827        out.push_str("=>");
1828        out.push_str(
1829            &state
1830                .prediction()
1831                .map(|prediction| prediction.to_string())
1832                .unwrap_or_default(),
1833        );
1834    }
1835    out
1836}
1837
1838#[cfg(test)]
1839#[allow(clippy::disallowed_methods)] // `insta` assertion macros unwrap internal I/O.
1840mod tests {
1841    use super::*;
1842    use crate::atn::AtnStateKind;
1843
1844    fn finish_atn(builder: ParserAtnBuilder) -> Atn {
1845        builder.finish().expect("valid packed parser ATN")
1846    }
1847
1848    #[test]
1849    fn union_decision_dfa_preserves_disjoint_coverage() {
1850        fn configs(
1851            atn_state: usize,
1852            arena: &mut ContextArena,
1853            workspace: &mut PredictionWorkspace,
1854        ) -> AtnConfigSet {
1855            let mut set = AtnConfigSet::new();
1856            set.add(
1857                AtnConfig::new(atn_state, 1, EMPTY_CONTEXT, arena),
1858                arena,
1859                workspace,
1860            );
1861            set
1862        }
1863        fn state(
1864            atn_state: usize,
1865            arena: &mut ContextArena,
1866            workspace: &mut PredictionWorkspace,
1867        ) -> DfaStateBuilder {
1868            DfaStateBuilder::new(configs(atn_state, arena, workspace))
1869        }
1870        let mut arena = ContextArena::new();
1871        let mut workspace = PredictionWorkspace::default();
1872
1873        // Two DFAs that evolved independently from the same grammar: equal
1874        // state/edge counts, but disjoint transitions and different state
1875        // numbering for the shared successor.
1876        let mut shared = ParserDfa::with_max_token_type(0, 0, 8);
1877        let shared_root = shared.add_state(state(10, &mut arena, &mut workspace));
1878        let shared_a = shared.add_state(state(11, &mut arena, &mut workspace));
1879        shared.add_edge(shared_root, 1, shared_a);
1880        shared.set_start_state(shared_root);
1881
1882        let mut local = ParserDfa::with_max_token_type(0, 0, 8);
1883        let local_b = local.add_state(state(12, &mut arena, &mut workspace));
1884        let local_root = local.add_state(state(10, &mut arena, &mut workspace));
1885        local.add_edge(local_root, 2, local_b);
1886        local.set_precedence_start_state(3, local_root);
1887
1888        union_decision_dfa(&mut shared, local);
1889
1890        // The root (same config set) gained local's edge without losing its
1891        // own, with the target re-keyed into shared numbering.
1892        assert_eq!(shared.edge(shared_root, 1), Some(shared_a));
1893        let merged_b = shared
1894            .state_id_for_configs(&configs(12, &mut arena, &mut workspace))
1895            .expect("local-only state adopted");
1896        assert_eq!(shared.edge(shared_root, 2), Some(merged_b));
1897        assert_eq!(shared.states().len(), 3);
1898        // Start-state gaps fill from local; incumbents are kept.
1899        assert_eq!(shared.start_state(), Some(shared_root));
1900        assert_eq!(shared.precedence_start_state(3), Some(shared_root));
1901    }
1902
1903    #[test]
1904    fn union_prediction_stores_remaps_context_ids_before_dfa_union() {
1905        let atn = two_token_decision_atn();
1906        let mut shared = PredictionStore::new(&atn);
1907        let mut local = PredictionStore::new(&atn);
1908        let mut workspace = PredictionWorkspace::default();
1909
1910        let distracting = shared.contexts.singleton(EMPTY_CONTEXT, 99);
1911        let local_context = local.contexts.singleton(EMPTY_CONTEXT, 7);
1912        assert_eq!(distracting, local_context, "both stores allocate ID 1");
1913
1914        let mut configs = AtnConfigSet::new();
1915        configs.add(
1916            AtnConfig::new(42, 1, local_context, &local.contexts),
1917            &mut local.contexts,
1918            &mut workspace,
1919        );
1920        local.decision_to_dfa[0].add_state(DfaStateBuilder::new(configs));
1921
1922        union_prediction_stores(&mut shared, local, &mut workspace);
1923
1924        let imported = shared.decision_to_dfa[0]
1925            .states()
1926            .flat_map(|state| shared.decision_to_dfa[0].configs(state.id()).configs())
1927            .find(|config| config.state == 42)
1928            .expect("local DFA config imported");
1929        assert_ne!(imported.context, local_context);
1930        assert_eq!(shared.contexts.return_state(imported.context, 0), Some(7));
1931        imported.assert_store(&shared.contexts);
1932    }
1933
1934    #[test]
1935    fn outer_context_cache_invalidates_with_rule_context_version() {
1936        let atn = two_token_decision_atn();
1937        let mut simulator = ParserAtnSimulator::new(&atn);
1938
1939        let first = simulator.intern_prediction_context(1, [7]);
1940        let cached = simulator.intern_prediction_context(1, [99]);
1941        let refreshed = simulator.intern_prediction_context(2, [99]);
1942
1943        assert_eq!(cached, first);
1944        assert_ne!(refreshed, first);
1945        assert_eq!(
1946            simulator.store.contexts.return_state(refreshed, 0),
1947            Some(99)
1948        );
1949        let stats = simulator.prediction_context_stats();
1950        assert_eq!(stats.outer_context_cache_hits, 1);
1951        assert_eq!(stats.outer_context_cache_misses, 2);
1952    }
1953
1954    #[test]
1955    fn outer_context_cache_is_simulator_local() {
1956        let atn = two_token_decision_atn();
1957        let mut first = ParserAtnSimulator::new(&atn);
1958        let mut second = ParserAtnSimulator::new(&atn);
1959
1960        let first_context = first.intern_prediction_context(1, [7]);
1961        let second_context = second.intern_prediction_context(1, [99]);
1962
1963        assert_eq!(first.store.contexts.return_state(first_context, 0), Some(7));
1964        assert_eq!(
1965            second.store.contexts.return_state(second_context, 0),
1966            Some(99)
1967        );
1968    }
1969
1970    #[test]
1971    fn adaptive_predict_reuses_dense_dfa_edges() {
1972        let atn = two_token_decision_atn();
1973        let mut simulator = ParserAtnSimulator::new(&atn);
1974
1975        assert_eq!(simulator.adaptive_predict(0, [1, 2]), Ok(1));
1976        assert_eq!(simulator.adaptive_predict(0, [1, 3]), Ok(2));
1977
1978        let dfa = &simulator.decision_dfas()[0];
1979        let start = dfa.start_state().expect("start state");
1980        let after_first = dfa.state(start).and_then(|state| state.edge(1));
1981        assert!(after_first.is_some());
1982    }
1983
1984    #[test]
1985    fn shared_simulator_reuses_learned_dfa_states() {
1986        let atn = Box::leak(Box::new(two_token_decision_atn()));
1987        let learned_states = {
1988            let mut simulator = ParserAtnSimulator::new_shared(atn);
1989            assert_eq!(simulator.adaptive_predict(0, [1, 2]), Ok(1));
1990            simulator.decision_dfas()[0].states().len()
1991        };
1992
1993        let simulator = ParserAtnSimulator::new_shared(atn);
1994        assert_eq!(simulator.decision_dfas()[0].states().len(), learned_states);
1995    }
1996
1997    #[test]
1998    fn clear_shared_dfa_drops_learned_states() {
1999        let atn = Box::leak(Box::new(two_token_decision_atn()));
2000        {
2001            let mut simulator = ParserAtnSimulator::new_shared(atn);
2002            assert_eq!(simulator.adaptive_predict(0, [1, 2]), Ok(1));
2003            assert!(!simulator.decision_dfas()[0].is_empty());
2004        }
2005
2006        ParserAtnSimulator::clear_shared_dfa(atn);
2007
2008        let simulator = ParserAtnSimulator::new_shared(atn);
2009        assert!(simulator.decision_dfas()[0].is_empty());
2010    }
2011
2012    #[test]
2013    fn clear_dfa_rejects_stale_overlapping_simulator_publication() {
2014        let atn = Box::leak(Box::new(two_token_decision_atn()));
2015        let mut current = ParserAtnSimulator::new_shared(atn);
2016        let mut stale = ParserAtnSimulator::new_shared(atn);
2017        assert_eq!(stale.adaptive_predict(0, [1, 2]), Ok(1));
2018        assert!(!stale.decision_dfas()[0].is_empty());
2019
2020        current.clear_dfa();
2021        drop(stale);
2022        drop(current);
2023
2024        let simulator = ParserAtnSimulator::new_shared(atn);
2025        assert!(simulator.decision_dfas()[0].is_empty());
2026    }
2027
2028    #[test]
2029    fn adaptive_predict_reports_no_viable_alt() {
2030        let atn = two_token_decision_atn();
2031        let mut simulator = ParserAtnSimulator::new(&atn);
2032
2033        assert_eq!(
2034            simulator.adaptive_predict(0, [4]),
2035            Err(ParserAtnSimulatorError::NoViableAlt {
2036                symbol: 4,
2037                index: 0
2038            })
2039        );
2040    }
2041
2042    #[test]
2043    fn adaptive_predict_marks_sll_conflict_for_full_context() {
2044        let atn = ambiguous_single_token_decision_atn();
2045        let mut simulator = ParserAtnSimulator::new(&atn);
2046
2047        assert_eq!(simulator.adaptive_predict(0, [1]), Ok(1));
2048        let prediction = simulator
2049            .adaptive_predict_info_with_precedence(0, 0, [1])
2050            .expect("prediction");
2051        insta::assert_debug_snapshot!(
2052            "adaptive_predict_marks_sll_conflict_for_full_context",
2053            prediction
2054        );
2055
2056        let dfa = &simulator.decision_dfas()[0];
2057        let start = dfa.start_state().expect("start state");
2058        let target = dfa
2059            .state(start)
2060            .and_then(|state| state.edge(1))
2061            .expect("edge for token 1");
2062        let state = dfa.state(target).expect("target state");
2063        assert!(state.is_accept_state());
2064        assert!(state.requires_full_context());
2065        assert_eq!(state.prediction(), Some(1));
2066    }
2067
2068    #[test]
2069    fn adaptive_predict_keeps_rule_stop_configs_at_eof() {
2070        let atn = optional_token_decision_atn();
2071        let mut simulator = ParserAtnSimulator::new(&atn);
2072
2073        assert_eq!(simulator.adaptive_predict(0, [TOKEN_EOF]), Ok(2));
2074    }
2075
2076    #[test]
2077    fn adaptive_predict_treats_repeated_eof_as_epsilon_after_first_eof() {
2078        let atn = multiple_eof_decision_atn();
2079        let mut simulator = ParserAtnSimulator::new(&atn);
2080
2081        assert_eq!(simulator.adaptive_predict(0, [1, TOKEN_EOF]), Ok(1));
2082    }
2083
2084    #[test]
2085    fn adaptive_predict_uses_finished_entry_rule_alt_on_error_edge() {
2086        let atn = prefix_alt_decision_atn();
2087        let mut simulator = ParserAtnSimulator::new(&atn);
2088
2089        assert_eq!(simulator.adaptive_predict(0, [1, 3]), Ok(1));
2090    }
2091
2092    #[test]
2093    fn adaptive_predict_keeps_prefix_alt_until_longer_alt_finishes() {
2094        let atn = three_token_prefix_alt_decision_atn();
2095        let mut simulator = ParserAtnSimulator::new(&atn);
2096
2097        assert_eq!(simulator.adaptive_predict(0, [1, 2, TOKEN_EOF]), Ok(1));
2098        assert_eq!(simulator.adaptive_predict(0, [1, 2, 1, TOKEN_EOF]), Ok(2));
2099    }
2100
2101    #[test]
2102    fn sll_probe_keeps_unique_alt_early_termination() {
2103        let atn = three_token_prefix_alt_decision_atn();
2104        let mut simulator = ParserAtnSimulator::new(&atn);
2105        let mut input = VecIntStream::new(vec![1, 2, TOKEN_EOF]);
2106
2107        let prediction = simulator
2108            .adaptive_predict_stream_info_sll_probe(0, 0, &mut input)
2109            .expect("SLL prediction should succeed");
2110
2111        assert_eq!(prediction.alt, 2);
2112    }
2113
2114    #[test]
2115    fn adaptive_predict_uses_precedence_dfa_start_states() {
2116        let atn = two_token_decision_atn_with_precedence(true);
2117        let mut simulator = ParserAtnSimulator::new(&atn);
2118
2119        assert_eq!(
2120            simulator.adaptive_predict_with_precedence(0, 3, [1, 2]),
2121            Ok(1)
2122        );
2123        assert_eq!(
2124            simulator.adaptive_predict_with_precedence(0, 7, [1, 3]),
2125            Ok(2)
2126        );
2127
2128        let dfa = &simulator.decision_dfas()[0];
2129        assert!(dfa.is_precedence_dfa());
2130        assert!(dfa.precedence_start_state(3).is_some());
2131        assert!(dfa.precedence_start_state(7).is_some());
2132    }
2133
2134    #[test]
2135    fn adaptive_predict_stream_restores_input_position() {
2136        let atn = two_token_decision_atn();
2137        let mut simulator = ParserAtnSimulator::new(&atn);
2138        let mut input = VecIntStream::new(vec![1, 3, TOKEN_EOF]);
2139
2140        assert_eq!(simulator.adaptive_predict_stream(0, &mut input), Ok(2));
2141        assert_eq!(input.index(), 0);
2142        assert_eq!(input.la(1), 1);
2143    }
2144
2145    #[test]
2146    fn adaptive_predict_stream_retries_full_context_conflict() {
2147        let atn = ambiguous_single_token_decision_atn();
2148        let mut simulator = ParserAtnSimulator::new(&atn);
2149        let mut input = VecIntStream::new(vec![1, TOKEN_EOF]);
2150
2151        let prediction = simulator
2152            .adaptive_predict_stream_info_with_precedence(0, 0, &mut input)
2153            .expect("prediction");
2154
2155        insta::assert_debug_snapshot!(
2156            "adaptive_predict_stream_retries_full_context_conflict",
2157            prediction
2158        );
2159        assert_eq!(input.index(), 0);
2160    }
2161
2162    #[test]
2163    fn context_prediction_reports_context_sensitivity_for_dfa_conflict() {
2164        let atn = two_token_decision_atn();
2165        let mut simulator = ParserAtnSimulator::new(&atn);
2166        let mut workspace = PredictionWorkspace::default();
2167        let mut start_configs = AtnConfigSet::new();
2168        start_configs.add(
2169            AtnConfig::new(2, 1, EMPTY_CONTEXT, &simulator.store.contexts),
2170            &mut simulator.store.contexts,
2171            &mut workspace,
2172        );
2173        let start =
2174            simulator.store.decision_to_dfa[0].add_state(DfaStateBuilder::new(start_configs));
2175        simulator.store.decision_to_dfa[0].set_start_state(start);
2176
2177        let mut accept_configs = AtnConfigSet::new();
2178        accept_configs.add(
2179            AtnConfig::new(3, 1, EMPTY_CONTEXT, &simulator.store.contexts).with_semantic_context(
2180                SemanticContext::Predicate {
2181                    rule_index: 0,
2182                    pred_index: 0,
2183                    context_dependent: false,
2184                },
2185            ),
2186            &mut simulator.store.contexts,
2187            &mut workspace,
2188        );
2189        let mut accept_state = DfaStateBuilder::new(accept_configs);
2190        accept_state.mark_accept(1);
2191        accept_state.set_requires_full_context(true);
2192        accept_state.set_conflicting_alts(vec![1, 2]);
2193        let accept = simulator.store.decision_to_dfa[0].add_state(accept_state);
2194        simulator.store.decision_to_dfa[0].add_edge(start, 1, accept);
2195
2196        let mut input = VecIntStream::new(vec![1, 3, TOKEN_EOF]);
2197        let prediction = simulator
2198            .adaptive_predict_stream_info_with_context(0, 0, &mut input, EMPTY_CONTEXT)
2199            .expect("prediction");
2200
2201        insta::assert_debug_snapshot!(
2202            "context_prediction_reports_context_sensitivity_for_dfa_conflict",
2203            prediction
2204        );
2205        assert_eq!(input.index(), 0);
2206    }
2207
2208    #[test]
2209    fn full_context_reach_prefers_longer_match_over_skipped_stop_state() {
2210        let atn = prefix_alt_decision_atn();
2211        let mut simulator = ParserAtnSimulator::new(&atn);
2212        let mut configs = AtnConfigSet::new_full_context(true);
2213        let mut merge_cache = PredictionWorkspace::default();
2214        configs.add(
2215            AtnConfig::new(2, 1, EMPTY_CONTEXT, &simulator.store.contexts),
2216            &mut simulator.store.contexts,
2217            &mut merge_cache,
2218        );
2219        configs.add(
2220            AtnConfig::new(1, 2, EMPTY_CONTEXT, &simulator.store.contexts),
2221            &mut simulator.store.contexts,
2222            &mut merge_cache,
2223        );
2224
2225        let reach = simulator.compute_reach_set(&configs, 2, true, 0, &mut merge_cache);
2226
2227        assert_eq!(reach.alts(), std::iter::once(2).collect());
2228        assert!(simulator.configs_all_reached_rule_stop(&reach));
2229    }
2230
2231    #[test]
2232    fn sll_closure_follows_empty_context_rule_stop_exits() {
2233        let mut atn = ParserAtnBuilder::new(1);
2234        add_state(&mut atn, 0, AtnStateKind::RuleStop);
2235        add_state(&mut atn, 1, AtnStateKind::Basic);
2236        add_state(&mut atn, 2, AtnStateKind::Basic);
2237        atn.add_transition(0, ParserTransitionSpec::Epsilon { target: 1 })
2238            .expect("transition");
2239        atn.add_transition(
2240            1,
2241            ParserTransitionSpec::Atom {
2242                target: 2,
2243                label: 1,
2244            },
2245        )
2246        .expect("transition");
2247        atn.set_rule_to_start_state(vec![0])
2248            .expect("rule start states");
2249        atn.set_rule_to_stop_state(vec![0])
2250            .expect("rule stop states");
2251        let atn = finish_atn(atn);
2252
2253        let mut simulator = ParserAtnSimulator::new(&atn);
2254        let mut configs = AtnConfigSet::new_full_context(false);
2255        let mut merge_cache = PredictionWorkspace::default();
2256        let mut scratch = ClosureScratch::default();
2257        let config = AtnConfig::new(0, 2, EMPTY_CONTEXT, &simulator.store.contexts);
2258        simulator.closure(
2259            config,
2260            &mut configs,
2261            &mut merge_cache,
2262            &mut scratch,
2263            ClosureParams {
2264                precedence: 0,
2265                collect_predicates: true,
2266                treat_eof_as_epsilon: false,
2267            },
2268        );
2269
2270        assert_eq!(configs.len(), 1);
2271        let config = &configs.configs()[0];
2272        assert_eq!(config.state, 1);
2273        assert_eq!(config.alt, 2);
2274        assert_eq!(config.reaches_into_outer_context, 1);
2275    }
2276
2277    #[test]
2278    fn precedence_contexts_are_collected_only_for_start_closure() {
2279        let mut atn = ParserAtnBuilder::new(1);
2280        add_state(&mut atn, 0, AtnStateKind::Basic);
2281        add_state(&mut atn, 1, AtnStateKind::Basic);
2282        atn.set_rule_to_start_state(vec![0])
2283            .expect("rule start states");
2284        atn.set_rule_to_stop_state(vec![1])
2285            .expect("rule stop states");
2286        atn.add_transition(
2287            0,
2288            ParserTransitionSpec::Precedence {
2289                target: 1,
2290                precedence: 2,
2291            },
2292        )
2293        .expect("precedence transition");
2294        let atn = finish_atn(atn);
2295        let transition = atn
2296            .state(0)
2297            .expect("source state")
2298            .transitions()
2299            .first()
2300            .expect("precedence transition");
2301        let mut simulator = ParserAtnSimulator::new(&atn);
2302        let config = AtnConfig::new(0, 1, EMPTY_CONTEXT, &simulator.store.contexts);
2303
2304        let sll_start = simulator
2305            .epsilon_target_config(&config, transition, transition.kind(), 1, true, false)
2306            .expect("sll start transition");
2307        assert!(matches!(
2308            sll_start.semantic_context,
2309            SemanticContext::Precedence { precedence: 2 }
2310        ));
2311
2312        let full_context_start = simulator
2313            .epsilon_target_config(&config, transition, transition.kind(), 1, true, true)
2314            .expect("full-context start transition");
2315        assert!(full_context_start.semantic_context.is_none());
2316
2317        let reach = simulator
2318            .epsilon_target_config(&config, transition, transition.kind(), 3, false, false)
2319            .expect("reach transition");
2320        assert!(reach.semantic_context.is_none());
2321
2322        assert!(
2323            simulator
2324                .epsilon_target_config(&config, transition, transition.kind(), 3, true, false)
2325                .is_none()
2326        );
2327    }
2328
2329    #[test]
2330    fn closure_stops_collecting_predicates_after_action_edge() {
2331        // ANTLR's `closure_` sets
2332        // `continueCollecting = collectPredicates && !ActionTransition`, so a
2333        // predicate reached *after* an action edge is NOT folded into the
2334        // config's semantic context — it is deferred to parse time (the
2335        // "action hides predicates" rule). Build `0 -Action-> 1 -Pred-> 2` and
2336        // assert the closure config carries NO semantic context.
2337        let mut atn = ParserAtnBuilder::new(1);
2338        add_state(&mut atn, 0, AtnStateKind::Basic);
2339        add_state(&mut atn, 1, AtnStateKind::Basic);
2340        add_state(&mut atn, 2, AtnStateKind::Basic);
2341        add_state(&mut atn, 3, AtnStateKind::Basic);
2342        atn.add_transition(
2343            0,
2344            ParserTransitionSpec::Action {
2345                target: 1,
2346                rule_index: 0,
2347                action_index: Some(0),
2348                context_dependent: false,
2349            },
2350        )
2351        .expect("transition");
2352        atn.add_transition(
2353            1,
2354            ParserTransitionSpec::Predicate {
2355                target: 2,
2356                rule_index: 0,
2357                pred_index: 0,
2358                context_dependent: false,
2359            },
2360        )
2361        .expect("transition");
2362        atn.add_transition(
2363            2,
2364            ParserTransitionSpec::Atom {
2365                target: 3,
2366                label: 1,
2367            },
2368        )
2369        .expect("transition");
2370        atn.set_rule_to_start_state(vec![0])
2371            .expect("rule start states");
2372        atn.set_rule_to_stop_state(vec![3])
2373            .expect("rule stop states");
2374        let atn = finish_atn(atn);
2375
2376        let mut simulator = ParserAtnSimulator::new(&atn);
2377        let mut configs = AtnConfigSet::new();
2378        let mut merge_cache = PredictionWorkspace::default();
2379        let mut scratch = ClosureScratch::default();
2380        let config = AtnConfig::new(0, 1, EMPTY_CONTEXT, &simulator.store.contexts);
2381        simulator.closure(
2382            config,
2383            &mut configs,
2384            &mut merge_cache,
2385            &mut scratch,
2386            ClosureParams {
2387                precedence: 0,
2388                collect_predicates: true,
2389                treat_eof_as_epsilon: false,
2390            },
2391        );
2392
2393        // The config that stops at state 2 (post-predicate, awaiting the atom)
2394        // must NOT carry the predicate — the action edge turned collection off.
2395        let at_two = configs
2396            .configs()
2397            .iter()
2398            .find(|config| config.state == 2)
2399            .expect("config at state 2");
2400        assert!(
2401            at_two.semantic_context.is_none(),
2402            "predicate after an action edge must not be collected during prediction"
2403        );
2404
2405        // Control: the SAME predicate reached WITHOUT an intervening action edge
2406        // IS collected (so the assertion above is about the action edge, not a
2407        // blanket failure to collect predicates).
2408        let direct_config = AtnConfig::new(1, 1, EMPTY_CONTEXT, &simulator.store.contexts);
2409        let direct_transition = atn
2410            .state(1)
2411            .expect("predicate source")
2412            .transitions()
2413            .first()
2414            .expect("predicate transition");
2415        let direct = simulator
2416            .epsilon_target_config(
2417                &direct_config,
2418                direct_transition,
2419                direct_transition.kind(),
2420                0,
2421                true,
2422                false,
2423            )
2424            .expect("predicate transition");
2425        assert!(matches!(
2426            direct.semantic_context,
2427            SemanticContext::Predicate { pred_index: 0, .. }
2428        ));
2429    }
2430
2431    #[test]
2432    fn reach_set_skips_closure_for_unique_intermediate_alt() {
2433        let mut atn = ParserAtnBuilder::new(1);
2434        add_state(&mut atn, 0, AtnStateKind::Basic);
2435        add_state(&mut atn, 1, AtnStateKind::Basic);
2436        add_state(&mut atn, 2, AtnStateKind::Basic);
2437        atn.add_transition(
2438            0,
2439            ParserTransitionSpec::Atom {
2440                target: 1,
2441                label: 7,
2442            },
2443        )
2444        .expect("transition");
2445        atn.add_transition(1, ParserTransitionSpec::Epsilon { target: 2 })
2446            .expect("transition");
2447        atn.set_rule_to_start_state(vec![0])
2448            .expect("rule start states");
2449        atn.set_rule_to_stop_state(vec![2])
2450            .expect("rule stop states");
2451        let atn = finish_atn(atn);
2452
2453        let mut simulator = ParserAtnSimulator::new(&atn);
2454        let mut configs = AtnConfigSet::new_full_context(false);
2455        let mut merge_cache = PredictionWorkspace::default();
2456        configs.add(
2457            AtnConfig::new(0, 1, EMPTY_CONTEXT, &simulator.store.contexts),
2458            &mut simulator.store.contexts,
2459            &mut merge_cache,
2460        );
2461
2462        let reach = simulator.compute_reach_set(&configs, 7, false, 0, &mut merge_cache);
2463
2464        assert_eq!(reach.len(), 1);
2465        assert_eq!(reach.configs()[0].state, 1);
2466    }
2467
2468    #[test]
2469    fn semantic_context_flag_is_scoped_to_predicted_alt() {
2470        let mut arena = ContextArena::new();
2471        let mut workspace = PredictionWorkspace::default();
2472        let mut configs = AtnConfigSet::new();
2473        configs.add(
2474            AtnConfig::new(1, 1, EMPTY_CONTEXT, &arena),
2475            &mut arena,
2476            &mut workspace,
2477        );
2478        configs.add(
2479            AtnConfig::new(2, 2, EMPTY_CONTEXT, &arena).with_semantic_context(
2480                SemanticContext::Predicate {
2481                    rule_index: 0,
2482                    pred_index: 0,
2483                    context_dependent: false,
2484                },
2485            ),
2486            &mut arena,
2487            &mut workspace,
2488        );
2489
2490        assert!(!configs_have_semantic_context_for_alt(&configs, 1));
2491        assert!(configs_have_semantic_context_for_alt(&configs, 2));
2492    }
2493
2494    #[test]
2495    fn adaptive_predict_prefers_non_greedy_exit_before_consuming() {
2496        let atn = non_greedy_optional_exit_first_atn();
2497        let mut simulator = ParserAtnSimulator::new(&atn);
2498
2499        assert_eq!(simulator.adaptive_predict(0, [1, TOKEN_EOF]), Ok(1));
2500    }
2501
2502    #[test]
2503    fn left_recursive_loop_entry_drop_requires_same_rule_return() {
2504        let atn = left_recursive_loop_entry_atn();
2505        let loop_entry = atn.state(1).expect("loop entry");
2506        let mut contexts = ContextArena::new();
2507        let same_rule_context = contexts.singleton(EMPTY_CONTEXT, 4);
2508        let other_rule_context = contexts.singleton(EMPTY_CONTEXT, 5);
2509
2510        assert!(can_drop_left_recursive_loop_entry_edge(
2511            &atn,
2512            loop_entry,
2513            &contexts,
2514            same_rule_context
2515        ));
2516        assert!(!can_drop_left_recursive_loop_entry_edge(
2517            &atn,
2518            loop_entry,
2519            &contexts,
2520            other_rule_context
2521        ));
2522        assert!(!can_drop_left_recursive_loop_entry_edge(
2523            &atn,
2524            loop_entry,
2525            &contexts,
2526            EMPTY_CONTEXT
2527        ));
2528    }
2529
2530    fn two_token_decision_atn() -> Atn {
2531        two_token_decision_atn_with_precedence(false)
2532    }
2533
2534    fn two_token_decision_atn_with_precedence(precedence: bool) -> Atn {
2535        let mut atn = ParserAtnBuilder::new(3);
2536        add_state(&mut atn, 0, AtnStateKind::RuleStart);
2537        add_state(&mut atn, 1, AtnStateKind::BlockStart);
2538        add_state(&mut atn, 2, AtnStateKind::Basic);
2539        add_state(&mut atn, 3, AtnStateKind::Basic);
2540        add_state(&mut atn, 4, AtnStateKind::Basic);
2541        add_state(&mut atn, 5, AtnStateKind::Basic);
2542        add_state(&mut atn, 6, AtnStateKind::BlockEnd);
2543        add_state(&mut atn, 7, AtnStateKind::RuleStop);
2544        atn.set_rule_to_start_state(vec![0])
2545            .expect("rule start states");
2546        atn.set_rule_to_stop_state(vec![7])
2547            .expect("rule stop states");
2548        atn.add_decision_state(1).expect("decision state");
2549        if precedence {
2550            atn.set_precedence_rule_decision(1)
2551                .expect("precedence decision state");
2552        }
2553        atn.add_transition(0, ParserTransitionSpec::Epsilon { target: 1 })
2554            .expect("transition");
2555        atn.add_transition(1, ParserTransitionSpec::Epsilon { target: 2 })
2556            .expect("transition");
2557        atn.add_transition(1, ParserTransitionSpec::Epsilon { target: 4 })
2558            .expect("transition");
2559        atn.add_transition(
2560            2,
2561            ParserTransitionSpec::Atom {
2562                target: 3,
2563                label: 1,
2564            },
2565        )
2566        .expect("transition");
2567        atn.add_transition(
2568            3,
2569            ParserTransitionSpec::Atom {
2570                target: 6,
2571                label: 2,
2572            },
2573        )
2574        .expect("transition");
2575        atn.add_transition(
2576            4,
2577            ParserTransitionSpec::Atom {
2578                target: 5,
2579                label: 1,
2580            },
2581        )
2582        .expect("transition");
2583        atn.add_transition(
2584            5,
2585            ParserTransitionSpec::Atom {
2586                target: 6,
2587                label: 3,
2588            },
2589        )
2590        .expect("transition");
2591        atn.add_transition(6, ParserTransitionSpec::Epsilon { target: 7 })
2592            .expect("transition");
2593        finish_atn(atn)
2594    }
2595
2596    fn optional_token_decision_atn() -> Atn {
2597        let mut atn = ParserAtnBuilder::new(1);
2598        add_state(&mut atn, 0, AtnStateKind::RuleStart);
2599        add_state(&mut atn, 1, AtnStateKind::BlockStart);
2600        add_state(&mut atn, 2, AtnStateKind::Basic);
2601        add_state(&mut atn, 3, AtnStateKind::BlockEnd);
2602        add_state(&mut atn, 4, AtnStateKind::RuleStop);
2603        atn.set_rule_to_start_state(vec![0])
2604            .expect("rule start states");
2605        atn.set_rule_to_stop_state(vec![4])
2606            .expect("rule stop states");
2607        atn.add_decision_state(1).expect("decision state");
2608        atn.add_transition(0, ParserTransitionSpec::Epsilon { target: 1 })
2609            .expect("transition");
2610        atn.add_transition(1, ParserTransitionSpec::Epsilon { target: 2 })
2611            .expect("transition");
2612        atn.add_transition(1, ParserTransitionSpec::Epsilon { target: 3 })
2613            .expect("transition");
2614        atn.add_transition(
2615            2,
2616            ParserTransitionSpec::Atom {
2617                target: 3,
2618                label: 1,
2619            },
2620        )
2621        .expect("transition");
2622        atn.add_transition(3, ParserTransitionSpec::Epsilon { target: 4 })
2623            .expect("transition");
2624        finish_atn(atn)
2625    }
2626
2627    fn non_greedy_optional_exit_first_atn() -> Atn {
2628        let mut atn = ParserAtnBuilder::new(1);
2629        add_state(&mut atn, 0, AtnStateKind::RuleStart);
2630        add_state(&mut atn, 1, AtnStateKind::BlockStart);
2631        add_state(&mut atn, 2, AtnStateKind::BlockEnd);
2632        add_state(&mut atn, 3, AtnStateKind::Basic);
2633        add_state(&mut atn, 4, AtnStateKind::RuleStop);
2634        atn.set_rule_to_start_state(vec![0])
2635            .expect("rule start states");
2636        atn.set_rule_to_stop_state(vec![4])
2637            .expect("rule stop states");
2638        atn.add_decision_state(1).expect("decision state");
2639        atn.set_non_greedy(1).expect("non-greedy state");
2640        atn.add_transition(0, ParserTransitionSpec::Epsilon { target: 1 })
2641            .expect("transition");
2642        atn.add_transition(1, ParserTransitionSpec::Epsilon { target: 2 })
2643            .expect("transition");
2644        atn.add_transition(1, ParserTransitionSpec::Epsilon { target: 3 })
2645            .expect("transition");
2646        atn.add_transition(2, ParserTransitionSpec::Epsilon { target: 4 })
2647            .expect("transition");
2648        atn.add_transition(
2649            3,
2650            ParserTransitionSpec::Atom {
2651                target: 4,
2652                label: 1,
2653            },
2654        )
2655        .expect("transition");
2656        finish_atn(atn)
2657    }
2658
2659    fn ambiguous_single_token_decision_atn() -> Atn {
2660        let mut atn = ParserAtnBuilder::new(1);
2661        add_state(&mut atn, 0, AtnStateKind::RuleStart);
2662        add_state(&mut atn, 1, AtnStateKind::BlockStart);
2663        add_state(&mut atn, 2, AtnStateKind::Basic);
2664        add_state(&mut atn, 3, AtnStateKind::Basic);
2665        add_state(&mut atn, 4, AtnStateKind::Basic);
2666        add_state(&mut atn, 5, AtnStateKind::Basic);
2667        add_state(&mut atn, 6, AtnStateKind::BlockEnd);
2668        add_state(&mut atn, 7, AtnStateKind::RuleStop);
2669        atn.set_rule_to_start_state(vec![0])
2670            .expect("rule start states");
2671        atn.set_rule_to_stop_state(vec![7])
2672            .expect("rule stop states");
2673        atn.add_decision_state(1).expect("decision state");
2674        atn.add_transition(0, ParserTransitionSpec::Epsilon { target: 1 })
2675            .expect("transition");
2676        atn.add_transition(1, ParserTransitionSpec::Epsilon { target: 2 })
2677            .expect("transition");
2678        atn.add_transition(1, ParserTransitionSpec::Epsilon { target: 4 })
2679            .expect("transition");
2680        atn.add_transition(
2681            2,
2682            ParserTransitionSpec::Atom {
2683                target: 3,
2684                label: 1,
2685            },
2686        )
2687        .expect("transition");
2688        atn.add_transition(3, ParserTransitionSpec::Epsilon { target: 6 })
2689            .expect("transition");
2690        atn.add_transition(
2691            4,
2692            ParserTransitionSpec::Atom {
2693                target: 5,
2694                label: 1,
2695            },
2696        )
2697        .expect("transition");
2698        atn.add_transition(5, ParserTransitionSpec::Epsilon { target: 6 })
2699            .expect("transition");
2700        atn.add_transition(6, ParserTransitionSpec::Epsilon { target: 7 })
2701            .expect("transition");
2702        finish_atn(atn)
2703    }
2704
2705    fn prefix_alt_decision_atn() -> Atn {
2706        let mut atn = ParserAtnBuilder::new(3);
2707        add_state(&mut atn, 0, AtnStateKind::BlockStart);
2708        add_state(&mut atn, 1, AtnStateKind::Basic);
2709        add_state(&mut atn, 2, AtnStateKind::RuleStop);
2710        atn.set_rule_to_start_state(vec![0])
2711            .expect("rule start states");
2712        atn.set_rule_to_stop_state(vec![2])
2713            .expect("rule stop states");
2714        atn.add_decision_state(0).expect("decision state");
2715        atn.add_transition(
2716            0,
2717            ParserTransitionSpec::Atom {
2718                target: 2,
2719                label: 1,
2720            },
2721        )
2722        .expect("transition");
2723        atn.add_transition(
2724            0,
2725            ParserTransitionSpec::Atom {
2726                target: 1,
2727                label: 1,
2728            },
2729        )
2730        .expect("transition");
2731        atn.add_transition(
2732            1,
2733            ParserTransitionSpec::Atom {
2734                target: 2,
2735                label: 2,
2736            },
2737        )
2738        .expect("transition");
2739        finish_atn(atn)
2740    }
2741
2742    fn three_token_prefix_alt_decision_atn() -> Atn {
2743        let mut atn = ParserAtnBuilder::new(2);
2744        for (state_number, kind) in [
2745            (0, AtnStateKind::BlockStart),
2746            (1, AtnStateKind::Basic),
2747            (2, AtnStateKind::Basic),
2748            (3, AtnStateKind::Basic),
2749            (4, AtnStateKind::Basic),
2750            (5, AtnStateKind::Basic),
2751            (6, AtnStateKind::RuleStop),
2752        ] {
2753            add_state(&mut atn, state_number, kind);
2754        }
2755        atn.set_rule_to_start_state(vec![0])
2756            .expect("rule start states");
2757        atn.set_rule_to_stop_state(vec![6])
2758            .expect("rule stop states");
2759        atn.add_decision_state(0).expect("decision state");
2760        atn.add_transition(0, ParserTransitionSpec::Epsilon { target: 1 })
2761            .expect("transition");
2762        atn.add_transition(0, ParserTransitionSpec::Epsilon { target: 2 })
2763            .expect("transition");
2764        atn.add_transition(
2765            1,
2766            ParserTransitionSpec::Atom {
2767                target: 6,
2768                label: 1,
2769            },
2770        )
2771        .expect("transition");
2772        atn.add_transition(
2773            2,
2774            ParserTransitionSpec::Atom {
2775                target: 3,
2776                label: 1,
2777            },
2778        )
2779        .expect("transition");
2780        atn.add_transition(
2781            3,
2782            ParserTransitionSpec::Atom {
2783                target: 4,
2784                label: 2,
2785            },
2786        )
2787        .expect("transition");
2788        atn.add_transition(
2789            4,
2790            ParserTransitionSpec::Atom {
2791                target: 5,
2792                label: 1,
2793            },
2794        )
2795        .expect("transition");
2796        atn.add_transition(5, ParserTransitionSpec::Epsilon { target: 6 })
2797            .expect("transition");
2798        finish_atn(atn)
2799    }
2800
2801    fn multiple_eof_decision_atn() -> Atn {
2802        let mut atn = ParserAtnBuilder::new(2);
2803        for state_number in 0..=10 {
2804            let kind = match state_number {
2805                0 => AtnStateKind::RuleStart,
2806                1 => AtnStateKind::BlockStart,
2807                7 => AtnStateKind::BlockEnd,
2808                10 => AtnStateKind::RuleStop,
2809                _ => AtnStateKind::Basic,
2810            };
2811            add_state(&mut atn, state_number, kind);
2812        }
2813        atn.set_rule_to_start_state(vec![0])
2814            .expect("rule start states");
2815        atn.set_rule_to_stop_state(vec![10])
2816            .expect("rule stop states");
2817        atn.add_decision_state(1).expect("decision state");
2818        atn.add_transition(0, ParserTransitionSpec::Epsilon { target: 1 })
2819            .expect("transition");
2820        atn.add_transition(1, ParserTransitionSpec::Epsilon { target: 2 })
2821            .expect("transition");
2822        atn.add_transition(1, ParserTransitionSpec::Epsilon { target: 4 })
2823            .expect("transition");
2824        atn.add_transition(
2825            2,
2826            ParserTransitionSpec::Atom {
2827                target: 3,
2828                label: 1,
2829            },
2830        )
2831        .expect("transition");
2832        atn.add_transition(3, ParserTransitionSpec::Epsilon { target: 7 })
2833            .expect("transition");
2834        atn.add_transition(
2835            4,
2836            ParserTransitionSpec::Atom {
2837                target: 5,
2838                label: 1,
2839            },
2840        )
2841        .expect("transition");
2842        atn.add_transition(
2843            5,
2844            ParserTransitionSpec::Atom {
2845                target: 6,
2846                label: 2,
2847            },
2848        )
2849        .expect("transition");
2850        atn.add_transition(6, ParserTransitionSpec::Epsilon { target: 7 })
2851            .expect("transition");
2852        atn.add_transition(7, ParserTransitionSpec::Epsilon { target: 8 })
2853            .expect("transition");
2854        atn.add_transition(
2855            8,
2856            ParserTransitionSpec::Atom {
2857                target: 9,
2858                label: TOKEN_EOF,
2859            },
2860        )
2861        .expect("transition");
2862        atn.add_transition(
2863            9,
2864            ParserTransitionSpec::Atom {
2865                target: 10,
2866                label: TOKEN_EOF,
2867            },
2868        )
2869        .expect("transition");
2870        finish_atn(atn)
2871    }
2872
2873    fn left_recursive_loop_entry_atn() -> Atn {
2874        let mut atn = ParserAtnBuilder::new(1);
2875        add_state(&mut atn, 0, AtnStateKind::RuleStart);
2876        add_state(&mut atn, 1, AtnStateKind::StarLoopEntry);
2877        add_state(&mut atn, 2, AtnStateKind::BlockStart);
2878        add_state(&mut atn, 3, AtnStateKind::BlockEnd);
2879        add_state(&mut atn, 4, AtnStateKind::Basic);
2880        assert_eq!(
2881            atn.add_state(AtnStateKind::Basic, Some(1))
2882                .expect("state")
2883                .index(),
2884            5
2885        );
2886        add_state(&mut atn, 6, AtnStateKind::LoopEnd);
2887        add_state(&mut atn, 7, AtnStateKind::RuleStop);
2888        atn.set_rule_to_start_state(vec![0, 5])
2889            .expect("rule start states");
2890        atn.set_rule_to_stop_state(vec![7, 7])
2891            .expect("rule stop states");
2892        atn.set_precedence_rule_decision(1)
2893            .expect("precedence decision state");
2894        atn.set_end_state(2, 3).expect("block end state");
2895        atn.add_transition(1, ParserTransitionSpec::Epsilon { target: 2 })
2896            .expect("transition");
2897        atn.add_transition(1, ParserTransitionSpec::Epsilon { target: 6 })
2898            .expect("transition");
2899        atn.add_transition(4, ParserTransitionSpec::Epsilon { target: 3 })
2900            .expect("transition");
2901        atn.add_transition(5, ParserTransitionSpec::Epsilon { target: 3 })
2902            .expect("transition");
2903        finish_atn(atn)
2904    }
2905
2906    fn add_state(atn: &mut ParserAtnBuilder, state_number: usize, kind: AtnStateKind) {
2907        assert_eq!(
2908            atn.add_state(kind, Some(0)).expect("state").index(),
2909            state_number
2910        );
2911    }
2912
2913    #[derive(Debug)]
2914    struct VecIntStream {
2915        symbols: Vec<i32>,
2916        index: usize,
2917    }
2918
2919    impl VecIntStream {
2920        fn new(symbols: Vec<i32>) -> Self {
2921            Self { symbols, index: 0 }
2922        }
2923    }
2924
2925    impl IntStream for VecIntStream {
2926        fn consume(&mut self) {
2927            if self.la(1) != TOKEN_EOF {
2928                self.index += 1;
2929            }
2930        }
2931
2932        fn la(&mut self, offset: isize) -> i32 {
2933            if offset <= 0 {
2934                return 0;
2935            }
2936            let offset = offset.cast_unsigned() - 1;
2937            self.symbols
2938                .get(self.index + offset)
2939                .copied()
2940                .unwrap_or(TOKEN_EOF)
2941        }
2942
2943        fn index(&self) -> usize {
2944            self.index
2945        }
2946
2947        fn seek(&mut self, index: usize) {
2948            self.index = index;
2949        }
2950
2951        fn size(&self) -> usize {
2952            self.symbols.len()
2953        }
2954    }
2955}