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,
755                    exact,
756                    alts.clone(),
757                ),
758                // A unique full-context alt after an SLL conflict is Java's
759                // reportContextSensitivity; the SLL state's conflicting alts
760                // describe the conflict that forced the retry.
761                FullContextResolution::Unique => (
762                    ParserAtnPredictionDiagnosticKind::ContextSensitivity,
763                    false,
764                    info.conflicting_alts,
765                ),
766            };
767            let mut prediction = full_context.prediction;
768            if conflicting_alts.len() > 1 {
769                prediction.diagnostic = Some(ParserAtnPredictionDiagnostic {
770                    kind,
771                    start_index,
772                    sll_stop_index,
773                    ll_stop_index: full_context.stop_index,
774                    conflicting_alts,
775                    exact,
776                });
777            }
778            return Ok(Some(prediction));
779        }
780        Ok(Some(prediction))
781    }
782
783    fn non_greedy_exit_prediction(
784        &self,
785        decision: usize,
786        decision_state: usize,
787        state_number: usize,
788    ) -> Option<ParserAtnPrediction> {
789        if !self
790            .atn
791            .state(decision_state)
792            .is_some_and(|state| state.non_greedy)
793        {
794            return None;
795        }
796        let configs = &self
797            .decision_to_dfa
798            .get(decision)?
799            .state(state_number)?
800            .configs;
801        let alt = configs
802            .configs()
803            .iter()
804            .filter(|config| {
805                self.atn
806                    .state(config.state)
807                    .is_some_and(AtnState::is_rule_stop)
808                    && config.context.has_empty_path()
809            })
810            .map(|config| config.alt)
811            .min()?;
812        Some(ParserAtnPrediction {
813            alt,
814            requires_full_context: false,
815            has_semantic_context: configs_have_semantic_context_for_alt(configs, alt),
816            diagnostic: None,
817        })
818    }
819
820    fn ensure_start_state(
821        &mut self,
822        decision: usize,
823        decision_state: usize,
824        precedence: i32,
825        merge_cache: &mut PredictionContextMergeCache,
826    ) -> Result<usize, ParserAtnSimulatorError> {
827        if self.decision_to_dfa[decision].is_precedence_dfa() {
828            let precedence_key = usize::try_from(precedence.max(0)).unwrap_or_default();
829            if let Some(start) =
830                self.decision_to_dfa[decision].precedence_start_state(precedence_key)
831            {
832                return Ok(start);
833            }
834        } else if let Some(start) = self.decision_to_dfa[decision].start_state() {
835            return Ok(start);
836        }
837        let decision_state = self
838            .atn
839            .state(decision_state)
840            .ok_or(ParserAtnSimulatorError::MissingAtnState(decision_state))?;
841        let configs = self.compute_start_state(decision_state, precedence, merge_cache);
842        let state_number = self.add_dfa_state(decision, DfaState::new(configs));
843        if self.decision_to_dfa[decision].is_precedence_dfa() {
844            let precedence_key = usize::try_from(precedence.max(0)).unwrap_or_default();
845            self.decision_to_dfa[decision].set_precedence_start_state(precedence_key, state_number);
846        } else {
847            self.decision_to_dfa[decision].set_start_state(state_number);
848        }
849        Ok(state_number)
850    }
851
852    fn add_dfa_state(&mut self, decision: usize, mut state: DfaState) -> usize {
853        if state.configs.is_readonly() {
854            return self.decision_to_dfa[decision].add_state(state);
855        }
856        if let Some(existing) =
857            self.decision_to_dfa[decision].state_number_for_configs(&state.configs)
858        {
859            return existing;
860        }
861        state
862            .configs
863            .optimize_contexts(&mut self.context_cache.borrow_mut());
864        self.decision_to_dfa[decision].insert_state(state)
865    }
866
867    fn compute_start_state(
868        &self,
869        decision_state: &AtnState,
870        precedence: i32,
871        merge_cache: &mut PredictionContextMergeCache,
872    ) -> AtnConfigSet {
873        let empty = PredictionContext::empty();
874        self.compute_start_state_with_context(
875            decision_state,
876            false,
877            &empty,
878            precedence,
879            merge_cache,
880        )
881    }
882
883    fn compute_start_state_with_context(
884        &self,
885        decision_state: &AtnState,
886        full_context: bool,
887        initial_context: &Rc<PredictionContext>,
888        precedence: i32,
889        merge_cache: &mut PredictionContextMergeCache,
890    ) -> AtnConfigSet {
891        let mut configs = AtnConfigSet::new_full_context(full_context);
892        let mut scratch = ClosureScratch::default();
893        let params = ClosureParams {
894            precedence,
895            collect_predicates: true,
896            treat_eof_as_epsilon: false,
897        };
898        for (index, transition) in decision_state.transitions.iter().enumerate() {
899            let alt = index + 1;
900            let config = AtnConfig::new(transition.target(), alt, Rc::clone(initial_context));
901            self.closure(config, &mut configs, merge_cache, &mut scratch, params);
902        }
903        configs
904    }
905
906    fn adaptive_predict_full_context<T: IntStream>(
907        &self,
908        decision_state: usize,
909        input: &mut T,
910        precedence: i32,
911        outer_context: &Rc<PredictionContext>,
912        merge_cache: &mut PredictionContextMergeCache,
913    ) -> Result<FullContextPrediction, ParserAtnSimulatorError> {
914        let decision_state = self
915            .atn
916            .state(decision_state)
917            .ok_or(ParserAtnSimulatorError::MissingAtnState(decision_state))?;
918        let mut configs = self.compute_start_state_with_context(
919            decision_state,
920            true,
921            outer_context,
922            precedence,
923            merge_cache,
924        );
925        // Java's `execATNWithFullContext`: after each reach set a truly
926        // unique alt resolves as context sensitivity. Otherwise default LL
927        // mode stops at the first "resolves to just one viable alt" conflict
928        // — reported as a NON-exact ambiguity, which the exactOnly listener
929        // suppresses — while LL_EXACT_AMBIG_DETECTION keeps consuming until
930        // every (state, context) subset conflicts over the same alt set: an
931        // exact ambiguity.
932        loop {
933            if let Some(alt) = configs.unique_alt() {
934                return Ok(full_context_prediction(
935                    alt,
936                    &configs,
937                    input.index(),
938                    FullContextResolution::Unique,
939                ));
940            }
941            let symbol = input.la(1);
942            let reach = self.compute_reach_set(&configs, symbol, true, precedence, merge_cache);
943            if reach.is_empty() {
944                return Err(ParserAtnSimulatorError::NoViableAlt {
945                    symbol,
946                    index: input.index(),
947                });
948            }
949            configs = reach;
950            if let Some(alt) = configs.unique_alt() {
951                return Ok(full_context_prediction(
952                    alt,
953                    &configs,
954                    input.index(),
955                    FullContextResolution::Unique,
956                ));
957            }
958            if !configs.has_semantic_context() {
959                let subsets = conflicting_alt_subsets(configs.configs());
960                if self.exact_ambig_detection {
961                    let alts: Vec<usize> = configs.alts().into_iter().collect();
962                    // Both subset checks hold vacuously for an empty list; a
963                    // real exact ambiguity always carries alternatives, so
964                    // guard the pick instead of indexing.
965                    if all_subsets_conflict(&subsets)
966                        && all_subsets_equal(&subsets)
967                        && let Some(&alt) = alts.first()
968                    {
969                        return Ok(full_context_prediction(
970                            alt,
971                            &configs,
972                            input.index(),
973                            FullContextResolution::Ambiguous { exact: true, alts },
974                        ));
975                    }
976                } else if let Some(alt) = single_viable_alt(&subsets) {
977                    let alts: Vec<usize> = configs.alts().into_iter().collect();
978                    return Ok(full_context_prediction(
979                        alt,
980                        &configs,
981                        input.index(),
982                        FullContextResolution::Ambiguous { exact: false, alts },
983                    ));
984                }
985            }
986            if symbol == TOKEN_EOF || self.configs_all_reached_rule_stop(&configs) {
987                // Safety net Java reaches implicitly: at EOF every surviving
988                // path sits in a rule-stop config, so the checks above
989                // resolve; guard against pathological sets instead of
990                // spinning on an unconsumable EOF.
991                let alts: Vec<usize> = configs.alts().into_iter().collect();
992                let alt = *alts
993                    .first()
994                    .ok_or(ParserAtnSimulatorError::PredictionRequiresMoreLookahead)?;
995                let resolution = if alts.len() > 1 {
996                    FullContextResolution::Ambiguous {
997                        exact: self.exact_ambig_detection,
998                        alts,
999                    }
1000                } else {
1001                    FullContextResolution::Unique
1002                };
1003                return Ok(full_context_prediction(
1004                    alt,
1005                    &configs,
1006                    input.index(),
1007                    resolution,
1008                ));
1009            }
1010            input.consume();
1011        }
1012    }
1013
1014    fn compute_target_state(
1015        &mut self,
1016        edge: DfaEdge,
1017        configs: &AtnConfigSet,
1018        symbol: i32,
1019        precedence: i32,
1020        merge_cache: &mut PredictionContextMergeCache,
1021    ) -> Result<usize, ParserAtnSimulatorError> {
1022        let mut reach = self.compute_reach_set(configs, symbol, false, precedence, merge_cache);
1023        if reach.is_empty() {
1024            if let Some(prediction) = self.alt_that_finished_decision_entry_rule(configs) {
1025                let mut dfa_state = DfaState::new(configs.clone());
1026                dfa_state.mark_accept(prediction);
1027                // The set-wide flag gates the per-alt scan: if no config in the
1028                // set carries a semantic context, no alt can either.
1029                dfa_state.has_semantic_context_for_alt = dfa_state.configs.has_semantic_context()
1030                    && configs_have_semantic_context_for_alt(&dfa_state.configs, prediction);
1031                let target_state = self.add_dfa_state(edge.decision, dfa_state);
1032                if let Some(source) =
1033                    self.decision_to_dfa[edge.decision].state_mut(edge.source_state)
1034                {
1035                    source.add_edge(symbol, target_state);
1036                }
1037                return Ok(target_state);
1038            }
1039            return Err(ParserAtnSimulatorError::NoViableAlt { symbol, index: 0 });
1040        }
1041        let prediction = reach.unique_alt();
1042        let conflict_prediction = prediction.or_else(|| {
1043            if !has_sll_conflict_terminating_prediction(&reach, |state| {
1044                self.atn.state(state).is_some_and(AtnState::is_rule_stop)
1045            }) {
1046                return None;
1047            }
1048            reach
1049                .conflicting_alts()
1050                .into_iter()
1051                .next()
1052                .or_else(|| reach.alts().into_iter().next())
1053        });
1054        let requires_full_context = prediction.is_none() && conflict_prediction.is_some();
1055        #[cfg(feature = "perf-counters")]
1056        if requires_full_context {
1057            crate::perf::record_sll_conflict(edge.decision);
1058        }
1059        let conflicting_alts = if requires_full_context {
1060            let alts = reach.conflicting_alts();
1061            if alts.is_empty() { reach.alts() } else { alts }
1062                .into_iter()
1063                .collect()
1064        } else {
1065            Vec::new()
1066        };
1067        let mut dfa_state = DfaState::new(reach);
1068        if let Some(prediction) = conflict_prediction {
1069            dfa_state.mark_accept(prediction);
1070            dfa_state.requires_full_context = requires_full_context;
1071            dfa_state.conflicting_alts = conflicting_alts;
1072            // The set-wide flag gates the per-alt scan: if no config in the set
1073            // carries a semantic context, no alt can either.
1074            dfa_state.has_semantic_context_for_alt = dfa_state.configs.has_semantic_context()
1075                && configs_have_semantic_context_for_alt(&dfa_state.configs, prediction);
1076        }
1077        let target_state = self.add_dfa_state(edge.decision, dfa_state);
1078        if let Some(source) = self.decision_to_dfa[edge.decision].state_mut(edge.source_state) {
1079            source.add_edge(symbol, target_state);
1080        }
1081        Ok(target_state)
1082    }
1083
1084    fn compute_reach_set(
1085        &self,
1086        configs: &AtnConfigSet,
1087        symbol: i32,
1088        full_context: bool,
1089        precedence: i32,
1090        merge_cache: &mut PredictionContextMergeCache,
1091    ) -> AtnConfigSet {
1092        let mut intermediate = AtnConfigSet::new_full_context(full_context);
1093        let mut skipped_stop_states = Vec::new();
1094        for config in configs.configs() {
1095            let Some(state) = self.atn.state(config.state) else {
1096                continue;
1097            };
1098            if state.is_rule_stop() {
1099                if full_context || symbol == TOKEN_EOF {
1100                    skipped_stop_states.push(config.clone());
1101                }
1102                continue;
1103            }
1104            for transition in &state.transitions {
1105                if transition.matches(symbol, 1, self.atn.max_token_type()) {
1106                    let target = AtnConfig {
1107                        state: transition.target(),
1108                        alt: config.alt,
1109                        context: Rc::clone(&config.context),
1110                        semantic_context: config.semantic_context.clone(),
1111                        reaches_into_outer_context: config.reaches_into_outer_context,
1112                        precedence_filter_suppressed: config.precedence_filter_suppressed,
1113                    };
1114                    intermediate.add_with_merge_cache(target, Some(merge_cache));
1115                }
1116            }
1117        }
1118        let mut reach = if skipped_stop_states.is_empty() && symbol != TOKEN_EOF {
1119            if intermediate.len() == 1 || intermediate.unique_alt().is_some() {
1120                intermediate
1121            } else {
1122                self.close_intermediate_reach_set(
1123                    intermediate,
1124                    full_context,
1125                    precedence,
1126                    symbol,
1127                    merge_cache,
1128                )
1129            }
1130        } else {
1131            self.close_intermediate_reach_set(
1132                intermediate,
1133                full_context,
1134                precedence,
1135                symbol,
1136                merge_cache,
1137            )
1138        };
1139        if symbol == TOKEN_EOF {
1140            reach = self.rule_stop_configs(reach, merge_cache);
1141        }
1142        if !full_context || !self.configs_contain_rule_stop(&reach) {
1143            for config in skipped_stop_states {
1144                reach.add_with_merge_cache(config, Some(merge_cache));
1145            }
1146        }
1147        #[cfg(feature = "perf-counters")]
1148        crate::perf::record_reach_set(full_context, configs.len(), reach.len());
1149        reach
1150    }
1151
1152    fn close_intermediate_reach_set(
1153        &self,
1154        intermediate: AtnConfigSet,
1155        full_context: bool,
1156        precedence: i32,
1157        symbol: i32,
1158        merge_cache: &mut PredictionContextMergeCache,
1159    ) -> AtnConfigSet {
1160        let mut reach = AtnConfigSet::new_full_context(full_context);
1161        let mut scratch = ClosureScratch::default();
1162        let params = ClosureParams {
1163            precedence,
1164            collect_predicates: false,
1165            treat_eof_as_epsilon: symbol == TOKEN_EOF,
1166        };
1167        // `closure` takes `AtnConfig` by value, so drain the intermediate set by
1168        // move instead of cloning each config.
1169        for config in intermediate.into_configs() {
1170            self.closure(config, &mut reach, merge_cache, &mut scratch, params);
1171        }
1172        reach
1173    }
1174
1175    fn alt_that_finished_decision_entry_rule(&self, configs: &AtnConfigSet) -> Option<usize> {
1176        configs
1177            .configs()
1178            .iter()
1179            .filter(|config| {
1180                config.reaches_into_outer_context > 0
1181                    || self
1182                        .atn
1183                        .state(config.state)
1184                        .is_some_and(AtnState::is_rule_stop)
1185                        && config.context.has_empty_path()
1186            })
1187            .map(|config| config.alt)
1188            .min()
1189    }
1190
1191    fn rule_stop_configs(
1192        &self,
1193        configs: AtnConfigSet,
1194        merge_cache: &mut PredictionContextMergeCache,
1195    ) -> AtnConfigSet {
1196        if configs.configs().iter().all(|config| {
1197            self.atn
1198                .state(config.state)
1199                .is_some_and(AtnState::is_rule_stop)
1200        }) {
1201            return configs;
1202        }
1203        let mut result = AtnConfigSet::new_full_context(configs.full_context());
1204        for config in configs.configs().iter().filter(|config| {
1205            self.atn
1206                .state(config.state)
1207                .is_some_and(AtnState::is_rule_stop)
1208        }) {
1209            result.add_with_merge_cache(config.clone(), Some(merge_cache));
1210        }
1211        result
1212    }
1213
1214    fn configs_all_reached_rule_stop(&self, configs: &AtnConfigSet) -> bool {
1215        configs.configs().iter().all(|config| {
1216            self.atn
1217                .state(config.state)
1218                .is_some_and(AtnState::is_rule_stop)
1219        })
1220    }
1221
1222    fn configs_contain_rule_stop(&self, configs: &AtnConfigSet) -> bool {
1223        configs.configs().iter().any(|config| {
1224            self.atn
1225                .state(config.state)
1226                .is_some_and(AtnState::is_rule_stop)
1227        })
1228    }
1229
1230    fn closure(
1231        &self,
1232        config: AtnConfig,
1233        configs: &mut AtnConfigSet,
1234        merge_cache: &mut PredictionContextMergeCache,
1235        scratch: &mut ClosureScratch,
1236        params: ClosureParams,
1237    ) {
1238        let ClosureParams {
1239            precedence,
1240            collect_predicates,
1241            treat_eof_as_epsilon,
1242        } = params;
1243        scratch.stack.clear();
1244        scratch.visited.clear();
1245        scratch.stack.push((config, collect_predicates));
1246        while let Some((config, collect_predicates)) = scratch.stack.pop() {
1247            if !scratch.visited.insert(ClosureConfigKey::from(&config)) {
1248                continue;
1249            }
1250            let Some(state) = self.atn.state(config.state) else {
1251                continue;
1252            };
1253            let at_rule_stop = state.is_rule_stop();
1254            if at_rule_stop
1255                && self.closure_at_rule_stop(
1256                    config.clone(),
1257                    collect_predicates,
1258                    configs,
1259                    merge_cache,
1260                    &mut scratch.stack,
1261                )
1262            {
1263                continue;
1264            }
1265            let epsilon_only = !state.transitions.is_empty()
1266                && state.transitions.iter().all(Transition::is_epsilon);
1267            if !epsilon_only {
1268                configs.add_with_merge_cache(config.clone(), Some(merge_cache));
1269            }
1270            for (index, transition) in state.transitions.iter().enumerate() {
1271                if index == 0
1272                    && can_drop_left_recursive_loop_entry_edge(self.atn, state, &config.context)
1273                {
1274                    continue;
1275                }
1276                if transition.is_epsilon() {
1277                    if let Some(mut target) = self.epsilon_target_config(
1278                        &config,
1279                        transition,
1280                        precedence,
1281                        collect_predicates,
1282                        configs.full_context(),
1283                    ) {
1284                        if at_rule_stop {
1285                            target.reaches_into_outer_context =
1286                                target.reaches_into_outer_context.saturating_add(1);
1287                        }
1288                        // ANTLR: stop collecting predicates once an action edge is
1289                        // crossed, so a predicate after an action is deferred to
1290                        // parse time rather than evaluated during prediction.
1291                        let target_collect_predicates =
1292                            collect_predicates && !matches!(transition, Transition::Action { .. });
1293                        scratch.stack.push((target, target_collect_predicates));
1294                    }
1295                } else if treat_eof_as_epsilon
1296                    && transition.matches(TOKEN_EOF, 1, self.atn.max_token_type())
1297                {
1298                    scratch.stack.push((
1299                        AtnConfig {
1300                            state: transition.target(),
1301                            alt: config.alt,
1302                            context: Rc::clone(&config.context),
1303                            semantic_context: config.semantic_context.clone(),
1304                            reaches_into_outer_context: config.reaches_into_outer_context,
1305                            precedence_filter_suppressed: config.precedence_filter_suppressed,
1306                        },
1307                        collect_predicates,
1308                    ));
1309                }
1310            }
1311        }
1312        #[cfg(feature = "perf-counters")]
1313        crate::perf::record_closure(scratch.visited.len());
1314    }
1315
1316    fn closure_at_rule_stop(
1317        &self,
1318        config: AtnConfig,
1319        collect_predicates: bool,
1320        configs: &mut AtnConfigSet,
1321        merge_cache: &mut PredictionContextMergeCache,
1322        stack: &mut Vec<(AtnConfig, bool)>,
1323    ) -> bool {
1324        if config.context.is_empty() {
1325            if configs.full_context() {
1326                configs.add_with_merge_cache(config, Some(merge_cache));
1327                return true;
1328            }
1329            return false;
1330        }
1331        let mut handled_all_paths = true;
1332        for index in 0..config.context.len() {
1333            let Some(return_state) = config.context.return_state(index) else {
1334                continue;
1335            };
1336            if return_state == EMPTY_RETURN_STATE {
1337                if configs.full_context() {
1338                    let mut empty_context_config = config.clone();
1339                    empty_context_config.context = PredictionContext::empty();
1340                    configs.add_with_merge_cache(empty_context_config, Some(merge_cache));
1341                } else {
1342                    handled_all_paths = false;
1343                }
1344                continue;
1345            }
1346            let parent = config
1347                .context
1348                .parent(index)
1349                .unwrap_or_else(PredictionContext::empty);
1350            let next = AtnConfig {
1351                state: return_state,
1352                alt: config.alt,
1353                context: parent,
1354                semantic_context: config.semantic_context.clone(),
1355                reaches_into_outer_context: config.reaches_into_outer_context,
1356                precedence_filter_suppressed: config.precedence_filter_suppressed,
1357            };
1358            stack.push((next, collect_predicates));
1359        }
1360        handled_all_paths
1361    }
1362
1363    fn epsilon_target_config(
1364        &self,
1365        config: &AtnConfig,
1366        transition: &Transition,
1367        precedence: i32,
1368        collect_predicates: bool,
1369        full_context: bool,
1370    ) -> Option<AtnConfig> {
1371        let semantic_context = match transition {
1372            Transition::Predicate {
1373                rule_index,
1374                pred_index,
1375                context_dependent,
1376                ..
1377            } if collect_predicates => SemanticContext::and(
1378                config.semantic_context.clone(),
1379                SemanticContext::Predicate {
1380                    rule_index: *rule_index,
1381                    pred_index: *pred_index,
1382                    context_dependent: *context_dependent,
1383                },
1384            ),
1385            Transition::Precedence {
1386                precedence: transition_precedence,
1387                ..
1388            } if collect_predicates && *transition_precedence < precedence => return None,
1389            Transition::Precedence { precedence, .. } if collect_predicates && !full_context => {
1390                SemanticContext::and(
1391                    config.semantic_context.clone(),
1392                    SemanticContext::Precedence {
1393                        precedence: *precedence,
1394                    },
1395                )
1396            }
1397            _ => config.semantic_context.clone(),
1398        };
1399        let context = match transition {
1400            Transition::Rule { follow_state, .. } => {
1401                PredictionContext::singleton(Rc::clone(&config.context), *follow_state)
1402            }
1403            _ => Rc::clone(&config.context),
1404        };
1405        Some(AtnConfig {
1406            state: transition.target(),
1407            alt: config.alt,
1408            context,
1409            semantic_context,
1410            reaches_into_outer_context: config.reaches_into_outer_context,
1411            precedence_filter_suppressed: config.precedence_filter_suppressed,
1412        })
1413    }
1414
1415    fn dfa_prediction_info(
1416        &self,
1417        decision: usize,
1418        state_number: usize,
1419    ) -> Option<DfaPredictionInfo> {
1420        self.decision_to_dfa
1421            .get(decision)
1422            .and_then(|dfa| dfa.state(state_number))
1423            .and_then(|state| {
1424                state.prediction.map(|alt| {
1425                    let conflicting_alts = if state.requires_full_context {
1426                        if state.conflicting_alts.is_empty() {
1427                            state.configs.alts().into_iter().collect()
1428                        } else {
1429                            state.conflicting_alts.clone()
1430                        }
1431                    } else {
1432                        Vec::new()
1433                    };
1434                    DfaPredictionInfo {
1435                        prediction: ParserAtnPrediction {
1436                            alt,
1437                            requires_full_context: state.requires_full_context,
1438                            // Precomputed at accept time (see compute_target_state)
1439                            // so this warm-hit path avoids an O(configs) rescan.
1440                            has_semantic_context: state.has_semantic_context_for_alt,
1441                            diagnostic: None,
1442                        },
1443                        conflicting_alts,
1444                    }
1445                })
1446            })
1447    }
1448}
1449
1450/// Reports whether closure should skip the loop-entry branch for a
1451/// left-recursive rule under the current caller context.
1452pub(crate) fn can_drop_left_recursive_loop_entry_edge(
1453    atn: &Atn,
1454    state: &AtnState,
1455    context: &PredictionContext,
1456) -> bool {
1457    if state.kind != AtnStateKind::StarLoopEntry
1458        || !state.precedence_rule_decision
1459        || context.is_empty()
1460        || context.has_empty_path()
1461    {
1462        return false;
1463    }
1464    let Some(rule_index) = state.rule_index else {
1465        return false;
1466    };
1467    for index in 0..context.len() {
1468        let Some(return_state_number) = context.return_state(index) else {
1469            return false;
1470        };
1471        let Some(return_state) = atn.state(return_state_number) else {
1472            return false;
1473        };
1474        if return_state.rule_index != Some(rule_index) {
1475            return false;
1476        }
1477    }
1478    let Some(block_end_state_number) = state
1479        .transitions
1480        .first()
1481        .and_then(|transition| atn.state(transition.target()))
1482        .and_then(|decision_start| decision_start.end_state)
1483    else {
1484        return false;
1485    };
1486    for index in 0..context.len() {
1487        let return_state_number = context
1488            .return_state(index)
1489            .expect("return state checked above");
1490        let return_state = atn
1491            .state(return_state_number)
1492            .expect("return state checked above");
1493        if return_state.state_number == block_end_state_number {
1494            continue;
1495        }
1496        if return_state.transitions.len() != 1 || !return_state.transitions[0].is_epsilon() {
1497            return false;
1498        }
1499        let return_target = return_state.transitions[0].target();
1500        if return_state.kind == AtnStateKind::BlockEnd && return_target == state.state_number {
1501            continue;
1502        }
1503        if return_target == block_end_state_number {
1504            continue;
1505        }
1506        let Some(return_target_state) = atn.state(return_target) else {
1507            return false;
1508        };
1509        if return_target_state.kind == AtnStateKind::BlockEnd
1510            && return_target_state.transitions.len() == 1
1511            && return_target_state.transitions[0].is_epsilon()
1512            && return_target_state.transitions[0].target() == state.state_number
1513        {
1514            continue;
1515        }
1516        return false;
1517    }
1518    true
1519}
1520
1521fn configs_have_semantic_context_for_alt(configs: &AtnConfigSet, alt: usize) -> bool {
1522    configs
1523        .configs()
1524        .iter()
1525        .any(|config| config.alt == alt && !config.semantic_context.is_none())
1526}
1527
1528#[derive(Clone, Debug, Eq, PartialEq)]
1529pub enum ParserAtnSimulatorError {
1530    MissingAtnState(usize),
1531    MissingDfaState(usize),
1532    NoViableAlt { symbol: i32, index: usize },
1533    PredictionRequiresMoreLookahead,
1534    UnknownDecision(usize),
1535}
1536
1537/// Java `DFASerializer.getStateString`: `:sN^=>alt` for accept states.
1538fn dfa_state_display(state: &DfaState) -> String {
1539    let mut out = String::new();
1540    if state.is_accept_state {
1541        out.push(':');
1542    }
1543    out.push('s');
1544    out.push_str(&state.state_number.to_string());
1545    if state.requires_full_context {
1546        out.push('^');
1547    }
1548    if state.is_accept_state {
1549        out.push_str("=>");
1550        out.push_str(
1551            &state
1552                .prediction
1553                .map(|prediction| prediction.to_string())
1554                .unwrap_or_default(),
1555        );
1556    }
1557    out
1558}
1559
1560#[cfg(test)]
1561mod tests {
1562    use super::*;
1563    use crate::atn::{AtnStateKind, AtnType};
1564
1565    #[test]
1566    fn union_decision_dfa_preserves_disjoint_coverage() {
1567        fn configs(atn_state: usize) -> AtnConfigSet {
1568            let mut set = AtnConfigSet::new();
1569            set.add(AtnConfig::new(atn_state, 1, PredictionContext::empty()));
1570            set
1571        }
1572        fn state(atn_state: usize) -> DfaState {
1573            DfaState::new(configs(atn_state))
1574        }
1575
1576        // Two DFAs that evolved independently from the same grammar: equal
1577        // state/edge counts, but disjoint transitions and different state
1578        // numbering for the shared successor.
1579        let mut shared = Dfa::with_max_token_type(0, 0, 8);
1580        let shared_root = shared.add_state(state(10));
1581        let shared_a = shared.add_state(state(11));
1582        shared
1583            .state_mut(shared_root)
1584            .expect("shared root")
1585            .add_edge(1, shared_a);
1586        shared.set_start_state(shared_root);
1587
1588        let mut local = Dfa::with_max_token_type(0, 0, 8);
1589        let local_b = local.add_state(state(12));
1590        let local_root = local.add_state(state(10));
1591        local
1592            .state_mut(local_root)
1593            .expect("local root")
1594            .add_edge(2, local_b);
1595        local.set_precedence_start_state(3, local_root);
1596
1597        union_decision_dfa(&mut shared, local);
1598
1599        // The root (same config set) gained local's edge without losing its
1600        // own, with the target re-keyed into shared numbering.
1601        let root = shared.state(shared_root).expect("root");
1602        assert_eq!(root.edge(1), Some(shared_a));
1603        let merged_b = shared
1604            .state_number_for_configs(&configs(12))
1605            .expect("local-only state adopted");
1606        assert_eq!(root.edge(2), Some(merged_b));
1607        assert_eq!(shared.states().len(), 3);
1608        // Start-state gaps fill from local; incumbents are kept.
1609        assert_eq!(shared.start_state(), Some(shared_root));
1610        assert_eq!(shared.precedence_start_state(3), Some(shared_root));
1611    }
1612
1613    #[test]
1614    fn adaptive_predict_reuses_dense_dfa_edges() {
1615        let atn = two_token_decision_atn();
1616        let mut simulator = ParserAtnSimulator::new(&atn);
1617
1618        assert_eq!(simulator.adaptive_predict(0, [1, 2]), Ok(1));
1619        assert_eq!(simulator.adaptive_predict(0, [1, 3]), Ok(2));
1620
1621        let dfa = &simulator.decision_dfas()[0];
1622        let start = dfa.start_state().expect("start state");
1623        let after_first = dfa.state(start).and_then(|state| state.edge(1));
1624        assert!(after_first.is_some());
1625    }
1626
1627    #[test]
1628    fn shared_simulator_reuses_learned_dfa_states() {
1629        let atn = Box::leak(Box::new(two_token_decision_atn()));
1630        let learned_states = {
1631            let mut simulator = ParserAtnSimulator::new_shared(atn);
1632            assert_eq!(simulator.adaptive_predict(0, [1, 2]), Ok(1));
1633            simulator.decision_dfas()[0].states().len()
1634        };
1635
1636        let simulator = ParserAtnSimulator::new_shared(atn);
1637        assert_eq!(simulator.decision_dfas()[0].states().len(), learned_states);
1638    }
1639
1640    #[test]
1641    fn adaptive_predict_reports_no_viable_alt() {
1642        let atn = two_token_decision_atn();
1643        let mut simulator = ParserAtnSimulator::new(&atn);
1644
1645        assert_eq!(
1646            simulator.adaptive_predict(0, [4]),
1647            Err(ParserAtnSimulatorError::NoViableAlt {
1648                symbol: 4,
1649                index: 0
1650            })
1651        );
1652    }
1653
1654    #[test]
1655    fn adaptive_predict_marks_sll_conflict_for_full_context() {
1656        let atn = ambiguous_single_token_decision_atn();
1657        let mut simulator = ParserAtnSimulator::new(&atn);
1658
1659        assert_eq!(simulator.adaptive_predict(0, [1]), Ok(1));
1660        let prediction = simulator
1661            .adaptive_predict_info_with_precedence(0, 0, [1])
1662            .expect("prediction");
1663        assert_eq!(
1664            prediction,
1665            ParserAtnPrediction {
1666                alt: 1,
1667                requires_full_context: true,
1668                has_semantic_context: false,
1669                diagnostic: Some(ParserAtnPredictionDiagnostic {
1670                    kind: ParserAtnPredictionDiagnosticKind::Ambiguity,
1671                    start_index: 0,
1672                    sll_stop_index: 0,
1673                    ll_stop_index: 0,
1674                    conflicting_alts: vec![1, 2],
1675                    exact: false,
1676                }),
1677            }
1678        );
1679
1680        let dfa = &simulator.decision_dfas()[0];
1681        let start = dfa.start_state().expect("start state");
1682        let target = dfa
1683            .state(start)
1684            .and_then(|state| state.edge(1))
1685            .expect("edge for token 1");
1686        let state = dfa.state(target).expect("target state");
1687        assert!(state.is_accept_state);
1688        assert!(state.requires_full_context);
1689        assert_eq!(state.prediction, Some(1));
1690    }
1691
1692    #[test]
1693    fn adaptive_predict_keeps_rule_stop_configs_at_eof() {
1694        let atn = optional_token_decision_atn();
1695        let mut simulator = ParserAtnSimulator::new(&atn);
1696
1697        assert_eq!(simulator.adaptive_predict(0, [TOKEN_EOF]), Ok(2));
1698    }
1699
1700    #[test]
1701    fn adaptive_predict_treats_repeated_eof_as_epsilon_after_first_eof() {
1702        let atn = multiple_eof_decision_atn();
1703        let mut simulator = ParserAtnSimulator::new(&atn);
1704
1705        assert_eq!(simulator.adaptive_predict(0, [1, TOKEN_EOF]), Ok(1));
1706    }
1707
1708    #[test]
1709    fn adaptive_predict_uses_finished_entry_rule_alt_on_error_edge() {
1710        let atn = prefix_alt_decision_atn();
1711        let mut simulator = ParserAtnSimulator::new(&atn);
1712
1713        assert_eq!(simulator.adaptive_predict(0, [1, 3]), Ok(1));
1714    }
1715
1716    #[test]
1717    fn adaptive_predict_uses_precedence_dfa_start_states() {
1718        let mut atn = two_token_decision_atn();
1719        atn.state_mut(1)
1720            .expect("decision state")
1721            .precedence_rule_decision = true;
1722        let mut simulator = ParserAtnSimulator::new(&atn);
1723
1724        assert_eq!(
1725            simulator.adaptive_predict_with_precedence(0, 3, [1, 2]),
1726            Ok(1)
1727        );
1728        assert_eq!(
1729            simulator.adaptive_predict_with_precedence(0, 7, [1, 3]),
1730            Ok(2)
1731        );
1732
1733        let dfa = &simulator.decision_dfas()[0];
1734        assert!(dfa.is_precedence_dfa());
1735        assert!(dfa.precedence_start_state(3).is_some());
1736        assert!(dfa.precedence_start_state(7).is_some());
1737    }
1738
1739    #[test]
1740    fn adaptive_predict_stream_restores_input_position() {
1741        let atn = two_token_decision_atn();
1742        let mut simulator = ParserAtnSimulator::new(&atn);
1743        let mut input = VecIntStream::new(vec![1, 3, TOKEN_EOF]);
1744
1745        assert_eq!(simulator.adaptive_predict_stream(0, &mut input), Ok(2));
1746        assert_eq!(input.index(), 0);
1747        assert_eq!(input.la(1), 1);
1748    }
1749
1750    #[test]
1751    fn adaptive_predict_stream_retries_full_context_conflict() {
1752        let atn = ambiguous_single_token_decision_atn();
1753        let mut simulator = ParserAtnSimulator::new(&atn);
1754        let mut input = VecIntStream::new(vec![1, TOKEN_EOF]);
1755
1756        let prediction = simulator
1757            .adaptive_predict_stream_info_with_precedence(0, 0, &mut input)
1758            .expect("prediction");
1759
1760        assert_eq!(
1761            prediction,
1762            ParserAtnPrediction {
1763                alt: 1,
1764                requires_full_context: true,
1765                has_semantic_context: false,
1766                diagnostic: Some(ParserAtnPredictionDiagnostic {
1767                    kind: ParserAtnPredictionDiagnosticKind::Ambiguity,
1768                    start_index: 0,
1769                    sll_stop_index: 0,
1770                    ll_stop_index: 0,
1771                    conflicting_alts: vec![1, 2],
1772                    exact: false,
1773                }),
1774            }
1775        );
1776        assert_eq!(input.index(), 0);
1777    }
1778
1779    #[test]
1780    fn context_prediction_reports_context_sensitivity_for_dfa_conflict() {
1781        let atn = two_token_decision_atn();
1782        let mut simulator = ParserAtnSimulator::new(&atn);
1783        let empty = PredictionContext::empty();
1784        let mut start_configs = AtnConfigSet::new();
1785        start_configs.add(AtnConfig::new(2, 1, Rc::clone(&empty)));
1786        let start = simulator.decision_to_dfa[0].add_state(DfaState::new(start_configs));
1787        simulator.decision_to_dfa[0].set_start_state(start);
1788
1789        let mut accept_configs = AtnConfigSet::new();
1790        accept_configs.add(
1791            AtnConfig::new(3, 1, Rc::clone(&empty)).with_semantic_context(
1792                SemanticContext::Predicate {
1793                    rule_index: 0,
1794                    pred_index: 0,
1795                    context_dependent: false,
1796                },
1797            ),
1798        );
1799        let mut accept_state = DfaState::new(accept_configs);
1800        accept_state.mark_accept(1);
1801        accept_state.requires_full_context = true;
1802        accept_state.conflicting_alts = vec![1, 2];
1803        let accept = simulator.decision_to_dfa[0].add_state(accept_state);
1804        simulator.decision_to_dfa[0]
1805            .state_mut(start)
1806            .expect("start state")
1807            .add_edge(1, accept);
1808
1809        let mut input = VecIntStream::new(vec![1, 3, TOKEN_EOF]);
1810        let prediction = simulator
1811            .adaptive_predict_stream_info_with_context(0, 0, &mut input, &empty)
1812            .expect("prediction");
1813
1814        assert_eq!(
1815            prediction,
1816            ParserAtnPrediction {
1817                alt: 2,
1818                requires_full_context: true,
1819                has_semantic_context: false,
1820                diagnostic: Some(ParserAtnPredictionDiagnostic {
1821                    kind: ParserAtnPredictionDiagnosticKind::ContextSensitivity,
1822                    start_index: 0,
1823                    sll_stop_index: 0,
1824                    ll_stop_index: 1,
1825                    conflicting_alts: vec![1, 2],
1826                    exact: false,
1827                }),
1828            }
1829        );
1830        assert_eq!(input.index(), 0);
1831    }
1832
1833    #[test]
1834    fn full_context_reach_prefers_longer_match_over_skipped_stop_state() {
1835        let atn = prefix_alt_decision_atn();
1836        let simulator = ParserAtnSimulator::new(&atn);
1837        let empty = PredictionContext::empty();
1838        let mut configs = AtnConfigSet::new_full_context(true);
1839        configs.add(AtnConfig::new(2, 1, Rc::clone(&empty)));
1840        configs.add(AtnConfig::new(1, 2, empty));
1841        let mut merge_cache = PredictionContextMergeCache::new();
1842
1843        let reach = simulator.compute_reach_set(&configs, 2, true, 0, &mut merge_cache);
1844
1845        assert_eq!(reach.alts(), std::iter::once(2).collect());
1846        assert!(simulator.configs_all_reached_rule_stop(&reach));
1847    }
1848
1849    #[test]
1850    fn sll_closure_follows_empty_context_rule_stop_exits() {
1851        let mut atn = Atn::new(AtnType::Parser, 1);
1852        add_state(&mut atn, 0, AtnStateKind::RuleStop);
1853        add_state(&mut atn, 1, AtnStateKind::Basic);
1854        add_state(&mut atn, 2, AtnStateKind::Basic);
1855        atn.state_mut(0)
1856            .expect("state 0")
1857            .add_transition(Transition::Epsilon { target: 1 });
1858        atn.state_mut(1)
1859            .expect("state 1")
1860            .add_transition(Transition::Atom {
1861                target: 2,
1862                label: 1,
1863            });
1864
1865        let simulator = ParserAtnSimulator::new(&atn);
1866        let mut configs = AtnConfigSet::new_full_context(false);
1867        let mut merge_cache = PredictionContextMergeCache::new();
1868        let mut scratch = ClosureScratch::default();
1869        simulator.closure(
1870            AtnConfig::new(0, 2, PredictionContext::empty()),
1871            &mut configs,
1872            &mut merge_cache,
1873            &mut scratch,
1874            ClosureParams {
1875                precedence: 0,
1876                collect_predicates: true,
1877                treat_eof_as_epsilon: false,
1878            },
1879        );
1880
1881        assert_eq!(configs.len(), 1);
1882        let config = &configs.configs()[0];
1883        assert_eq!(config.state, 1);
1884        assert_eq!(config.alt, 2);
1885        assert_eq!(config.reaches_into_outer_context, 1);
1886    }
1887
1888    #[test]
1889    fn precedence_contexts_are_collected_only_for_start_closure() {
1890        let mut atn = Atn::new(AtnType::Parser, 1);
1891        add_state(&mut atn, 0, AtnStateKind::Basic);
1892        add_state(&mut atn, 1, AtnStateKind::Basic);
1893        let simulator = ParserAtnSimulator::new(&atn);
1894        let transition = Transition::Precedence {
1895            target: 1,
1896            precedence: 2,
1897        };
1898        let config = AtnConfig::new(0, 1, PredictionContext::empty());
1899
1900        let sll_start = simulator
1901            .epsilon_target_config(&config, &transition, 1, true, false)
1902            .expect("sll start transition");
1903        assert!(matches!(
1904            sll_start.semantic_context,
1905            SemanticContext::Precedence { precedence: 2 }
1906        ));
1907
1908        let full_context_start = simulator
1909            .epsilon_target_config(&config, &transition, 1, true, true)
1910            .expect("full-context start transition");
1911        assert!(full_context_start.semantic_context.is_none());
1912
1913        let reach = simulator
1914            .epsilon_target_config(&config, &transition, 3, false, false)
1915            .expect("reach transition");
1916        assert!(reach.semantic_context.is_none());
1917
1918        assert!(
1919            simulator
1920                .epsilon_target_config(&config, &transition, 3, true, false)
1921                .is_none()
1922        );
1923    }
1924
1925    #[test]
1926    fn closure_stops_collecting_predicates_after_action_edge() {
1927        // ANTLR's `closure_` sets
1928        // `continueCollecting = collectPredicates && !ActionTransition`, so a
1929        // predicate reached *after* an action edge is NOT folded into the
1930        // config's semantic context — it is deferred to parse time (the
1931        // "action hides predicates" rule). Build `0 -Action-> 1 -Pred-> 2` and
1932        // assert the closure config carries NO semantic context.
1933        let mut atn = Atn::new(AtnType::Parser, 1);
1934        add_state(&mut atn, 0, AtnStateKind::Basic);
1935        add_state(&mut atn, 1, AtnStateKind::Basic);
1936        add_state(&mut atn, 2, AtnStateKind::Basic);
1937        add_state(&mut atn, 3, AtnStateKind::Basic);
1938        atn.state_mut(0)
1939            .expect("state 0")
1940            .add_transition(Transition::Action {
1941                target: 1,
1942                rule_index: 0,
1943                action_index: Some(0),
1944                context_dependent: false,
1945            });
1946        atn.state_mut(1)
1947            .expect("state 1")
1948            .add_transition(Transition::Predicate {
1949                target: 2,
1950                rule_index: 0,
1951                pred_index: 0,
1952                context_dependent: false,
1953            });
1954        atn.state_mut(2)
1955            .expect("state 2")
1956            .add_transition(Transition::Atom {
1957                target: 3,
1958                label: 1,
1959            });
1960
1961        let simulator = ParserAtnSimulator::new(&atn);
1962        let mut configs = AtnConfigSet::new();
1963        let mut merge_cache = PredictionContextMergeCache::new();
1964        let mut scratch = ClosureScratch::default();
1965        simulator.closure(
1966            AtnConfig::new(0, 1, PredictionContext::empty()),
1967            &mut configs,
1968            &mut merge_cache,
1969            &mut scratch,
1970            ClosureParams {
1971                precedence: 0,
1972                collect_predicates: true,
1973                treat_eof_as_epsilon: false,
1974            },
1975        );
1976
1977        // The config that stops at state 2 (post-predicate, awaiting the atom)
1978        // must NOT carry the predicate — the action edge turned collection off.
1979        let at_two = configs
1980            .configs()
1981            .iter()
1982            .find(|config| config.state == 2)
1983            .expect("config at state 2");
1984        assert!(
1985            at_two.semantic_context.is_none(),
1986            "predicate after an action edge must not be collected during prediction"
1987        );
1988
1989        // Control: the SAME predicate reached WITHOUT an intervening action edge
1990        // IS collected (so the assertion above is about the action edge, not a
1991        // blanket failure to collect predicates).
1992        let direct = simulator
1993            .epsilon_target_config(
1994                &AtnConfig::new(1, 1, PredictionContext::empty()),
1995                &Transition::Predicate {
1996                    target: 2,
1997                    rule_index: 0,
1998                    pred_index: 0,
1999                    context_dependent: false,
2000                },
2001                0,
2002                true,
2003                false,
2004            )
2005            .expect("predicate transition");
2006        assert!(matches!(
2007            direct.semantic_context,
2008            SemanticContext::Predicate { pred_index: 0, .. }
2009        ));
2010    }
2011
2012    #[test]
2013    fn reach_set_skips_closure_for_unique_intermediate_alt() {
2014        let mut atn = Atn::new(AtnType::Parser, 1);
2015        add_state(&mut atn, 0, AtnStateKind::Basic);
2016        add_state(&mut atn, 1, AtnStateKind::Basic);
2017        add_state(&mut atn, 2, AtnStateKind::Basic);
2018        atn.state_mut(0)
2019            .expect("state 0")
2020            .add_transition(Transition::Atom {
2021                target: 1,
2022                label: 7,
2023            });
2024        atn.state_mut(1)
2025            .expect("state 1")
2026            .add_transition(Transition::Epsilon { target: 2 });
2027
2028        let simulator = ParserAtnSimulator::new(&atn);
2029        let empty = PredictionContext::empty();
2030        let mut configs = AtnConfigSet::new_full_context(false);
2031        configs.add(AtnConfig::new(0, 1, empty));
2032        let mut merge_cache = PredictionContextMergeCache::new();
2033
2034        let reach = simulator.compute_reach_set(&configs, 7, false, 0, &mut merge_cache);
2035
2036        assert_eq!(reach.len(), 1);
2037        assert_eq!(reach.configs()[0].state, 1);
2038    }
2039
2040    #[test]
2041    fn semantic_context_flag_is_scoped_to_predicted_alt() {
2042        let empty = PredictionContext::empty();
2043        let mut configs = AtnConfigSet::new();
2044        configs.add(AtnConfig::new(1, 1, Rc::clone(&empty)));
2045        configs.add(AtnConfig::new(2, 2, empty).with_semantic_context(
2046            SemanticContext::Predicate {
2047                rule_index: 0,
2048                pred_index: 0,
2049                context_dependent: false,
2050            },
2051        ));
2052
2053        assert!(!configs_have_semantic_context_for_alt(&configs, 1));
2054        assert!(configs_have_semantic_context_for_alt(&configs, 2));
2055    }
2056
2057    #[test]
2058    fn adaptive_predict_prefers_non_greedy_exit_before_consuming() {
2059        let atn = non_greedy_optional_exit_first_atn();
2060        let mut simulator = ParserAtnSimulator::new(&atn);
2061
2062        assert_eq!(simulator.adaptive_predict(0, [1, TOKEN_EOF]), Ok(1));
2063    }
2064
2065    #[test]
2066    fn left_recursive_loop_entry_drop_requires_same_rule_return() {
2067        let atn = left_recursive_loop_entry_atn();
2068        let loop_entry = atn.state(1).expect("loop entry");
2069        let same_rule_context = PredictionContext::singleton(PredictionContext::empty(), 4);
2070        let other_rule_context = PredictionContext::singleton(PredictionContext::empty(), 5);
2071
2072        assert!(can_drop_left_recursive_loop_entry_edge(
2073            &atn,
2074            loop_entry,
2075            &same_rule_context
2076        ));
2077        assert!(!can_drop_left_recursive_loop_entry_edge(
2078            &atn,
2079            loop_entry,
2080            &other_rule_context
2081        ));
2082        assert!(!can_drop_left_recursive_loop_entry_edge(
2083            &atn,
2084            loop_entry,
2085            &PredictionContext::empty()
2086        ));
2087    }
2088
2089    fn two_token_decision_atn() -> Atn {
2090        let mut atn = Atn::new(AtnType::Parser, 3);
2091        add_state(&mut atn, 0, AtnStateKind::RuleStart);
2092        add_state(&mut atn, 1, AtnStateKind::BlockStart);
2093        add_state(&mut atn, 2, AtnStateKind::Basic);
2094        add_state(&mut atn, 3, AtnStateKind::Basic);
2095        add_state(&mut atn, 4, AtnStateKind::Basic);
2096        add_state(&mut atn, 5, AtnStateKind::Basic);
2097        add_state(&mut atn, 6, AtnStateKind::BlockEnd);
2098        add_state(&mut atn, 7, AtnStateKind::RuleStop);
2099        atn.set_rule_to_start_state(vec![0]);
2100        atn.set_rule_to_stop_state(vec![7]);
2101        atn.add_decision_state(1);
2102        atn.state_mut(0)
2103            .expect("state 0")
2104            .add_transition(Transition::Epsilon { target: 1 });
2105        atn.state_mut(1)
2106            .expect("state 1")
2107            .add_transition(Transition::Epsilon { target: 2 });
2108        atn.state_mut(1)
2109            .expect("state 1")
2110            .add_transition(Transition::Epsilon { target: 4 });
2111        atn.state_mut(2)
2112            .expect("state 2")
2113            .add_transition(Transition::Atom {
2114                target: 3,
2115                label: 1,
2116            });
2117        atn.state_mut(3)
2118            .expect("state 3")
2119            .add_transition(Transition::Atom {
2120                target: 6,
2121                label: 2,
2122            });
2123        atn.state_mut(4)
2124            .expect("state 4")
2125            .add_transition(Transition::Atom {
2126                target: 5,
2127                label: 1,
2128            });
2129        atn.state_mut(5)
2130            .expect("state 5")
2131            .add_transition(Transition::Atom {
2132                target: 6,
2133                label: 3,
2134            });
2135        atn.state_mut(6)
2136            .expect("state 6")
2137            .add_transition(Transition::Epsilon { target: 7 });
2138        atn
2139    }
2140
2141    fn optional_token_decision_atn() -> Atn {
2142        let mut atn = Atn::new(AtnType::Parser, 1);
2143        add_state(&mut atn, 0, AtnStateKind::RuleStart);
2144        add_state(&mut atn, 1, AtnStateKind::BlockStart);
2145        add_state(&mut atn, 2, AtnStateKind::Basic);
2146        add_state(&mut atn, 3, AtnStateKind::BlockEnd);
2147        add_state(&mut atn, 4, AtnStateKind::RuleStop);
2148        atn.set_rule_to_start_state(vec![0]);
2149        atn.set_rule_to_stop_state(vec![4]);
2150        atn.add_decision_state(1);
2151        atn.state_mut(0)
2152            .expect("state 0")
2153            .add_transition(Transition::Epsilon { target: 1 });
2154        atn.state_mut(1)
2155            .expect("state 1")
2156            .add_transition(Transition::Epsilon { target: 2 });
2157        atn.state_mut(1)
2158            .expect("state 1")
2159            .add_transition(Transition::Epsilon { target: 3 });
2160        atn.state_mut(2)
2161            .expect("state 2")
2162            .add_transition(Transition::Atom {
2163                target: 3,
2164                label: 1,
2165            });
2166        atn.state_mut(3)
2167            .expect("state 3")
2168            .add_transition(Transition::Epsilon { target: 4 });
2169        atn
2170    }
2171
2172    fn non_greedy_optional_exit_first_atn() -> Atn {
2173        let mut atn = Atn::new(AtnType::Parser, 1);
2174        add_state(&mut atn, 0, AtnStateKind::RuleStart);
2175        add_state(&mut atn, 1, AtnStateKind::BlockStart);
2176        add_state(&mut atn, 2, AtnStateKind::BlockEnd);
2177        add_state(&mut atn, 3, AtnStateKind::Basic);
2178        add_state(&mut atn, 4, AtnStateKind::RuleStop);
2179        atn.set_rule_to_start_state(vec![0]);
2180        atn.set_rule_to_stop_state(vec![4]);
2181        atn.add_decision_state(1);
2182        atn.state_mut(1).expect("state 1").non_greedy = true;
2183        atn.state_mut(0)
2184            .expect("state 0")
2185            .add_transition(Transition::Epsilon { target: 1 });
2186        atn.state_mut(1)
2187            .expect("state 1")
2188            .add_transition(Transition::Epsilon { target: 2 });
2189        atn.state_mut(1)
2190            .expect("state 1")
2191            .add_transition(Transition::Epsilon { target: 3 });
2192        atn.state_mut(2)
2193            .expect("state 2")
2194            .add_transition(Transition::Epsilon { target: 4 });
2195        atn.state_mut(3)
2196            .expect("state 3")
2197            .add_transition(Transition::Atom {
2198                target: 4,
2199                label: 1,
2200            });
2201        atn
2202    }
2203
2204    fn ambiguous_single_token_decision_atn() -> Atn {
2205        let mut atn = Atn::new(AtnType::Parser, 1);
2206        add_state(&mut atn, 0, AtnStateKind::RuleStart);
2207        add_state(&mut atn, 1, AtnStateKind::BlockStart);
2208        add_state(&mut atn, 2, AtnStateKind::Basic);
2209        add_state(&mut atn, 3, AtnStateKind::Basic);
2210        add_state(&mut atn, 4, AtnStateKind::Basic);
2211        add_state(&mut atn, 5, AtnStateKind::Basic);
2212        add_state(&mut atn, 6, AtnStateKind::BlockEnd);
2213        add_state(&mut atn, 7, AtnStateKind::RuleStop);
2214        atn.set_rule_to_start_state(vec![0]);
2215        atn.set_rule_to_stop_state(vec![7]);
2216        atn.add_decision_state(1);
2217        atn.state_mut(0)
2218            .expect("state 0")
2219            .add_transition(Transition::Epsilon { target: 1 });
2220        atn.state_mut(1)
2221            .expect("state 1")
2222            .add_transition(Transition::Epsilon { target: 2 });
2223        atn.state_mut(1)
2224            .expect("state 1")
2225            .add_transition(Transition::Epsilon { target: 4 });
2226        atn.state_mut(2)
2227            .expect("state 2")
2228            .add_transition(Transition::Atom {
2229                target: 3,
2230                label: 1,
2231            });
2232        atn.state_mut(3)
2233            .expect("state 3")
2234            .add_transition(Transition::Epsilon { target: 6 });
2235        atn.state_mut(4)
2236            .expect("state 4")
2237            .add_transition(Transition::Atom {
2238                target: 5,
2239                label: 1,
2240            });
2241        atn.state_mut(5)
2242            .expect("state 5")
2243            .add_transition(Transition::Epsilon { target: 6 });
2244        atn.state_mut(6)
2245            .expect("state 6")
2246            .add_transition(Transition::Epsilon { target: 7 });
2247        atn
2248    }
2249
2250    fn prefix_alt_decision_atn() -> Atn {
2251        let mut atn = Atn::new(AtnType::Parser, 3);
2252        add_state(&mut atn, 0, AtnStateKind::BlockStart);
2253        add_state(&mut atn, 1, AtnStateKind::Basic);
2254        add_state(&mut atn, 2, AtnStateKind::RuleStop);
2255        atn.set_rule_to_start_state(vec![0]);
2256        atn.set_rule_to_stop_state(vec![2]);
2257        atn.add_decision_state(0);
2258        atn.state_mut(0)
2259            .expect("state 0")
2260            .add_transition(Transition::Atom {
2261                target: 2,
2262                label: 1,
2263            });
2264        atn.state_mut(0)
2265            .expect("state 0")
2266            .add_transition(Transition::Atom {
2267                target: 1,
2268                label: 1,
2269            });
2270        atn.state_mut(1)
2271            .expect("state 1")
2272            .add_transition(Transition::Atom {
2273                target: 2,
2274                label: 2,
2275            });
2276        atn
2277    }
2278
2279    fn multiple_eof_decision_atn() -> Atn {
2280        let mut atn = Atn::new(AtnType::Parser, 2);
2281        for state_number in 0..=10 {
2282            let kind = match state_number {
2283                0 => AtnStateKind::RuleStart,
2284                1 => AtnStateKind::BlockStart,
2285                7 => AtnStateKind::BlockEnd,
2286                10 => AtnStateKind::RuleStop,
2287                _ => AtnStateKind::Basic,
2288            };
2289            add_state(&mut atn, state_number, kind);
2290        }
2291        atn.set_rule_to_start_state(vec![0]);
2292        atn.set_rule_to_stop_state(vec![10]);
2293        atn.add_decision_state(1);
2294        atn.state_mut(0)
2295            .expect("state 0")
2296            .add_transition(Transition::Epsilon { target: 1 });
2297        atn.state_mut(1)
2298            .expect("state 1")
2299            .add_transition(Transition::Epsilon { target: 2 });
2300        atn.state_mut(1)
2301            .expect("state 1")
2302            .add_transition(Transition::Epsilon { target: 4 });
2303        atn.state_mut(2)
2304            .expect("state 2")
2305            .add_transition(Transition::Atom {
2306                target: 3,
2307                label: 1,
2308            });
2309        atn.state_mut(3)
2310            .expect("state 3")
2311            .add_transition(Transition::Epsilon { target: 7 });
2312        atn.state_mut(4)
2313            .expect("state 4")
2314            .add_transition(Transition::Atom {
2315                target: 5,
2316                label: 1,
2317            });
2318        atn.state_mut(5)
2319            .expect("state 5")
2320            .add_transition(Transition::Atom {
2321                target: 6,
2322                label: 2,
2323            });
2324        atn.state_mut(6)
2325            .expect("state 6")
2326            .add_transition(Transition::Epsilon { target: 7 });
2327        atn.state_mut(7)
2328            .expect("state 7")
2329            .add_transition(Transition::Epsilon { target: 8 });
2330        atn.state_mut(8)
2331            .expect("state 8")
2332            .add_transition(Transition::Atom {
2333                target: 9,
2334                label: TOKEN_EOF,
2335            });
2336        atn.state_mut(9)
2337            .expect("state 9")
2338            .add_transition(Transition::Atom {
2339                target: 10,
2340                label: TOKEN_EOF,
2341            });
2342        atn
2343    }
2344
2345    fn left_recursive_loop_entry_atn() -> Atn {
2346        let mut atn = Atn::new(AtnType::Parser, 1);
2347        add_state(&mut atn, 0, AtnStateKind::RuleStart);
2348        add_state(&mut atn, 1, AtnStateKind::StarLoopEntry);
2349        add_state(&mut atn, 2, AtnStateKind::BlockStart);
2350        add_state(&mut atn, 3, AtnStateKind::BlockEnd);
2351        add_state(&mut atn, 4, AtnStateKind::Basic);
2352        atn.add_state(AtnState::new(5, AtnStateKind::Basic).with_rule_index(1));
2353        add_state(&mut atn, 6, AtnStateKind::LoopEnd);
2354        add_state(&mut atn, 7, AtnStateKind::RuleStop);
2355        atn.state_mut(1)
2356            .expect("loop entry")
2357            .precedence_rule_decision = true;
2358        atn.state_mut(2).expect("block start").end_state = Some(3);
2359        atn.state_mut(1)
2360            .expect("loop entry")
2361            .add_transition(Transition::Epsilon { target: 2 });
2362        atn.state_mut(1)
2363            .expect("loop entry")
2364            .add_transition(Transition::Epsilon { target: 6 });
2365        atn.state_mut(4)
2366            .expect("same-rule return")
2367            .add_transition(Transition::Epsilon { target: 3 });
2368        atn.state_mut(5)
2369            .expect("other-rule return")
2370            .add_transition(Transition::Epsilon { target: 3 });
2371        atn
2372    }
2373
2374    fn add_state(atn: &mut Atn, state_number: usize, kind: AtnStateKind) {
2375        atn.add_state(AtnState::new(state_number, kind).with_rule_index(0));
2376    }
2377
2378    #[derive(Debug)]
2379    struct VecIntStream {
2380        symbols: Vec<i32>,
2381        index: usize,
2382    }
2383
2384    impl VecIntStream {
2385        fn new(symbols: Vec<i32>) -> Self {
2386            Self { symbols, index: 0 }
2387        }
2388    }
2389
2390    impl IntStream for VecIntStream {
2391        fn consume(&mut self) {
2392            if self.la(1) != TOKEN_EOF {
2393                self.index += 1;
2394            }
2395        }
2396
2397        fn la(&mut self, offset: isize) -> i32 {
2398            if offset <= 0 {
2399                return 0;
2400            }
2401            let offset = offset.cast_unsigned() - 1;
2402            self.symbols
2403                .get(self.index + offset)
2404                .copied()
2405                .unwrap_or(TOKEN_EOF)
2406        }
2407
2408        fn index(&self) -> usize {
2409            self.index
2410        }
2411
2412        fn seek(&mut self, index: usize) {
2413            self.index = index;
2414        }
2415
2416        fn size(&self) -> usize {
2417            self.symbols.len()
2418        }
2419    }
2420}