Skip to main content

antlr4_runtime/atn/
parser.rs

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