Skip to main content

antlr4_runtime/atn/
parser_atn.rs

1// SPDX-License-Identifier: BSD-3-Clause
2// Copyright (c) 2026 Konstantin Vyatkin
3//! Packed, index-addressed parser ATN storage.
4//!
5//! Parser ATNs are immutable after generation/deserialization. Keeping their
6//! states and transitions in one validated word stream avoids the allocation
7//! and pointer-chasing costs of an owned object graph while still exposing
8//! borrowing semantic views to the simulator and diagnostics.
9
10// These accessors are scalar address calculations used throughout the parser's
11// innermost transition loops. Cross-crate generated parsers need them inlined.
12#![allow(clippy::inline_always)]
13
14use std::borrow::Cow;
15use std::collections::BTreeMap;
16use std::fmt;
17use std::iter::FusedIterator;
18
19use crate::token::TOKEN_EOF;
20
21use super::AtnStateKind;
22
23const PARSER_ATN_MAGIC: u32 = 0x5041_544e;
24const PARSER_ATN_FORMAT_VERSION: u32 = 2;
25const PARSER_ATN_MIN_FORMAT_VERSION: u32 = 1;
26const PARSER_ATN_MAX_FORMAT_VERSION: u32 = 2;
27const PARSER_ATN_BYTE_ORDER: u32 = 0x0102_0304;
28
29const LEGACY_HEADER_WORDS: usize = 26;
30const HEADER_WORDS: usize = 29;
31const STATE_WORDS: usize = 7;
32const TRANSITION_WORDS: usize = 5;
33const LEGACY_SET_WORDS: usize = 2;
34const SET_WORDS: usize = 5;
35const PACKED_U64_WORDS: usize = 2;
36
37const INLINE_TOKEN_SET_WORDS: usize = 2;
38const INLINE_TOKEN_SET_MAX_SLOT: usize = INLINE_TOKEN_SET_WORDS * u64::BITS as usize - 1;
39const MAX_DENSE_TOKEN_SET_BYTES: usize = 64 * 1024;
40const MAX_DENSE_TOKEN_SET_WORDS: usize = MAX_DENSE_TOKEN_SET_BYTES / size_of::<u64>();
41const DENSE_TOKEN_SET_COST_MULTIPLIER: usize = 2;
42const DENSE_TOKEN_SET_MIN_DENSITY_DENOMINATOR: u64 = 8;
43
44const NO_INDEX: u32 = u32::MAX;
45
46const FLAG_NON_GREEDY: u32 = 1 << 0;
47const FLAG_PRECEDENCE_DECISION: u32 = 1 << 1;
48const FLAG_LEFT_RECURSIVE_RULE: u32 = 1 << 2;
49const FLAG_EPSILON_ONLY: u32 = 1 << 3;
50const FLAG_RULE_STOP: u32 = 1 << 4;
51const FLAG_HAS_CONSUMING: u32 = 1 << 5;
52const FLAG_HAS_SEMANTIC: u32 = 1 << 6;
53const STATE_FLAGS: u32 = FLAG_NON_GREEDY
54    | FLAG_PRECEDENCE_DECISION
55    | FLAG_LEFT_RECURSIVE_RULE
56    | FLAG_EPSILON_ONLY
57    | FLAG_RULE_STOP
58    | FLAG_HAS_CONSUMING
59    | FLAG_HAS_SEMANTIC;
60
61const HEADER_MAGIC: usize = 0;
62const HEADER_VERSION: usize = 1;
63const HEADER_BYTE_ORDER: usize = 2;
64const HEADER_SIZE: usize = 3;
65const HEADER_MAX_TOKEN_TYPE: usize = 4;
66const HEADER_STATE_COUNT: usize = 5;
67const HEADER_TRANSITION_COUNT: usize = 6;
68const HEADER_SET_COUNT: usize = 7;
69const HEADER_INTERVAL_COUNT: usize = 8;
70const HEADER_DECISION_COUNT: usize = 9;
71const HEADER_RULE_COUNT: usize = 10;
72const HEADER_STATES_OFFSET: usize = 11;
73const HEADER_TRANSITIONS_OFFSET: usize = 13;
74const HEADER_SETS_OFFSET: usize = 15;
75const HEADER_INTERVALS_OFFSET: usize = 17;
76const HEADER_DECISIONS_OFFSET: usize = 19;
77const HEADER_RULE_STARTS_OFFSET: usize = 21;
78const HEADER_RULE_STOPS_OFFSET: usize = 23;
79const HEADER_TOTAL_LEN: usize = 25;
80const HEADER_TOKEN_BIT_WORD_COUNT: usize = 26;
81const HEADER_TOKEN_BITS_OFFSET: usize = 27;
82
83/// Checked compact identity for one parser ATN state.
84#[repr(transparent)]
85#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
86pub struct AtnStateId(u32);
87
88impl AtnStateId {
89    pub const fn index(self) -> usize {
90        self.0 as usize
91    }
92
93    const fn raw(self) -> u32 {
94        self.0
95    }
96}
97
98impl TryFrom<usize> for AtnStateId {
99    type Error = ParserAtnError;
100
101    fn try_from(value: usize) -> Result<Self, Self::Error> {
102        compact_id("parser ATN state", value).map(Self)
103    }
104}
105
106/// Checked compact identity for one parser ATN transition.
107#[repr(transparent)]
108#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
109pub struct TransitionId(u32);
110
111impl TransitionId {
112    pub const fn index(self) -> usize {
113        self.0 as usize
114    }
115}
116
117impl TryFrom<usize> for TransitionId {
118    type Error = ParserAtnError;
119
120    fn try_from(value: usize) -> Result<Self, Self::Error> {
121        compact_id("parser ATN transition", value).map(Self)
122    }
123}
124
125/// Checked compact identity for one shared interval set.
126#[repr(transparent)]
127#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
128pub struct ParserIntervalSetId(u32);
129
130impl ParserIntervalSetId {
131    pub const fn index(self) -> usize {
132        self.0 as usize
133    }
134
135    const fn raw(self) -> u32 {
136        self.0
137    }
138}
139
140impl TryFrom<usize> for ParserIntervalSetId {
141    type Error = ParserAtnError;
142
143    fn try_from(value: usize) -> Result<Self, Self::Error> {
144        compact_id("parser ATN interval set", value).map(Self)
145    }
146}
147
148/// Membership representation selected for one immutable parser token set.
149#[derive(Clone, Copy, Debug, Eq, PartialEq)]
150#[repr(u32)]
151pub enum ParserTokenSetKind {
152    /// Sorted, coalesced inclusive ranges searched by interval boundary.
153    Intervals = 0,
154    /// Two packed words covering EOF and token types `1..=127`.
155    Inline128 = 1,
156    /// A bounded packed word slice for a larger, cost-effective token domain.
157    Dense = 2,
158}
159
160/// Failure while reading, validating, or constructing packed parser ATN data.
161#[derive(Clone, Debug, Eq, PartialEq, thiserror::Error)]
162pub enum ParserAtnError {
163    #[error(
164        "generated parser ATN format version {found} is unsupported; \
165         this runtime requires generator/runtime format {minimum}..={maximum}"
166    )]
167    UnsupportedVersion {
168        found: u32,
169        minimum: u32,
170        maximum: u32,
171    },
172    #[error("invalid packed parser ATN: {0}")]
173    InvalidData(String),
174    #[error("{field} count/index {value} exceeds the compact u32 range")]
175    Overflow { field: &'static str, value: usize },
176}
177
178/// Storage and shape measurements for one packed parser ATN.
179#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
180pub struct ParserAtnStats {
181    pub states: usize,
182    pub transitions: usize,
183    pub interval_sets: usize,
184    pub interval_ranges: usize,
185    pub inline_token_sets: usize,
186    pub dense_token_sets: usize,
187    pub interval_token_sets: usize,
188    pub token_bitset_bytes: usize,
189    pub decisions: usize,
190    pub rules: usize,
191    pub packed_bytes: usize,
192}
193
194/// Immutable packed parser ATN.
195///
196/// Generated parsers borrow a static word stream directly. Deserialization of
197/// ordinary ANTLR v4 integer metadata produces the same layout in one owned
198/// allocation.
199pub struct ParserAtn {
200    words: Cow<'static, [u32]>,
201    words_address: usize,
202    layout: ParserAtnLayout,
203}
204
205impl Clone for ParserAtn {
206    fn clone(&self) -> Self {
207        let words = self.words.clone();
208        let words_address = words.as_ptr() as usize;
209        Self {
210            words,
211            words_address,
212            layout: self.layout,
213        }
214    }
215}
216
217impl PartialEq for ParserAtn {
218    fn eq(&self, other: &Self) -> bool {
219        self.words == other.words && self.layout == other.layout
220    }
221}
222
223impl Eq for ParserAtn {}
224
225impl fmt::Debug for ParserAtn {
226    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
227        formatter
228            .debug_struct("ParserAtn")
229            .field("max_token_type", &self.max_token_type())
230            .field("stats", &self.stats())
231            .finish_non_exhaustive()
232    }
233}
234
235impl ParserAtn {
236    /// Validates and borrows generator-emitted packed data without allocating.
237    pub fn from_static(words: &'static [u32]) -> Result<Self, ParserAtnError> {
238        let layout = validate_packed(words)?;
239        let atn = Self {
240            words: Cow::Borrowed(words),
241            words_address: words.as_ptr() as usize,
242            layout,
243        };
244        #[cfg(feature = "perf-counters")]
245        atn.record_token_set_inventory();
246        Ok(atn)
247    }
248
249    /// Validates one owned packed stream.
250    pub fn from_owned(words: Vec<u32>) -> Result<Self, ParserAtnError> {
251        let layout = validate_packed(&words)?;
252        let words: Cow<'static, [u32]> = Cow::Owned(words);
253        let words_address = words.as_ptr() as usize;
254        let atn = Self {
255            words,
256            words_address,
257            layout,
258        };
259        #[cfg(feature = "perf-counters")]
260        atn.record_token_set_inventory();
261        Ok(atn)
262    }
263
264    /// Canonical generator/runtime format version carried by this ATN.
265    pub fn format_version(&self) -> u32 {
266        self.words[HEADER_VERSION]
267    }
268
269    #[inline(always)]
270    pub const fn max_token_type(&self) -> i32 {
271        self.layout.max_token_type
272    }
273
274    pub const fn state_count(&self) -> usize {
275        self.layout.state_count
276    }
277
278    pub const fn transition_count(&self) -> usize {
279        self.layout.transition_count
280    }
281
282    pub const fn decision_count(&self) -> usize {
283        self.layout.decisions.len
284    }
285
286    pub const fn rule_count(&self) -> usize {
287        self.layout.rule_starts.len
288    }
289
290    #[inline(always)]
291    pub fn state(&self, state_number: usize) -> Option<ParserAtnState<'_>> {
292        (state_number < self.state_count())
293            .then(|| ParserAtnState::new(self, AtnStateId(state_number as u32)))
294    }
295
296    #[inline(always)]
297    pub fn state_by_id(&self, id: AtnStateId) -> Option<ParserAtnState<'_>> {
298        (id.index() < self.state_count()).then(|| ParserAtnState::new(self, id))
299    }
300
301    pub const fn states(&self) -> ParserAtnStates<'_> {
302        ParserAtnStates {
303            atn: self,
304            next: 0,
305            end: self.state_count(),
306        }
307    }
308
309    #[inline(always)]
310    pub fn transition(&self, id: TransitionId) -> Option<ParserTransition<'_>> {
311        (id.index() < self.transition_count()).then(|| ParserTransition::new(self, id))
312    }
313
314    pub const fn decision_to_state(&self) -> ParserStateIdTable<'_> {
315        ParserStateIdTable::new(self, self.layout.decisions)
316    }
317
318    pub const fn rule_to_start_state(&self) -> ParserStateIdTable<'_> {
319        ParserStateIdTable::new(self, self.layout.rule_starts)
320    }
321
322    pub const fn rule_to_stop_state(&self) -> ParserStateIdTable<'_> {
323        ParserStateIdTable::new(self, self.layout.rule_stops)
324    }
325
326    /// Returns the exact generator-emitted representation.
327    pub fn packed_words(&self) -> &[u32] {
328        &self.words
329    }
330
331    /// Returns one immutable parser token set by its packed metadata index.
332    ///
333    /// Generated rule bodies use this to share the same adaptive membership
334    /// representation as ATN prediction instead of embedding a second set.
335    #[inline(always)]
336    pub fn token_set(&self, index: usize) -> Option<ParserIntervalSet<'_>> {
337        let id = ParserIntervalSetId::try_from(index).ok()?;
338        (index < self.set_count()).then(|| self.interval_set(id))
339    }
340
341    /// Stable backing-storage address used by thread-local grammar caches.
342    pub(crate) fn storage_identity(&self) -> (usize, usize) {
343        (self.words.as_ptr() as usize, self.words.len())
344    }
345
346    pub fn stats(&self) -> ParserAtnStats {
347        let mut inline_token_sets = 0;
348        let mut dense_token_sets = 0;
349        let mut interval_token_sets = 0;
350        let mut token_bitset_bytes = 0;
351        for index in 0..self.set_count() {
352            let set = self
353                .token_set(index)
354                .expect("in-bounds parser token-set index");
355            match set.kind() {
356                ParserTokenSetKind::Inline128 => inline_token_sets += 1,
357                ParserTokenSetKind::Dense => dense_token_sets += 1,
358                ParserTokenSetKind::Intervals => interval_token_sets += 1,
359            }
360            token_bitset_bytes += set.bit_len * size_of::<u64>();
361        }
362        ParserAtnStats {
363            states: self.state_count(),
364            transitions: self.transition_count(),
365            interval_sets: self.set_count(),
366            interval_ranges: self.layout.intervals.len / 2,
367            inline_token_sets,
368            dense_token_sets,
369            interval_token_sets,
370            token_bitset_bytes,
371            decisions: self.decision_count(),
372            rules: self.rule_count(),
373            packed_bytes: self.words.len() * size_of::<u32>(),
374        }
375    }
376
377    pub(crate) const fn set_count(&self) -> usize {
378        self.layout.sets.len / self.layout.set_words
379    }
380
381    #[inline(always)]
382    fn word(&self, section: Section, record: usize, field: usize, width: usize) -> u32 {
383        self.packed_word(section.offset + record * width + field)
384    }
385
386    #[inline(always)]
387    fn interval_set(&self, id: ParserIntervalSetId) -> ParserIntervalSet<'_> {
388        let width = self.layout.set_words;
389        let start = self.word(self.layout.sets, id.index(), 0, width) as usize;
390        let len = self.word(self.layout.sets, id.index(), 1, width) as usize;
391        let (kind, bit_start, bit_len) = if self.layout.format_version == 1 {
392            (ParserTokenSetKind::Intervals, 0, 0)
393        } else {
394            (
395                decode_token_set_kind(self.word(self.layout.sets, id.index(), 2, width))
396                    .expect("packed parser token-set kind was validated"),
397                self.word(self.layout.sets, id.index(), 3, width) as usize,
398                self.word(self.layout.sets, id.index(), 4, width) as usize,
399            )
400        };
401        ParserIntervalSet {
402            atn: self,
403            id,
404            start,
405            len,
406            kind,
407            bit_start,
408            bit_len,
409        }
410    }
411
412    #[inline(always)]
413    fn token_bit_word(&self, index: usize) -> u64 {
414        let offset = self.layout.token_bits.offset + index * PACKED_U64_WORDS;
415        u64::from(self.packed_word(offset)) | (u64::from(self.packed_word(offset + 1)) << u32::BITS)
416    }
417
418    #[cfg(feature = "perf-counters")]
419    fn record_token_set_inventory(&self) {
420        for index in 0..self.set_count() {
421            let set = self
422                .token_set(index)
423                .expect("in-bounds parser token-set index");
424            crate::perf::record_parser_token_set_selection(
425                set.kind(),
426                set.bit_len * size_of::<u64>(),
427            );
428        }
429    }
430
431    #[inline(always)]
432    fn packed_address(&self, index: usize) -> usize {
433        debug_assert!(index < self.words.len());
434        self.words_address + index * size_of::<u32>()
435    }
436
437    #[inline(always)]
438    #[allow(unsafe_code)]
439    fn packed_word(&self, index: usize) -> u32 {
440        debug_assert!(index < self.words.len());
441        // `words_address` is captured after the final backing allocation is in
442        // place. Parser ATNs are immutable, and every view index/range is
443        // validated before construction, so the allocation remains live and
444        // the read stays in bounds for the lifetime of `self`.
445        unsafe { *((self.words_address as *const u32).add(index)) }
446    }
447}
448
449/// Borrowing semantic view over one parser ATN state.
450#[derive(Clone, Copy)]
451pub struct ParserAtnState<'a> {
452    atn: &'a ParserAtn,
453    record_address: usize,
454}
455
456impl fmt::Debug for ParserAtnState<'_> {
457    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
458        formatter
459            .debug_struct("ParserAtnState")
460            .field("id", &self.id())
461            .field("kind", &self.kind())
462            .field("rule_index", &self.rule_index())
463            .field("transition_count", &self.transitions().len())
464            .finish()
465    }
466}
467
468impl<'a> ParserAtnState<'a> {
469    #[inline(always)]
470    fn new(atn: &'a ParserAtn, id: AtnStateId) -> Self {
471        Self {
472            atn,
473            record_address: atn.packed_address(atn.layout.states.offset + id.index() * STATE_WORDS),
474        }
475    }
476
477    pub const fn id(self) -> AtnStateId {
478        let word = (self.record_address - self.atn.words_address) / size_of::<u32>();
479        AtnStateId(((word - self.atn.layout.states.offset) / STATE_WORDS) as u32)
480    }
481
482    pub const fn state_number(self) -> usize {
483        self.id().index()
484    }
485
486    #[inline(always)]
487    pub fn kind(self) -> AtnStateKind {
488        decode_state_kind(self.word(0)).expect("packed parser ATN state kind was validated")
489    }
490
491    #[inline(always)]
492    pub fn rule_index(self) -> Option<usize> {
493        unpack_index(self.word(1))
494    }
495
496    #[inline(always)]
497    pub fn end_state(self) -> Option<usize> {
498        unpack_index(self.word(5))
499    }
500
501    #[inline(always)]
502    pub fn loop_back_state(self) -> Option<usize> {
503        unpack_index(self.word(6))
504    }
505
506    #[inline(always)]
507    pub fn non_greedy(self) -> bool {
508        self.flags() & FLAG_NON_GREEDY != 0
509    }
510
511    #[inline(always)]
512    pub fn precedence_rule_decision(self) -> bool {
513        self.flags() & FLAG_PRECEDENCE_DECISION != 0
514    }
515
516    #[inline(always)]
517    pub fn left_recursive_rule(self) -> bool {
518        self.flags() & FLAG_LEFT_RECURSIVE_RULE != 0
519    }
520
521    #[inline]
522    pub fn is_rule_stop(self) -> bool {
523        self.flags() & FLAG_RULE_STOP != 0
524    }
525
526    #[inline]
527    pub fn epsilon_only(self) -> bool {
528        self.flags() & FLAG_EPSILON_ONLY != 0
529    }
530
531    #[inline]
532    pub fn has_consuming_transition(self) -> bool {
533        self.flags() & FLAG_HAS_CONSUMING != 0
534    }
535
536    #[inline]
537    pub fn has_semantic_transition(self) -> bool {
538        self.flags() & FLAG_HAS_SEMANTIC != 0
539    }
540
541    #[inline(always)]
542    pub fn transitions(self) -> ParserTransitions<'a> {
543        let start = self.word(3) as usize;
544        ParserTransitions {
545            atn: self.atn,
546            record_address: self
547                .atn
548                .packed_address(self.atn.layout.transitions.offset + start * TRANSITION_WORDS),
549            len: self.word(4) as usize,
550        }
551    }
552
553    #[inline(always)]
554    fn flags(self) -> u32 {
555        self.word(2)
556    }
557
558    #[inline(always)]
559    #[allow(unsafe_code)]
560    fn word(self, field: usize) -> u32 {
561        debug_assert!(field < STATE_WORDS);
562        // The record address comes from the immutable validated state
563        // section, and `field` is constrained to the fixed record width.
564        unsafe { *((self.record_address as *const u32).add(field)) }
565    }
566}
567
568/// Borrowing range of transitions owned by the ATN's shared transition pool.
569#[derive(Clone, Copy, Debug)]
570pub struct ParserTransitions<'a> {
571    atn: &'a ParserAtn,
572    record_address: usize,
573    len: usize,
574}
575
576impl<'a> ParserTransitions<'a> {
577    pub const fn len(self) -> usize {
578        self.len
579    }
580
581    pub const fn is_empty(self) -> bool {
582        self.len == 0
583    }
584
585    #[inline(always)]
586    pub fn get(self, index: usize) -> Option<ParserTransition<'a>> {
587        (index < self.len).then(|| ParserTransition {
588            atn: self.atn,
589            record_address: self.record_address + index * TRANSITION_WORDS * size_of::<u32>(),
590        })
591    }
592
593    #[inline(always)]
594    pub fn first(self) -> Option<ParserTransition<'a>> {
595        self.get(0)
596    }
597
598    #[inline]
599    pub fn last(self) -> Option<ParserTransition<'a>> {
600        self.len.checked_sub(1).and_then(|index| self.get(index))
601    }
602
603    pub const fn iter(self) -> ParserTransitionIter<'a> {
604        ParserTransitionIter {
605            atn: self.atn,
606            next_record_address: self.record_address,
607            remaining: self.len,
608        }
609    }
610}
611
612impl<'a> IntoIterator for ParserTransitions<'a> {
613    type Item = ParserTransition<'a>;
614    type IntoIter = ParserTransitionIter<'a>;
615
616    fn into_iter(self) -> Self::IntoIter {
617        self.iter()
618    }
619}
620
621impl<'a> IntoIterator for &'a ParserTransitions<'a> {
622    type Item = ParserTransition<'a>;
623    type IntoIter = ParserTransitionIter<'a>;
624
625    fn into_iter(self) -> Self::IntoIter {
626        self.iter()
627    }
628}
629
630/// Iterator over one state's contiguous transition range.
631#[derive(Clone, Debug)]
632pub struct ParserTransitionIter<'a> {
633    atn: &'a ParserAtn,
634    next_record_address: usize,
635    remaining: usize,
636}
637
638impl<'a> Iterator for ParserTransitionIter<'a> {
639    type Item = ParserTransition<'a>;
640
641    #[inline(always)]
642    fn next(&mut self) -> Option<Self::Item> {
643        if self.remaining == 0 {
644            return None;
645        }
646        let transition = ParserTransition {
647            atn: self.atn,
648            record_address: self.next_record_address,
649        };
650        self.next_record_address += TRANSITION_WORDS * size_of::<u32>();
651        self.remaining -= 1;
652        Some(transition)
653    }
654
655    fn size_hint(&self) -> (usize, Option<usize>) {
656        (self.remaining, Some(self.remaining))
657    }
658}
659
660impl ExactSizeIterator for ParserTransitionIter<'_> {}
661impl FusedIterator for ParserTransitionIter<'_> {}
662
663/// Borrowing semantic view over one parser ATN transition.
664#[derive(Clone, Copy)]
665pub struct ParserTransition<'a> {
666    atn: &'a ParserAtn,
667    record_address: usize,
668}
669
670impl fmt::Debug for ParserTransition<'_> {
671    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
672        self.data().fmt(formatter)
673    }
674}
675
676impl<'a> ParserTransition<'a> {
677    #[inline(always)]
678    fn new(atn: &'a ParserAtn, id: TransitionId) -> Self {
679        Self {
680            atn,
681            record_address: atn
682                .packed_address(atn.layout.transitions.offset + id.index() * TRANSITION_WORDS),
683        }
684    }
685
686    #[inline(always)]
687    pub const fn id(self) -> TransitionId {
688        let word = (self.record_address - self.atn.words_address) / size_of::<u32>();
689        TransitionId(((word - self.atn.layout.transitions.offset) / TRANSITION_WORDS) as u32)
690    }
691
692    #[inline(always)]
693    pub fn target_id(self) -> AtnStateId {
694        AtnStateId(self.word(1))
695    }
696
697    #[inline(always)]
698    pub fn target(self) -> usize {
699        self.target_id().index()
700    }
701
702    #[inline(always)]
703    pub fn kind(self) -> ParserTransitionKind {
704        decode_transition_kind(self.word(0))
705            .expect("packed parser ATN transition kind was validated")
706    }
707
708    #[inline(always)]
709    pub fn is_epsilon(self) -> bool {
710        matches!(
711            self.kind(),
712            ParserTransitionKind::Epsilon
713                | ParserTransitionKind::Rule
714                | ParserTransitionKind::Predicate
715                | ParserTransitionKind::Action
716                | ParserTransitionKind::Precedence
717        )
718    }
719
720    #[inline(always)]
721    pub fn is_action(self) -> bool {
722        self.kind() == ParserTransitionKind::Action
723    }
724
725    #[inline(always)]
726    pub fn matches(self, symbol: i32, min_vocabulary: i32, max_vocabulary: i32) -> bool {
727        self.matches_kind(self.kind(), symbol, min_vocabulary, max_vocabulary)
728    }
729
730    #[inline(always)]
731    pub(crate) fn matches_kind(
732        self,
733        kind: ParserTransitionKind,
734        symbol: i32,
735        min_vocabulary: i32,
736        max_vocabulary: i32,
737    ) -> bool {
738        match kind {
739            ParserTransitionKind::Atom => unpack_i32(self.arg0()) == symbol,
740            ParserTransitionKind::Range => {
741                (unpack_i32(self.arg0())..=unpack_i32(self.arg1())).contains(&symbol)
742            }
743            ParserTransitionKind::Set => self
744                .atn
745                .interval_set(ParserIntervalSetId(self.arg0()))
746                .contains(symbol),
747            ParserTransitionKind::NotSet => {
748                (min_vocabulary..=max_vocabulary).contains(&symbol)
749                    && !self
750                        .atn
751                        .interval_set(ParserIntervalSetId(self.arg0()))
752                        .contains(symbol)
753            }
754            ParserTransitionKind::Wildcard => (min_vocabulary..=max_vocabulary).contains(&symbol),
755            ParserTransitionKind::Epsilon
756            | ParserTransitionKind::Rule
757            | ParserTransitionKind::Predicate
758            | ParserTransitionKind::Action
759            | ParserTransitionKind::Precedence => false,
760        }
761    }
762
763    #[inline(always)]
764    pub(crate) fn arg0(self) -> u32 {
765        self.word(2)
766    }
767
768    #[inline(always)]
769    pub(crate) fn arg1(self) -> u32 {
770        self.word(3)
771    }
772
773    #[inline(always)]
774    pub(crate) fn arg2(self) -> u32 {
775        self.word(4)
776    }
777
778    #[inline(always)]
779    pub fn data(self) -> ParserTransitionData<'a> {
780        match decode_transition_kind(self.word(0))
781            .expect("packed parser ATN transition kind was validated")
782        {
783            ParserTransitionKind::Epsilon => ParserTransitionData::Epsilon {
784                target: self.word(1) as usize,
785            },
786            ParserTransitionKind::Atom => ParserTransitionData::Atom {
787                target: self.word(1) as usize,
788                label: unpack_i32(self.word(2)),
789            },
790            ParserTransitionKind::Range => ParserTransitionData::Range {
791                target: self.word(1) as usize,
792                start: unpack_i32(self.word(2)),
793                stop: unpack_i32(self.word(3)),
794            },
795            ParserTransitionKind::Set => ParserTransitionData::Set {
796                target: self.word(1) as usize,
797                set: self.atn.interval_set(ParserIntervalSetId(self.word(2))),
798            },
799            ParserTransitionKind::NotSet => ParserTransitionData::NotSet {
800                target: self.word(1) as usize,
801                set: self.atn.interval_set(ParserIntervalSetId(self.word(2))),
802            },
803            ParserTransitionKind::Wildcard => ParserTransitionData::Wildcard {
804                target: self.word(1) as usize,
805            },
806            ParserTransitionKind::Rule => ParserTransitionData::Rule {
807                target: self.word(1) as usize,
808                rule_index: self.word(2) as usize,
809                follow_state: self.word(3) as usize,
810                precedence: unpack_i32(self.word(4)),
811            },
812            ParserTransitionKind::Predicate => ParserTransitionData::Predicate {
813                target: self.word(1) as usize,
814                rule_index: self.word(2) as usize,
815                pred_index: self.word(3) as usize,
816                context_dependent: self.word(4) != 0,
817            },
818            ParserTransitionKind::Action => ParserTransitionData::Action {
819                target: self.word(1) as usize,
820                rule_index: self.word(2) as usize,
821                action_index: unpack_index(self.word(3)),
822                context_dependent: self.word(4) != 0,
823            },
824            ParserTransitionKind::Precedence => ParserTransitionData::Precedence {
825                target: self.word(1) as usize,
826                precedence: unpack_i32(self.word(2)),
827            },
828        }
829    }
830
831    #[inline(always)]
832    #[allow(unsafe_code)]
833    fn word(self, field: usize) -> u32 {
834        debug_assert!(field < TRANSITION_WORDS);
835        // The record address comes from the immutable validated transition
836        // section, and `field` is constrained to the fixed record width.
837        unsafe { *((self.record_address as *const u32).add(field)) }
838    }
839}
840
841/// Fixed transition tag stored in the packed transition table.
842#[derive(Clone, Copy, Debug, Eq, PartialEq)]
843#[repr(u8)]
844pub enum ParserTransitionKind {
845    Epsilon = 1,
846    Range = 2,
847    Rule = 3,
848    Predicate = 4,
849    Atom = 5,
850    Action = 6,
851    Set = 7,
852    NotSet = 8,
853    Wildcard = 9,
854    Precedence = 10,
855}
856
857/// Borrowing semantic payload for a packed parser transition.
858#[derive(Clone, Copy, Debug, Eq, PartialEq)]
859pub enum ParserTransitionData<'a> {
860    Epsilon {
861        target: usize,
862    },
863    Atom {
864        target: usize,
865        label: i32,
866    },
867    Range {
868        target: usize,
869        start: i32,
870        stop: i32,
871    },
872    Set {
873        target: usize,
874        set: ParserIntervalSet<'a>,
875    },
876    NotSet {
877        target: usize,
878        set: ParserIntervalSet<'a>,
879    },
880    Wildcard {
881        target: usize,
882    },
883    Rule {
884        target: usize,
885        rule_index: usize,
886        follow_state: usize,
887        precedence: i32,
888    },
889    Predicate {
890        target: usize,
891        rule_index: usize,
892        pred_index: usize,
893        context_dependent: bool,
894    },
895    Action {
896        target: usize,
897        rule_index: usize,
898        action_index: Option<usize>,
899        context_dependent: bool,
900    },
901    Precedence {
902        target: usize,
903        precedence: i32,
904    },
905}
906
907impl ParserTransitionData<'_> {
908    pub const fn target(self) -> usize {
909        match self {
910            Self::Epsilon { target }
911            | Self::Atom { target, .. }
912            | Self::Range { target, .. }
913            | Self::Set { target, .. }
914            | Self::NotSet { target, .. }
915            | Self::Wildcard { target }
916            | Self::Rule { target, .. }
917            | Self::Predicate { target, .. }
918            | Self::Action { target, .. }
919            | Self::Precedence { target, .. } => target,
920        }
921    }
922
923    pub const fn is_epsilon(self) -> bool {
924        matches!(
925            self,
926            Self::Epsilon { .. }
927                | Self::Rule { .. }
928                | Self::Predicate { .. }
929                | Self::Action { .. }
930                | Self::Precedence { .. }
931        )
932    }
933
934    pub const fn is_action(self) -> bool {
935        matches!(self, Self::Action { .. })
936    }
937
938    pub fn matches(self, symbol: i32, min_vocabulary: i32, max_vocabulary: i32) -> bool {
939        match self {
940            Self::Atom { label, .. } => label == symbol,
941            Self::Range { start, stop, .. } => (start..=stop).contains(&symbol),
942            Self::Set { set, .. } => set.contains(symbol),
943            Self::NotSet { set, .. } => {
944                (min_vocabulary..=max_vocabulary).contains(&symbol) && !set.contains(symbol)
945            }
946            Self::Wildcard { .. } => (min_vocabulary..=max_vocabulary).contains(&symbol),
947            Self::Epsilon { .. }
948            | Self::Rule { .. }
949            | Self::Predicate { .. }
950            | Self::Action { .. }
951            | Self::Precedence { .. } => false,
952        }
953    }
954}
955
956/// Borrowing view over one interval set in the shared interval pool.
957#[derive(Clone, Copy, Eq, PartialEq)]
958pub struct ParserIntervalSet<'a> {
959    atn: &'a ParserAtn,
960    id: ParserIntervalSetId,
961    start: usize,
962    len: usize,
963    kind: ParserTokenSetKind,
964    bit_start: usize,
965    bit_len: usize,
966}
967
968impl fmt::Debug for ParserIntervalSet<'_> {
969    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
970        formatter.debug_list().entries(self.ranges()).finish()
971    }
972}
973
974impl<'a> ParserIntervalSet<'a> {
975    /// Stable index of this set in the packed parser metadata.
976    pub const fn index(self) -> usize {
977        self.id.index()
978    }
979
980    /// Membership representation selected when the packed ATN was built.
981    pub const fn kind(self) -> ParserTokenSetKind {
982        self.kind
983    }
984
985    pub const fn is_empty(self) -> bool {
986        self.len == 0
987    }
988
989    // Forced inlining bloats recursive recognizer frames in unoptimized builds.
990    #[inline]
991    pub fn contains(self, value: i32) -> bool {
992        let hit = match self.kind {
993            ParserTokenSetKind::Inline128 | ParserTokenSetKind::Dense => {
994                self.contains_bitset(value)
995            }
996            ParserTokenSetKind::Intervals => self.contains_intervals(value),
997        };
998        #[cfg(feature = "perf-counters")]
999        crate::perf::record_parser_token_set_probe(self.kind, hit);
1000        hit
1001    }
1002
1003    #[inline(always)]
1004    fn contains_bitset(self, value: i32) -> bool {
1005        let Some(slot) = token_set_slot(value) else {
1006            return false;
1007        };
1008        let word = slot / u64::BITS as usize;
1009        word < self.bit_len
1010            && self.atn.token_bit_word(self.bit_start + word)
1011                & (1_u64 << (slot % u64::BITS as usize))
1012                != 0
1013    }
1014
1015    #[inline(always)]
1016    fn contains_intervals(self, value: i32) -> bool {
1017        let mut low = 0;
1018        let mut high = self.len;
1019        while low < high {
1020            let middle = low + (high - low) / 2;
1021            if self.range_start(middle) <= value {
1022                low = middle + 1;
1023            } else {
1024                high = middle;
1025            }
1026        }
1027        low > 0 && self.range_stop(low - 1) >= value
1028    }
1029
1030    pub const fn ranges(self) -> ParserIntervalRanges<'a> {
1031        ParserIntervalRanges { set: self, next: 0 }
1032    }
1033
1034    #[inline(always)]
1035    fn range(self, index: usize) -> (i32, i32) {
1036        (self.range_start(index), self.range_stop(index))
1037    }
1038
1039    #[inline(always)]
1040    fn range_start(self, index: usize) -> i32 {
1041        let word = self.atn.layout.intervals.offset + (self.start + index) * 2;
1042        unpack_i32(self.atn.packed_word(word))
1043    }
1044
1045    #[inline(always)]
1046    fn range_stop(self, index: usize) -> i32 {
1047        let word = self.atn.layout.intervals.offset + (self.start + index) * 2 + 1;
1048        unpack_i32(self.atn.packed_word(word))
1049    }
1050}
1051
1052/// Iterator over inclusive ranges in one shared parser interval set.
1053#[derive(Clone, Debug)]
1054pub struct ParserIntervalRanges<'a> {
1055    set: ParserIntervalSet<'a>,
1056    next: usize,
1057}
1058
1059impl Iterator for ParserIntervalRanges<'_> {
1060    type Item = (i32, i32);
1061
1062    #[inline]
1063    fn next(&mut self) -> Option<Self::Item> {
1064        if self.next >= self.set.len {
1065            return None;
1066        }
1067        let range = self.set.range(self.next);
1068        self.next += 1;
1069        Some(range)
1070    }
1071
1072    fn size_hint(&self) -> (usize, Option<usize>) {
1073        let remaining = self.set.len.saturating_sub(self.next);
1074        (remaining, Some(remaining))
1075    }
1076}
1077
1078impl ExactSizeIterator for ParserIntervalRanges<'_> {}
1079impl FusedIterator for ParserIntervalRanges<'_> {}
1080
1081/// Borrowing compact-ID side table with checked `usize` accessors.
1082#[derive(Clone, Copy, Debug)]
1083pub struct ParserStateIdTable<'a> {
1084    atn: &'a ParserAtn,
1085    section: Section,
1086}
1087
1088impl<'a> ParserStateIdTable<'a> {
1089    const fn new(atn: &'a ParserAtn, section: Section) -> Self {
1090        Self { atn, section }
1091    }
1092
1093    pub const fn len(self) -> usize {
1094        self.section.len
1095    }
1096
1097    pub const fn is_empty(self) -> bool {
1098        self.section.len == 0
1099    }
1100
1101    #[inline(always)]
1102    pub fn get(self, index: usize) -> Option<usize> {
1103        (index < self.len()).then(|| self.atn.packed_word(self.section.offset + index) as usize)
1104    }
1105
1106    pub fn get_id(self, index: usize) -> Option<AtnStateId> {
1107        self.get(index).map(|value| {
1108            AtnStateId::try_from(value).expect("validated side-table state fits compact ID")
1109        })
1110    }
1111
1112    pub const fn iter(self) -> ParserStateIdIter<'a> {
1113        ParserStateIdIter {
1114            table: self,
1115            next: 0,
1116        }
1117    }
1118}
1119
1120impl<'a> IntoIterator for ParserStateIdTable<'a> {
1121    type Item = usize;
1122    type IntoIter = ParserStateIdIter<'a>;
1123
1124    fn into_iter(self) -> Self::IntoIter {
1125        self.iter()
1126    }
1127}
1128
1129/// Iterator over checked state indices in a parser ATN side table.
1130#[derive(Clone, Debug)]
1131pub struct ParserStateIdIter<'a> {
1132    table: ParserStateIdTable<'a>,
1133    next: usize,
1134}
1135
1136impl Iterator for ParserStateIdIter<'_> {
1137    type Item = usize;
1138
1139    #[inline]
1140    fn next(&mut self) -> Option<Self::Item> {
1141        let value = self.table.get(self.next)?;
1142        self.next += 1;
1143        Some(value)
1144    }
1145
1146    fn size_hint(&self) -> (usize, Option<usize>) {
1147        let remaining = self.table.len().saturating_sub(self.next);
1148        (remaining, Some(remaining))
1149    }
1150}
1151
1152impl ExactSizeIterator for ParserStateIdIter<'_> {}
1153impl FusedIterator for ParserStateIdIter<'_> {}
1154
1155/// Iterator over every state in deterministic state-number order.
1156#[derive(Clone, Debug)]
1157pub struct ParserAtnStates<'a> {
1158    atn: &'a ParserAtn,
1159    next: usize,
1160    end: usize,
1161}
1162
1163impl<'a> Iterator for ParserAtnStates<'a> {
1164    type Item = ParserAtnState<'a>;
1165
1166    #[inline]
1167    fn next(&mut self) -> Option<Self::Item> {
1168        if self.next >= self.end {
1169            return None;
1170        }
1171        let state = self.atn.state(self.next);
1172        self.next += 1;
1173        state
1174    }
1175
1176    fn size_hint(&self) -> (usize, Option<usize>) {
1177        let remaining = self.end.saturating_sub(self.next);
1178        (remaining, Some(remaining))
1179    }
1180}
1181
1182impl ExactSizeIterator for ParserAtnStates<'_> {}
1183impl FusedIterator for ParserAtnStates<'_> {}
1184
1185/// Centralized construction API for packed parser ATNs.
1186///
1187/// States never own transition collections; edges are grouped into contiguous
1188/// ranges only when the final packed stream is emitted.
1189#[derive(Debug)]
1190pub struct ParserAtnBuilder {
1191    max_token_type: i32,
1192    states: Vec<StateBuild>,
1193    transitions: Vec<TransitionBuild>,
1194    /// Per-source transition indices in insertion order, so duplicate
1195    /// detection scans one state's out-edges instead of every transition
1196    /// added so far (which made re-emitting a whole ATN quadratic).
1197    transitions_by_source: BTreeMap<AtnStateId, Vec<usize>>,
1198    interval_sets: Vec<TokenSetBuild>,
1199    interval_ranges: Vec<(i32, i32)>,
1200    token_bit_words: Vec<u64>,
1201    decisions: Vec<AtnStateId>,
1202    rule_starts: Vec<AtnStateId>,
1203    rule_stops: Vec<AtnStateId>,
1204}
1205
1206impl ParserAtnBuilder {
1207    pub const fn new(max_token_type: i32) -> Self {
1208        Self {
1209            max_token_type,
1210            states: Vec::new(),
1211            transitions: Vec::new(),
1212            transitions_by_source: BTreeMap::new(),
1213            interval_sets: Vec::new(),
1214            interval_ranges: Vec::new(),
1215            token_bit_words: Vec::new(),
1216            decisions: Vec::new(),
1217            rule_starts: Vec::new(),
1218            rule_stops: Vec::new(),
1219        }
1220    }
1221
1222    pub fn add_state(
1223        &mut self,
1224        kind: AtnStateKind,
1225        rule_index: Option<usize>,
1226    ) -> Result<AtnStateId, ParserAtnError> {
1227        let id = AtnStateId::try_from(self.states.len())?;
1228        let rule_index = pack_optional_index("parser ATN rule", rule_index)?;
1229        self.states.push(StateBuild {
1230            kind,
1231            rule_index,
1232            flags: u32::from(kind == AtnStateKind::RuleStop) * FLAG_RULE_STOP,
1233            end_state: NO_INDEX,
1234            loop_back_state: NO_INDEX,
1235        });
1236        Ok(id)
1237    }
1238
1239    pub fn set_end_state(&mut self, state: usize, end_state: usize) -> Result<(), ParserAtnError> {
1240        let end_state = self.checked_state(end_state, "block end state")?;
1241        self.state_mut(state, "block start state")?.end_state = end_state.raw();
1242        Ok(())
1243    }
1244
1245    pub fn set_loop_back_state(
1246        &mut self,
1247        state: usize,
1248        loop_back_state: usize,
1249    ) -> Result<(), ParserAtnError> {
1250        let loop_back_state = self.checked_state(loop_back_state, "loop back state")?;
1251        self.state_mut(state, "loop end state")?.loop_back_state = loop_back_state.raw();
1252        Ok(())
1253    }
1254
1255    pub fn set_non_greedy(&mut self, state: usize) -> Result<(), ParserAtnError> {
1256        self.state_mut(state, "non-greedy state")?.flags |= FLAG_NON_GREEDY;
1257        Ok(())
1258    }
1259
1260    pub fn set_left_recursive_rule(&mut self, state: usize) -> Result<(), ParserAtnError> {
1261        self.state_mut(state, "precedence rule state")?.flags |= FLAG_LEFT_RECURSIVE_RULE;
1262        Ok(())
1263    }
1264
1265    pub fn set_precedence_rule_decision(&mut self, state: usize) -> Result<(), ParserAtnError> {
1266        self.state_mut(state, "precedence decision state")?.flags |= FLAG_PRECEDENCE_DECISION;
1267        Ok(())
1268    }
1269
1270    pub fn add_interval_set(
1271        &mut self,
1272        ranges: impl IntoIterator<Item = (i32, i32)>,
1273    ) -> Result<ParserIntervalSetId, ParserAtnError> {
1274        let id = ParserIntervalSetId::try_from(self.interval_sets.len())?;
1275        let normalized = normalize_ranges(ranges);
1276        let interval_start = compact_id("parser ATN interval start", self.interval_ranges.len())?;
1277        let interval_len = compact_id("parser ATN interval count", normalized.len())?;
1278        let prepared = prepare_token_set(&normalized);
1279        let bit_start = compact_id("parser token-set bit start", self.token_bit_words.len())?;
1280        let bit_len = compact_id("parser token-set bit count", prepared.words.len())?;
1281        self.interval_ranges.extend(normalized);
1282        self.token_bit_words.extend(prepared.words);
1283        self.interval_sets.push(TokenSetBuild {
1284            interval_start,
1285            interval_len,
1286            kind: prepared.kind,
1287            bit_start,
1288            bit_len,
1289        });
1290        Ok(id)
1291    }
1292
1293    pub fn add_transition(
1294        &mut self,
1295        source: usize,
1296        transition: ParserTransitionSpec,
1297    ) -> Result<TransitionId, ParserAtnError> {
1298        let source = self.checked_state(source, "transition source")?;
1299        if let Some(existing) = self.transitions_by_source.get(&source) {
1300            if let Some(&index) = existing
1301                .iter()
1302                .find(|&&index| self.transitions[index].spec() == transition)
1303            {
1304                return TransitionId::try_from(index);
1305            }
1306        }
1307        let record = self.transition_record(source, transition)?;
1308        let index = self.transitions.len();
1309        let id = TransitionId::try_from(index)?;
1310        self.transitions.push(record);
1311        self.transitions_by_source
1312            .entry(source)
1313            .or_default()
1314            .push(index);
1315        Ok(id)
1316    }
1317
1318    pub fn set_rule_to_start_state(&mut self, states: Vec<usize>) -> Result<(), ParserAtnError> {
1319        self.rule_starts = self.checked_states(states, "rule start state")?;
1320        Ok(())
1321    }
1322
1323    pub fn set_rule_to_stop_state(&mut self, states: Vec<usize>) -> Result<(), ParserAtnError> {
1324        self.rule_stops = self.checked_states(states, "rule stop state")?;
1325        Ok(())
1326    }
1327
1328    pub fn add_decision_state(&mut self, state: usize) -> Result<(), ParserAtnError> {
1329        let state = self.checked_state(state, "decision state")?;
1330        self.decisions.push(state);
1331        Ok(())
1332    }
1333
1334    pub fn state_kind(&self, state: usize) -> Option<AtnStateKind> {
1335        self.states.get(state).map(|record| record.kind)
1336    }
1337
1338    pub const fn state_count(&self) -> usize {
1339        self.states.len()
1340    }
1341
1342    pub fn state_rule_index(&self, state: usize) -> Option<usize> {
1343        self.states
1344            .get(state)
1345            .and_then(|record| unpack_index(record.rule_index))
1346    }
1347
1348    pub fn rule_stop_state(&self, rule: usize) -> Option<usize> {
1349        self.rule_stops.get(rule).copied().map(AtnStateId::index)
1350    }
1351
1352    pub fn transitions_from(
1353        &self,
1354        source: usize,
1355    ) -> impl DoubleEndedIterator<Item = ParserTransitionSpec> + '_ {
1356        self.transitions
1357            .iter()
1358            .filter(move |transition| transition.source.index() == source)
1359            .map(TransitionBuild::spec)
1360    }
1361
1362    pub fn finish(mut self) -> Result<ParserAtn, ParserAtnError> {
1363        self.mark_precedence_decisions();
1364        self.transitions.sort_by_key(|transition| transition.source);
1365        let transition_ranges = self.transition_ranges()?;
1366        self.precompute_state_flags(&transition_ranges);
1367        let words = self.encode(&transition_ranges)?;
1368        ParserAtn::from_owned(words)
1369    }
1370
1371    fn state_mut(&mut self, state: usize, label: &str) -> Result<&mut StateBuild, ParserAtnError> {
1372        self.states.get_mut(state).ok_or_else(|| {
1373            ParserAtnError::InvalidData(format!("{label} {state} outside state list"))
1374        })
1375    }
1376
1377    fn checked_state(&self, state: usize, label: &str) -> Result<AtnStateId, ParserAtnError> {
1378        let id = AtnStateId::try_from(state)?;
1379        if state >= self.states.len() {
1380            return Err(ParserAtnError::InvalidData(format!(
1381                "{label} {state} outside state list"
1382            )));
1383        }
1384        Ok(id)
1385    }
1386
1387    fn checked_states(
1388        &self,
1389        states: Vec<usize>,
1390        label: &str,
1391    ) -> Result<Vec<AtnStateId>, ParserAtnError> {
1392        states
1393            .into_iter()
1394            .map(|state| self.checked_state(state, label))
1395            .collect()
1396    }
1397
1398    fn transition_record(
1399        &self,
1400        source: AtnStateId,
1401        spec: ParserTransitionSpec,
1402    ) -> Result<TransitionBuild, ParserAtnError> {
1403        let target = self.checked_state(spec.target(), "transition target")?;
1404        let (kind, arg0, arg1, arg2) = match spec {
1405            ParserTransitionSpec::Epsilon { .. } => (ParserTransitionKind::Epsilon, 0, 0, 0),
1406            ParserTransitionSpec::Atom { label, .. } => {
1407                (ParserTransitionKind::Atom, pack_i32(label), 0, 0)
1408            }
1409            ParserTransitionSpec::Range { start, stop, .. } => (
1410                ParserTransitionKind::Range,
1411                pack_i32(start),
1412                pack_i32(stop),
1413                0,
1414            ),
1415            ParserTransitionSpec::Set { set, .. } => {
1416                self.checked_set(set)?;
1417                (ParserTransitionKind::Set, set.raw(), 0, 0)
1418            }
1419            ParserTransitionSpec::NotSet { set, .. } => {
1420                self.checked_set(set)?;
1421                (ParserTransitionKind::NotSet, set.raw(), 0, 0)
1422            }
1423            ParserTransitionSpec::Wildcard { .. } => (ParserTransitionKind::Wildcard, 0, 0, 0),
1424            ParserTransitionSpec::Rule {
1425                rule_index,
1426                follow_state,
1427                precedence,
1428                ..
1429            } => (
1430                ParserTransitionKind::Rule,
1431                compact_id("rule transition rule", rule_index)?,
1432                self.checked_state(follow_state, "rule follow state")?.raw(),
1433                pack_i32(precedence),
1434            ),
1435            ParserTransitionSpec::Predicate {
1436                rule_index,
1437                pred_index,
1438                context_dependent,
1439                ..
1440            } => (
1441                ParserTransitionKind::Predicate,
1442                compact_id("predicate rule", rule_index)?,
1443                compact_id("predicate index", pred_index)?,
1444                u32::from(context_dependent),
1445            ),
1446            ParserTransitionSpec::Action {
1447                rule_index,
1448                action_index,
1449                context_dependent,
1450                ..
1451            } => (
1452                ParserTransitionKind::Action,
1453                compact_id("action rule", rule_index)?,
1454                pack_optional_index("action", action_index)?,
1455                u32::from(context_dependent),
1456            ),
1457            ParserTransitionSpec::Precedence { precedence, .. } => {
1458                (ParserTransitionKind::Precedence, pack_i32(precedence), 0, 0)
1459            }
1460        };
1461        Ok(TransitionBuild {
1462            source,
1463            kind,
1464            target,
1465            arg0,
1466            arg1,
1467            arg2,
1468        })
1469    }
1470
1471    fn checked_set(&self, set: ParserIntervalSetId) -> Result<(), ParserAtnError> {
1472        if set.index() >= self.interval_sets.len() {
1473            return Err(ParserAtnError::InvalidData(format!(
1474                "interval set {} outside set list",
1475                set.index()
1476            )));
1477        }
1478        Ok(())
1479    }
1480
1481    fn transition_ranges(&self) -> Result<Vec<(u32, u32)>, ParserAtnError> {
1482        let mut ranges = vec![(0, 0); self.states.len()];
1483        let mut cursor = 0;
1484        for (state, range) in ranges.iter_mut().enumerate() {
1485            let start = cursor;
1486            while cursor < self.transitions.len()
1487                && self.transitions[cursor].source.index() == state
1488            {
1489                cursor += 1;
1490            }
1491            *range = (
1492                compact_id("state transition start", start)?,
1493                compact_id("state transition count", cursor - start)?,
1494            );
1495        }
1496        Ok(ranges)
1497    }
1498
1499    fn precompute_state_flags(&mut self, ranges: &[(u32, u32)]) {
1500        for (state, &(start, len)) in self.states.iter_mut().zip(ranges) {
1501            let transitions = &self.transitions[start as usize..start as usize + len as usize];
1502            if !transitions.is_empty()
1503                && transitions
1504                    .iter()
1505                    .all(|transition| transition.kind.is_epsilon())
1506            {
1507                state.flags |= FLAG_EPSILON_ONLY;
1508            }
1509            if transitions
1510                .iter()
1511                .any(|transition| transition.kind.is_consuming())
1512            {
1513                state.flags |= FLAG_HAS_CONSUMING;
1514            }
1515            if transitions
1516                .iter()
1517                .any(|transition| transition.kind.is_semantic())
1518            {
1519                state.flags |= FLAG_HAS_SEMANTIC;
1520            }
1521        }
1522    }
1523
1524    fn mark_precedence_decisions(&mut self) {
1525        let candidates = (0..self.states.len())
1526            .filter(|&state| self.is_precedence_decision(state))
1527            .collect::<Vec<_>>();
1528        for state in candidates {
1529            self.states[state].flags |= FLAG_PRECEDENCE_DECISION;
1530        }
1531    }
1532
1533    fn is_precedence_decision(&self, state: usize) -> bool {
1534        let record = &self.states[state];
1535        if record.kind != AtnStateKind::StarLoopEntry {
1536            return false;
1537        }
1538        let Some(rule_index) = unpack_index(record.rule_index) else {
1539            return false;
1540        };
1541        let Some(rule_start) = self.rule_starts.get(rule_index) else {
1542            return false;
1543        };
1544        if self.states[rule_start.index()].flags & FLAG_LEFT_RECURSIVE_RULE == 0 {
1545            return false;
1546        }
1547        let Some(loop_end) = self.transitions_from(state).next_back() else {
1548            return false;
1549        };
1550        let loop_end = loop_end.target();
1551        if self.state_kind(loop_end) != Some(AtnStateKind::LoopEnd) {
1552            return false;
1553        }
1554        self.transitions_from(loop_end)
1555            .next()
1556            .and_then(|transition| self.state_kind(transition.target()))
1557            == Some(AtnStateKind::RuleStop)
1558    }
1559
1560    fn encode(&self, transition_ranges: &[(u32, u32)]) -> Result<Vec<u32>, ParserAtnError> {
1561        let layout = EncodedLayout::new(self)?;
1562        let mut words = vec![0; layout.total_len];
1563        self.encode_header(&mut words, layout)?;
1564        self.encode_states(&mut words, layout.states, transition_ranges);
1565        self.encode_transitions(&mut words, layout.transitions);
1566        self.encode_sets(&mut words, layout.sets);
1567        self.encode_intervals(&mut words, layout.intervals);
1568        self.encode_token_bits(&mut words, layout.token_bits);
1569        encode_ids(&mut words, layout.decisions, &self.decisions);
1570        encode_ids(&mut words, layout.rule_starts, &self.rule_starts);
1571        encode_ids(&mut words, layout.rule_stops, &self.rule_stops);
1572        Ok(words)
1573    }
1574
1575    fn encode_header(
1576        &self,
1577        words: &mut [u32],
1578        layout: EncodedLayout,
1579    ) -> Result<(), ParserAtnError> {
1580        words[HEADER_MAGIC] = PARSER_ATN_MAGIC;
1581        words[HEADER_VERSION] = PARSER_ATN_FORMAT_VERSION;
1582        words[HEADER_BYTE_ORDER] = PARSER_ATN_BYTE_ORDER;
1583        words[HEADER_SIZE] = compact_id("parser ATN header size", HEADER_WORDS)?;
1584        words[HEADER_MAX_TOKEN_TYPE] = pack_i32(self.max_token_type);
1585        words[HEADER_STATE_COUNT] = compact_id("parser ATN state count", self.states.len())?;
1586        words[HEADER_TRANSITION_COUNT] =
1587            compact_id("parser ATN transition count", self.transitions.len())?;
1588        words[HEADER_SET_COUNT] =
1589            compact_id("parser ATN interval-set count", self.interval_sets.len())?;
1590        words[HEADER_INTERVAL_COUNT] =
1591            compact_id("parser ATN interval count", self.interval_ranges.len())?;
1592        words[HEADER_DECISION_COUNT] =
1593            compact_id("parser ATN decision count", self.decisions.len())?;
1594        words[HEADER_RULE_COUNT] = compact_id("parser ATN rule count", self.rule_starts.len())?;
1595        write_section(words, HEADER_STATES_OFFSET, layout.states)?;
1596        write_section(words, HEADER_TRANSITIONS_OFFSET, layout.transitions)?;
1597        write_section(words, HEADER_SETS_OFFSET, layout.sets)?;
1598        write_section(words, HEADER_INTERVALS_OFFSET, layout.intervals)?;
1599        words[HEADER_TOKEN_BIT_WORD_COUNT] = compact_id(
1600            "parser token-set bit word count",
1601            self.token_bit_words.len(),
1602        )?;
1603        write_section(words, HEADER_TOKEN_BITS_OFFSET, layout.token_bits)?;
1604        write_section(words, HEADER_DECISIONS_OFFSET, layout.decisions)?;
1605        write_section(words, HEADER_RULE_STARTS_OFFSET, layout.rule_starts)?;
1606        write_section(words, HEADER_RULE_STOPS_OFFSET, layout.rule_stops)?;
1607        words[HEADER_TOTAL_LEN] = compact_id("packed parser ATN word", layout.total_len)?;
1608        Ok(())
1609    }
1610
1611    fn encode_states(&self, words: &mut [u32], section: Section, transition_ranges: &[(u32, u32)]) {
1612        for (index, (state, &(start, len))) in self.states.iter().zip(transition_ranges).enumerate()
1613        {
1614            let base = section.offset + index * STATE_WORDS;
1615            words[base] = state_kind_word(state.kind);
1616            words[base + 1] = state.rule_index;
1617            words[base + 2] = state.flags;
1618            words[base + 3] = start;
1619            words[base + 4] = len;
1620            words[base + 5] = state.end_state;
1621            words[base + 6] = state.loop_back_state;
1622        }
1623    }
1624
1625    fn encode_transitions(&self, words: &mut [u32], section: Section) {
1626        for (index, transition) in self.transitions.iter().enumerate() {
1627            let base = section.offset + index * TRANSITION_WORDS;
1628            words[base] = transition.kind as u32;
1629            words[base + 1] = transition.target.raw();
1630            words[base + 2] = transition.arg0;
1631            words[base + 3] = transition.arg1;
1632            words[base + 4] = transition.arg2;
1633        }
1634    }
1635
1636    fn encode_sets(&self, words: &mut [u32], section: Section) {
1637        for (index, set) in self.interval_sets.iter().enumerate() {
1638            let base = section.offset + index * SET_WORDS;
1639            words[base] = set.interval_start;
1640            words[base + 1] = set.interval_len;
1641            words[base + 2] = set.kind as u32;
1642            words[base + 3] = set.bit_start;
1643            words[base + 4] = set.bit_len;
1644        }
1645    }
1646
1647    fn encode_intervals(&self, words: &mut [u32], section: Section) {
1648        for (index, &(start, stop)) in self.interval_ranges.iter().enumerate() {
1649            let base = section.offset + index * 2;
1650            words[base] = pack_i32(start);
1651            words[base + 1] = pack_i32(stop);
1652        }
1653    }
1654
1655    fn encode_token_bits(&self, words: &mut [u32], section: Section) {
1656        for (index, &bits) in self.token_bit_words.iter().enumerate() {
1657            let base = section.offset + index * PACKED_U64_WORDS;
1658            words[base] = bits as u32;
1659            words[base + 1] = (bits >> u32::BITS) as u32;
1660        }
1661    }
1662}
1663
1664/// Transient semantic transition accepted by [`ParserAtnBuilder`].
1665#[derive(Clone, Copy, Debug, Eq, PartialEq)]
1666pub enum ParserTransitionSpec {
1667    Epsilon {
1668        target: usize,
1669    },
1670    Atom {
1671        target: usize,
1672        label: i32,
1673    },
1674    Range {
1675        target: usize,
1676        start: i32,
1677        stop: i32,
1678    },
1679    Set {
1680        target: usize,
1681        set: ParserIntervalSetId,
1682    },
1683    NotSet {
1684        target: usize,
1685        set: ParserIntervalSetId,
1686    },
1687    Wildcard {
1688        target: usize,
1689    },
1690    Rule {
1691        target: usize,
1692        rule_index: usize,
1693        follow_state: usize,
1694        precedence: i32,
1695    },
1696    Predicate {
1697        target: usize,
1698        rule_index: usize,
1699        pred_index: usize,
1700        context_dependent: bool,
1701    },
1702    Action {
1703        target: usize,
1704        rule_index: usize,
1705        action_index: Option<usize>,
1706        context_dependent: bool,
1707    },
1708    Precedence {
1709        target: usize,
1710        precedence: i32,
1711    },
1712}
1713
1714impl ParserTransitionSpec {
1715    pub const fn target(self) -> usize {
1716        match self {
1717            Self::Epsilon { target }
1718            | Self::Atom { target, .. }
1719            | Self::Range { target, .. }
1720            | Self::Set { target, .. }
1721            | Self::NotSet { target, .. }
1722            | Self::Wildcard { target }
1723            | Self::Rule { target, .. }
1724            | Self::Predicate { target, .. }
1725            | Self::Action { target, .. }
1726            | Self::Precedence { target, .. } => target,
1727        }
1728    }
1729
1730    /// Returns this spec with its target redirected, preserving every other
1731    /// field.
1732    #[must_use]
1733    pub(crate) const fn with_target(self, target: usize) -> Self {
1734        match self {
1735            Self::Epsilon { .. } => Self::Epsilon { target },
1736            Self::Atom { label, .. } => Self::Atom { target, label },
1737            Self::Range { start, stop, .. } => Self::Range {
1738                target,
1739                start,
1740                stop,
1741            },
1742            Self::Set { set, .. } => Self::Set { target, set },
1743            Self::NotSet { set, .. } => Self::NotSet { target, set },
1744            Self::Wildcard { .. } => Self::Wildcard { target },
1745            Self::Rule {
1746                rule_index,
1747                follow_state,
1748                precedence,
1749                ..
1750            } => Self::Rule {
1751                target,
1752                rule_index,
1753                follow_state,
1754                precedence,
1755            },
1756            Self::Predicate {
1757                rule_index,
1758                pred_index,
1759                context_dependent,
1760                ..
1761            } => Self::Predicate {
1762                target,
1763                rule_index,
1764                pred_index,
1765                context_dependent,
1766            },
1767            Self::Action {
1768                rule_index,
1769                action_index,
1770                context_dependent,
1771                ..
1772            } => Self::Action {
1773                target,
1774                rule_index,
1775                action_index,
1776                context_dependent,
1777            },
1778            Self::Precedence { precedence, .. } => Self::Precedence { target, precedence },
1779        }
1780    }
1781}
1782
1783#[derive(Clone, Copy, Debug, Eq, PartialEq)]
1784struct ParserAtnLayout {
1785    format_version: u32,
1786    max_token_type: i32,
1787    state_count: usize,
1788    transition_count: usize,
1789    set_words: usize,
1790    states: Section,
1791    transitions: Section,
1792    sets: Section,
1793    intervals: Section,
1794    token_bits: Section,
1795    decisions: Section,
1796    rule_starts: Section,
1797    rule_stops: Section,
1798}
1799
1800#[derive(Clone, Copy, Debug, Eq, PartialEq)]
1801struct Section {
1802    offset: usize,
1803    len: usize,
1804}
1805
1806#[derive(Clone, Copy, Debug)]
1807struct EncodedLayout {
1808    states: Section,
1809    transitions: Section,
1810    sets: Section,
1811    intervals: Section,
1812    token_bits: Section,
1813    decisions: Section,
1814    rule_starts: Section,
1815    rule_stops: Section,
1816    total_len: usize,
1817}
1818
1819impl EncodedLayout {
1820    fn new(builder: &ParserAtnBuilder) -> Result<Self, ParserAtnError> {
1821        let mut cursor = HEADER_WORDS;
1822        let states = next_section(&mut cursor, builder.states.len(), STATE_WORDS, "states")?;
1823        let transitions = next_section(
1824            &mut cursor,
1825            builder.transitions.len(),
1826            TRANSITION_WORDS,
1827            "transitions",
1828        )?;
1829        let sets = next_section(
1830            &mut cursor,
1831            builder.interval_sets.len(),
1832            SET_WORDS,
1833            "interval sets",
1834        )?;
1835        let intervals = next_section(
1836            &mut cursor,
1837            builder.interval_ranges.len(),
1838            2,
1839            "interval ranges",
1840        )?;
1841        let token_bits = next_section(
1842            &mut cursor,
1843            builder.token_bit_words.len(),
1844            PACKED_U64_WORDS,
1845            "token-set bits",
1846        )?;
1847        let decisions = next_section(&mut cursor, builder.decisions.len(), 1, "decisions")?;
1848        let rule_starts = next_section(&mut cursor, builder.rule_starts.len(), 1, "rule starts")?;
1849        let rule_stops = next_section(&mut cursor, builder.rule_stops.len(), 1, "rule stops")?;
1850        compact_id("packed parser ATN word", cursor)?;
1851        Ok(Self {
1852            states,
1853            transitions,
1854            sets,
1855            intervals,
1856            token_bits,
1857            decisions,
1858            rule_starts,
1859            rule_stops,
1860            total_len: cursor,
1861        })
1862    }
1863}
1864
1865#[derive(Clone, Debug)]
1866struct StateBuild {
1867    kind: AtnStateKind,
1868    rule_index: u32,
1869    flags: u32,
1870    end_state: u32,
1871    loop_back_state: u32,
1872}
1873
1874#[derive(Clone, Debug)]
1875struct TokenSetBuild {
1876    interval_start: u32,
1877    interval_len: u32,
1878    kind: ParserTokenSetKind,
1879    bit_start: u32,
1880    bit_len: u32,
1881}
1882
1883#[derive(Debug)]
1884struct PreparedTokenSet {
1885    kind: ParserTokenSetKind,
1886    words: Vec<u64>,
1887}
1888
1889#[derive(Clone, Debug)]
1890struct TransitionBuild {
1891    source: AtnStateId,
1892    kind: ParserTransitionKind,
1893    target: AtnStateId,
1894    arg0: u32,
1895    arg1: u32,
1896    arg2: u32,
1897}
1898
1899impl TransitionBuild {
1900    const fn spec(&self) -> ParserTransitionSpec {
1901        let target = self.target.index();
1902        match self.kind {
1903            ParserTransitionKind::Epsilon => ParserTransitionSpec::Epsilon { target },
1904            ParserTransitionKind::Atom => ParserTransitionSpec::Atom {
1905                target,
1906                label: unpack_i32(self.arg0),
1907            },
1908            ParserTransitionKind::Range => ParserTransitionSpec::Range {
1909                target,
1910                start: unpack_i32(self.arg0),
1911                stop: unpack_i32(self.arg1),
1912            },
1913            ParserTransitionKind::Set => ParserTransitionSpec::Set {
1914                target,
1915                set: ParserIntervalSetId(self.arg0),
1916            },
1917            ParserTransitionKind::NotSet => ParserTransitionSpec::NotSet {
1918                target,
1919                set: ParserIntervalSetId(self.arg0),
1920            },
1921            ParserTransitionKind::Wildcard => ParserTransitionSpec::Wildcard { target },
1922            ParserTransitionKind::Rule => ParserTransitionSpec::Rule {
1923                target,
1924                rule_index: self.arg0 as usize,
1925                follow_state: self.arg1 as usize,
1926                precedence: unpack_i32(self.arg2),
1927            },
1928            ParserTransitionKind::Predicate => ParserTransitionSpec::Predicate {
1929                target,
1930                rule_index: self.arg0 as usize,
1931                pred_index: self.arg1 as usize,
1932                context_dependent: self.arg2 != 0,
1933            },
1934            ParserTransitionKind::Action => ParserTransitionSpec::Action {
1935                target,
1936                rule_index: self.arg0 as usize,
1937                action_index: unpack_index(self.arg1),
1938                context_dependent: self.arg2 != 0,
1939            },
1940            ParserTransitionKind::Precedence => ParserTransitionSpec::Precedence {
1941                target,
1942                precedence: unpack_i32(self.arg0),
1943            },
1944        }
1945    }
1946}
1947
1948impl ParserTransitionKind {
1949    const fn is_epsilon(self) -> bool {
1950        matches!(
1951            self,
1952            Self::Epsilon | Self::Rule | Self::Predicate | Self::Action | Self::Precedence
1953        )
1954    }
1955
1956    const fn is_consuming(self) -> bool {
1957        matches!(
1958            self,
1959            Self::Atom | Self::Range | Self::Set | Self::NotSet | Self::Wildcard
1960        )
1961    }
1962
1963    const fn is_semantic(self) -> bool {
1964        matches!(self, Self::Predicate | Self::Action | Self::Precedence)
1965    }
1966}
1967
1968fn validate_packed(words: &[u32]) -> Result<ParserAtnLayout, ParserAtnError> {
1969    validate_header(words)?;
1970    let layout = read_layout(words)?;
1971    validate_sections(words, layout)?;
1972    validate_states(words, layout)?;
1973    validate_transitions(words, layout)?;
1974    validate_state_flags(words, layout)?;
1975    validate_sets(words, layout)?;
1976    validate_side_tables(words, layout)?;
1977    Ok(layout)
1978}
1979
1980fn validate_header(words: &[u32]) -> Result<(), ParserAtnError> {
1981    if words.len() < LEGACY_HEADER_WORDS {
1982        return Err(ParserAtnError::InvalidData(format!(
1983            "header has {} words; expected at least {LEGACY_HEADER_WORDS}",
1984            words.len()
1985        )));
1986    }
1987    if words[HEADER_MAGIC] != PARSER_ATN_MAGIC {
1988        return Err(ParserAtnError::InvalidData(format!(
1989            "magic 0x{:08x}; expected 0x{PARSER_ATN_MAGIC:08x}",
1990            words[HEADER_MAGIC]
1991        )));
1992    }
1993    let version = words[HEADER_VERSION];
1994    if !(PARSER_ATN_MIN_FORMAT_VERSION..=PARSER_ATN_MAX_FORMAT_VERSION).contains(&version) {
1995        return Err(ParserAtnError::UnsupportedVersion {
1996            found: version,
1997            minimum: PARSER_ATN_MIN_FORMAT_VERSION,
1998            maximum: PARSER_ATN_MAX_FORMAT_VERSION,
1999        });
2000    }
2001    let header_words = if version == 1 {
2002        LEGACY_HEADER_WORDS
2003    } else {
2004        HEADER_WORDS
2005    };
2006    if words.len() < header_words {
2007        return Err(ParserAtnError::InvalidData(format!(
2008            "format {version} header has {} words; expected at least {header_words}",
2009            words.len()
2010        )));
2011    }
2012    if words[HEADER_BYTE_ORDER] != PARSER_ATN_BYTE_ORDER {
2013        return Err(ParserAtnError::InvalidData(format!(
2014            "byte-order marker 0x{:08x}; expected 0x{PARSER_ATN_BYTE_ORDER:08x}",
2015            words[HEADER_BYTE_ORDER]
2016        )));
2017    }
2018    if words[HEADER_SIZE] as usize != header_words {
2019        return Err(ParserAtnError::InvalidData(format!(
2020            "format {version} header length {}; expected {header_words}",
2021            words[HEADER_SIZE],
2022        )));
2023    }
2024    if words[HEADER_TOTAL_LEN] as usize != words.len() {
2025        return Err(ParserAtnError::InvalidData(format!(
2026            "declared total length {} does not match {} words",
2027            words[HEADER_TOTAL_LEN],
2028            words.len()
2029        )));
2030    }
2031    Ok(())
2032}
2033
2034fn read_layout(words: &[u32]) -> Result<ParserAtnLayout, ParserAtnError> {
2035    let format_version = words[HEADER_VERSION];
2036    let set_words = if format_version == 1 {
2037        LEGACY_SET_WORDS
2038    } else {
2039        SET_WORDS
2040    };
2041    let states = read_section(words, HEADER_STATES_OFFSET)?;
2042    let transitions = read_section(words, HEADER_TRANSITIONS_OFFSET)?;
2043    let sets = read_section(words, HEADER_SETS_OFFSET)?;
2044    let intervals = read_section(words, HEADER_INTERVALS_OFFSET)?;
2045    let token_bits = if format_version == 1 {
2046        Section {
2047            offset: intervals.offset + intervals.len,
2048            len: 0,
2049        }
2050    } else {
2051        read_section(words, HEADER_TOKEN_BITS_OFFSET)?
2052    };
2053    let decisions = read_section(words, HEADER_DECISIONS_OFFSET)?;
2054    let rule_starts = read_section(words, HEADER_RULE_STARTS_OFFSET)?;
2055    let rule_stops = read_section(words, HEADER_RULE_STOPS_OFFSET)?;
2056    let state_count = words[HEADER_STATE_COUNT] as usize;
2057    let transition_count = words[HEADER_TRANSITION_COUNT] as usize;
2058    expect_section_len("states", states, state_count, STATE_WORDS)?;
2059    expect_section_len(
2060        "transitions",
2061        transitions,
2062        transition_count,
2063        TRANSITION_WORDS,
2064    )?;
2065    expect_section_len(
2066        "interval sets",
2067        sets,
2068        words[HEADER_SET_COUNT] as usize,
2069        set_words,
2070    )?;
2071    expect_section_len(
2072        "intervals",
2073        intervals,
2074        words[HEADER_INTERVAL_COUNT] as usize,
2075        2,
2076    )?;
2077    if format_version != 1 {
2078        expect_section_len(
2079            "token-set bits",
2080            token_bits,
2081            words[HEADER_TOKEN_BIT_WORD_COUNT] as usize,
2082            PACKED_U64_WORDS,
2083        )?;
2084    }
2085    expect_section_len(
2086        "decisions",
2087        decisions,
2088        words[HEADER_DECISION_COUNT] as usize,
2089        1,
2090    )?;
2091    expect_section_len(
2092        "rule starts",
2093        rule_starts,
2094        words[HEADER_RULE_COUNT] as usize,
2095        1,
2096    )?;
2097    expect_section_len(
2098        "rule stops",
2099        rule_stops,
2100        words[HEADER_RULE_COUNT] as usize,
2101        1,
2102    )?;
2103    Ok(ParserAtnLayout {
2104        format_version,
2105        max_token_type: unpack_i32(words[HEADER_MAX_TOKEN_TYPE]),
2106        state_count,
2107        transition_count,
2108        set_words,
2109        states,
2110        transitions,
2111        sets,
2112        intervals,
2113        token_bits,
2114        decisions,
2115        rule_starts,
2116        rule_stops,
2117    })
2118}
2119
2120fn validate_sections(words: &[u32], layout: ParserAtnLayout) -> Result<(), ParserAtnError> {
2121    let sections = [
2122        ("states", layout.states),
2123        ("transitions", layout.transitions),
2124        ("sets", layout.sets),
2125        ("intervals", layout.intervals),
2126        ("token-set bits", layout.token_bits),
2127        ("decisions", layout.decisions),
2128        ("rule starts", layout.rule_starts),
2129        ("rule stops", layout.rule_stops),
2130    ];
2131    let mut expected_offset = if layout.format_version == 1 {
2132        LEGACY_HEADER_WORDS
2133    } else {
2134        HEADER_WORDS
2135    };
2136    for (name, section) in sections {
2137        if section.offset != expected_offset {
2138            return Err(ParserAtnError::InvalidData(format!(
2139                "{name} section starts at {}, expected {expected_offset}",
2140                section.offset
2141            )));
2142        }
2143        expected_offset = section_end(section, words.len(), name)?;
2144    }
2145    if expected_offset != words.len() {
2146        return Err(ParserAtnError::InvalidData(format!(
2147            "sections end at {expected_offset}, stream ends at {}",
2148            words.len()
2149        )));
2150    }
2151    Ok(())
2152}
2153
2154fn validate_states(words: &[u32], layout: ParserAtnLayout) -> Result<(), ParserAtnError> {
2155    let mut transition_cursor = 0;
2156    for state in 0..layout.state_count {
2157        let base = layout.states.offset + state * STATE_WORDS;
2158        decode_state_kind(words[base])?;
2159        let flags = words[base + 2];
2160        if flags & !STATE_FLAGS != 0 {
2161            return Err(ParserAtnError::InvalidData(format!(
2162                "state {state} has unknown flags 0x{:x}",
2163                flags & !STATE_FLAGS
2164            )));
2165        }
2166        validate_optional_index(words[base + 1], layout.rule_starts.len, "state rule index")?;
2167        let transition_start = words[base + 3] as usize;
2168        if transition_start != transition_cursor {
2169            return Err(ParserAtnError::InvalidData(format!(
2170                "state {state} transition range starts at {transition_start}, expected {transition_cursor}"
2171            )));
2172        }
2173        validate_range(
2174            words[base + 3],
2175            words[base + 4],
2176            layout.transition_count,
2177            "state transition",
2178        )?;
2179        transition_cursor += words[base + 4] as usize;
2180        validate_optional_index(words[base + 5], layout.state_count, "block end state")?;
2181        validate_optional_index(words[base + 6], layout.state_count, "loop back state")?;
2182    }
2183    if transition_cursor != layout.transition_count {
2184        return Err(ParserAtnError::InvalidData(format!(
2185            "state transition ranges cover {transition_cursor} transitions; expected {}",
2186            layout.transition_count
2187        )));
2188    }
2189    Ok(())
2190}
2191
2192fn validate_transitions(words: &[u32], layout: ParserAtnLayout) -> Result<(), ParserAtnError> {
2193    for transition in 0..layout.transition_count {
2194        let base = layout.transitions.offset + transition * TRANSITION_WORDS;
2195        let kind = decode_transition_kind(words[base])?;
2196        validate_index(words[base + 1], layout.state_count, "transition target")?;
2197        match kind {
2198            ParserTransitionKind::Range => {
2199                let start = unpack_i32(words[base + 2]);
2200                let stop = unpack_i32(words[base + 3]);
2201                if start > stop {
2202                    return Err(ParserAtnError::InvalidData(format!(
2203                        "transition {transition} range starts at {start} after stop {stop}"
2204                    )));
2205                }
2206            }
2207            ParserTransitionKind::Set | ParserTransitionKind::NotSet => {
2208                validate_index(
2209                    words[base + 2],
2210                    layout.sets.len / layout.set_words,
2211                    "interval set",
2212                )?;
2213            }
2214            ParserTransitionKind::Rule => {
2215                validate_index(words[base + 2], layout.rule_starts.len, "rule index")?;
2216                validate_index(words[base + 3], layout.state_count, "rule follow state")?;
2217            }
2218            ParserTransitionKind::Predicate => {
2219                validate_index(words[base + 2], layout.rule_starts.len, "predicate rule")?;
2220                validate_bool(words[base + 4], "predicate context-dependent flag")?;
2221            }
2222            ParserTransitionKind::Action => {
2223                validate_index(words[base + 2], layout.rule_starts.len, "action rule")?;
2224                validate_bool(words[base + 4], "action context-dependent flag")?;
2225            }
2226            ParserTransitionKind::Epsilon
2227            | ParserTransitionKind::Atom
2228            | ParserTransitionKind::Wildcard
2229            | ParserTransitionKind::Precedence => {}
2230        }
2231    }
2232    Ok(())
2233}
2234
2235fn validate_state_flags(words: &[u32], layout: ParserAtnLayout) -> Result<(), ParserAtnError> {
2236    for state in 0..layout.state_count {
2237        let base = layout.states.offset + state * STATE_WORDS;
2238        let kind = decode_state_kind(words[base])?;
2239        let start = words[base + 3] as usize;
2240        let len = words[base + 4] as usize;
2241        let mut all_epsilon = len != 0;
2242        let mut has_consuming = false;
2243        let mut has_semantic = false;
2244        for transition in start..start + len {
2245            let base = layout.transitions.offset + transition * TRANSITION_WORDS;
2246            let kind = decode_transition_kind(words[base])
2247                .expect("packed parser transition kind was already validated");
2248            all_epsilon &= kind.is_epsilon();
2249            has_consuming |= kind.is_consuming();
2250            has_semantic |= kind.is_semantic();
2251        }
2252        let mut expected = u32::from(kind == AtnStateKind::RuleStop) * FLAG_RULE_STOP;
2253        expected |= u32::from(all_epsilon) * FLAG_EPSILON_ONLY;
2254        expected |= u32::from(has_consuming) * FLAG_HAS_CONSUMING;
2255        expected |= u32::from(has_semantic) * FLAG_HAS_SEMANTIC;
2256        let derived = words[base + 2]
2257            & (FLAG_EPSILON_ONLY | FLAG_RULE_STOP | FLAG_HAS_CONSUMING | FLAG_HAS_SEMANTIC);
2258        if derived != expected {
2259            return Err(ParserAtnError::InvalidData(format!(
2260                "state {state} has inconsistent precomputed flags 0x{derived:x}; expected 0x{expected:x}"
2261            )));
2262        }
2263    }
2264    Ok(())
2265}
2266
2267fn validate_sets(words: &[u32], layout: ParserAtnLayout) -> Result<(), ParserAtnError> {
2268    let set_count = layout.sets.len / layout.set_words;
2269    let mut bit_cursor = 0;
2270    for set in 0..set_count {
2271        let base = layout.sets.offset + set * layout.set_words;
2272        validate_range(
2273            words[base],
2274            words[base + 1],
2275            layout.intervals.len / 2,
2276            "interval set",
2277        )?;
2278        let start = words[base] as usize;
2279        let len = words[base + 1] as usize;
2280        let mut previous_stop: Option<i32> = None;
2281        for interval in start..start + len {
2282            let interval_base = layout.intervals.offset + interval * 2;
2283            let range_start = unpack_i32(words[interval_base]);
2284            let range_stop = unpack_i32(words[interval_base + 1]);
2285            if range_start > range_stop {
2286                return Err(ParserAtnError::InvalidData(format!(
2287                    "interval {interval} starts at {range_start} after stop {range_stop}"
2288                )));
2289            }
2290            if previous_stop.is_some_and(|stop| range_start <= stop.saturating_add(1)) {
2291                return Err(ParserAtnError::InvalidData(format!(
2292                    "interval set {set} is not sorted and coalesced"
2293                )));
2294            }
2295            previous_stop = Some(range_stop);
2296        }
2297        if layout.format_version == 1 {
2298            continue;
2299        }
2300        let kind = decode_token_set_kind(words[base + 2])?;
2301        let bit_start = words[base + 3];
2302        let bit_len = words[base + 4];
2303        if bit_start as usize != bit_cursor {
2304            return Err(ParserAtnError::InvalidData(format!(
2305                "parser token set {set} bit range starts at {bit_start}, expected {bit_cursor}"
2306            )));
2307        }
2308        validate_range(
2309            bit_start,
2310            bit_len,
2311            layout.token_bits.len / PACKED_U64_WORDS,
2312            "parser token-set bits",
2313        )?;
2314        let (expected_kind, expected_bit_len) =
2315            token_set_shape((start..start + len).map(|interval| {
2316                let interval_base = layout.intervals.offset + interval * 2;
2317                (
2318                    unpack_i32(words[interval_base]),
2319                    unpack_i32(words[interval_base + 1]),
2320                )
2321            }));
2322        if kind != expected_kind || bit_len as usize != expected_bit_len {
2323            return Err(ParserAtnError::InvalidData(format!(
2324                "parser token set {set} uses {kind:?} with {bit_len} words; \
2325                 expected {expected_kind:?} with {expected_bit_len} words"
2326            )));
2327        }
2328        for bit_word in 0..expected_bit_len {
2329            let expected = expected_token_set_word(
2330                (start..start + len).map(|interval| {
2331                    let interval_base = layout.intervals.offset + interval * 2;
2332                    (
2333                        unpack_i32(words[interval_base]),
2334                        unpack_i32(words[interval_base + 1]),
2335                    )
2336                }),
2337                bit_word,
2338            );
2339            let actual = packed_u64(words, layout.token_bits, bit_cursor + bit_word);
2340            if actual != expected {
2341                return Err(ParserAtnError::InvalidData(format!(
2342                    "parser token set {set} bit word {bit_word} is 0x{actual:016x}; \
2343                     expected 0x{expected:016x}"
2344                )));
2345            }
2346        }
2347        bit_cursor += expected_bit_len;
2348    }
2349    if layout.format_version != 1 && bit_cursor != layout.token_bits.len / PACKED_U64_WORDS {
2350        return Err(ParserAtnError::InvalidData(format!(
2351            "parser token sets cover {bit_cursor} bit words; expected {}",
2352            layout.token_bits.len / PACKED_U64_WORDS
2353        )));
2354    }
2355    Ok(())
2356}
2357
2358fn validate_side_tables(words: &[u32], layout: ParserAtnLayout) -> Result<(), ParserAtnError> {
2359    for (name, section) in [
2360        ("decision state", layout.decisions),
2361        ("rule start state", layout.rule_starts),
2362        ("rule stop state", layout.rule_stops),
2363    ] {
2364        for &state in &words[section.offset..section.offset + section.len] {
2365            validate_index(state, layout.state_count, name)?;
2366        }
2367    }
2368    Ok(())
2369}
2370
2371#[inline(always)]
2372fn decode_state_kind(value: u32) -> Result<AtnStateKind, ParserAtnError> {
2373    let kind = match value {
2374        0 => AtnStateKind::Invalid,
2375        1 => AtnStateKind::Basic,
2376        2 => AtnStateKind::RuleStart,
2377        3 => AtnStateKind::BlockStart,
2378        4 => AtnStateKind::PlusBlockStart,
2379        5 => AtnStateKind::StarBlockStart,
2380        6 => AtnStateKind::TokenStart,
2381        7 => AtnStateKind::RuleStop,
2382        8 => AtnStateKind::BlockEnd,
2383        9 => AtnStateKind::StarLoopBack,
2384        10 => AtnStateKind::StarLoopEntry,
2385        11 => AtnStateKind::PlusLoopBack,
2386        12 => AtnStateKind::LoopEnd,
2387        other => {
2388            return Err(ParserAtnError::InvalidData(format!(
2389                "parser ATN state kind {other}"
2390            )));
2391        }
2392    };
2393    Ok(kind)
2394}
2395
2396#[inline(always)]
2397fn decode_transition_kind(value: u32) -> Result<ParserTransitionKind, ParserAtnError> {
2398    let kind = match value {
2399        1 => ParserTransitionKind::Epsilon,
2400        2 => ParserTransitionKind::Range,
2401        3 => ParserTransitionKind::Rule,
2402        4 => ParserTransitionKind::Predicate,
2403        5 => ParserTransitionKind::Atom,
2404        6 => ParserTransitionKind::Action,
2405        7 => ParserTransitionKind::Set,
2406        8 => ParserTransitionKind::NotSet,
2407        9 => ParserTransitionKind::Wildcard,
2408        10 => ParserTransitionKind::Precedence,
2409        other => {
2410            return Err(ParserAtnError::InvalidData(format!(
2411                "parser ATN transition kind {other}"
2412            )));
2413        }
2414    };
2415    Ok(kind)
2416}
2417
2418fn decode_token_set_kind(value: u32) -> Result<ParserTokenSetKind, ParserAtnError> {
2419    match value {
2420        0 => Ok(ParserTokenSetKind::Intervals),
2421        1 => Ok(ParserTokenSetKind::Inline128),
2422        2 => Ok(ParserTokenSetKind::Dense),
2423        other => Err(ParserAtnError::InvalidData(format!(
2424            "parser token-set kind {other}"
2425        ))),
2426    }
2427}
2428
2429const fn state_kind_word(kind: AtnStateKind) -> u32 {
2430    match kind {
2431        AtnStateKind::Invalid => 0,
2432        AtnStateKind::Basic => 1,
2433        AtnStateKind::RuleStart => 2,
2434        AtnStateKind::BlockStart => 3,
2435        AtnStateKind::PlusBlockStart => 4,
2436        AtnStateKind::StarBlockStart => 5,
2437        AtnStateKind::TokenStart => 6,
2438        AtnStateKind::RuleStop => 7,
2439        AtnStateKind::BlockEnd => 8,
2440        AtnStateKind::StarLoopBack => 9,
2441        AtnStateKind::StarLoopEntry => 10,
2442        AtnStateKind::PlusLoopBack => 11,
2443        AtnStateKind::LoopEnd => 12,
2444    }
2445}
2446
2447fn compact_id(field: &'static str, value: usize) -> Result<u32, ParserAtnError> {
2448    u32::try_from(value).map_err(|_| ParserAtnError::Overflow { field, value })
2449}
2450
2451fn pack_optional_index(field: &'static str, value: Option<usize>) -> Result<u32, ParserAtnError> {
2452    match value {
2453        Some(value) => {
2454            let compact = compact_id(field, value)?;
2455            if compact == NO_INDEX {
2456                return Err(ParserAtnError::Overflow { field, value });
2457            }
2458            Ok(compact)
2459        }
2460        None => Ok(NO_INDEX),
2461    }
2462}
2463
2464const fn unpack_index(value: u32) -> Option<usize> {
2465    if value == NO_INDEX {
2466        None
2467    } else {
2468        Some(value as usize)
2469    }
2470}
2471
2472const fn pack_i32(value: i32) -> u32 {
2473    u32::from_le_bytes(value.to_le_bytes())
2474}
2475
2476const fn unpack_i32(value: u32) -> i32 {
2477    i32::from_le_bytes(value.to_le_bytes())
2478}
2479
2480fn normalize_ranges(ranges: impl IntoIterator<Item = (i32, i32)>) -> Vec<(i32, i32)> {
2481    let mut ranges = ranges
2482        .into_iter()
2483        .map(|(start, stop)| {
2484            if start <= stop {
2485                (start, stop)
2486            } else {
2487                (stop, start)
2488            }
2489        })
2490        .collect::<Vec<_>>();
2491    ranges.sort_unstable();
2492    let mut normalized: Vec<(i32, i32)> = Vec::with_capacity(ranges.len());
2493    for (start, stop) in ranges {
2494        if let Some((_, previous_stop)) = normalized.last_mut()
2495            && start <= previous_stop.saturating_add(1)
2496        {
2497            *previous_stop = (*previous_stop).max(stop);
2498            continue;
2499        }
2500        normalized.push((start, stop));
2501    }
2502    normalized
2503}
2504
2505/// Selects token-set storage without allocating from an unchecked maximum.
2506///
2507/// Every compatible set at or below token slot 127 uses two inline words.
2508/// Larger sets use dense words only when the payload is at most 64 KiB and
2509/// either no larger than interval storage, or at most twice that storage while
2510/// covering at least one eighth of the indexed domain. Sparse, malformed, and
2511/// very large domains retain normalized interval lookup.
2512fn token_set_shape(ranges: impl IntoIterator<Item = (i32, i32)>) -> (ParserTokenSetKind, usize) {
2513    let mut compatible = true;
2514    let mut max_slot = 0;
2515    let mut represented = 0_u64;
2516    let mut range_count = 0_usize;
2517    for (start, stop) in ranges {
2518        range_count += 1;
2519        represented = represented.saturating_add(
2520            u64::try_from(i64::from(stop) - i64::from(start) + 1).unwrap_or(u64::MAX),
2521        );
2522        if start == TOKEN_EOF && stop == TOKEN_EOF {
2523            continue;
2524        }
2525        if start < 1 {
2526            compatible = false;
2527            continue;
2528        }
2529        let stop = usize::try_from(stop).expect("positive i32 token type fits usize");
2530        max_slot = max_slot.max(stop);
2531    }
2532    if !compatible {
2533        return (ParserTokenSetKind::Intervals, 0);
2534    }
2535    if max_slot <= INLINE_TOKEN_SET_MAX_SLOT {
2536        return (ParserTokenSetKind::Inline128, INLINE_TOKEN_SET_WORDS);
2537    }
2538    let word_len = max_slot / u64::BITS as usize + 1;
2539    let Some(dense_bytes) = word_len.checked_mul(size_of::<u64>()) else {
2540        return (ParserTokenSetKind::Intervals, 0);
2541    };
2542    let interval_bytes = range_count.saturating_mul(size_of::<(i32, i32)>());
2543    let dense_enough = represented.saturating_mul(DENSE_TOKEN_SET_MIN_DENSITY_DENOMINATOR)
2544        >= u64::try_from(max_slot)
2545            .unwrap_or(u64::MAX)
2546            .saturating_add(1);
2547    let cost_effective = dense_bytes <= interval_bytes
2548        || (dense_bytes <= interval_bytes.saturating_mul(DENSE_TOKEN_SET_COST_MULTIPLIER)
2549            && dense_enough);
2550    if word_len <= MAX_DENSE_TOKEN_SET_WORDS && cost_effective {
2551        (ParserTokenSetKind::Dense, word_len)
2552    } else {
2553        (ParserTokenSetKind::Intervals, 0)
2554    }
2555}
2556
2557fn prepare_token_set(ranges: &[(i32, i32)]) -> PreparedTokenSet {
2558    let (kind, word_len) = token_set_shape(ranges.iter().copied());
2559    let mut words = vec![0; word_len];
2560    for &(start, stop) in ranges {
2561        insert_token_set_range(&mut words, start, stop);
2562    }
2563    PreparedTokenSet { kind, words }
2564}
2565
2566fn insert_token_set_range(words: &mut [u64], start: i32, stop: i32) {
2567    if words.is_empty() {
2568        return;
2569    }
2570    if start == TOKEN_EOF && stop == TOKEN_EOF {
2571        words[0] |= 1;
2572        return;
2573    }
2574    debug_assert!(start >= 1 && stop >= start);
2575    let start = usize::try_from(start).expect("positive i32 token type fits usize");
2576    let stop = usize::try_from(stop).expect("positive i32 token type fits usize");
2577    let start_word = start / u64::BITS as usize;
2578    let stop_word = stop / u64::BITS as usize;
2579    if start_word == stop_word {
2580        words[start_word] |= token_word_mask(start % u64::BITS as usize, stop % u64::BITS as usize);
2581        return;
2582    }
2583    words[start_word] |= !0_u64 << (start % u64::BITS as usize);
2584    words[(start_word + 1)..stop_word].fill(!0);
2585    words[stop_word] |= !0_u64 >> (u64::BITS as usize - 1 - stop % u64::BITS as usize);
2586}
2587
2588fn expected_token_set_word(ranges: impl IntoIterator<Item = (i32, i32)>, word_index: usize) -> u64 {
2589    let word_start = word_index * u64::BITS as usize;
2590    let word_stop = word_start + u64::BITS as usize - 1;
2591    let mut expected = 0;
2592    for (start, stop) in ranges {
2593        if start == TOKEN_EOF && stop == TOKEN_EOF {
2594            if word_index == 0 {
2595                expected |= 1;
2596            }
2597            continue;
2598        }
2599        let start = usize::try_from(start).expect("positive i32 token type fits usize");
2600        let stop = usize::try_from(stop).expect("positive i32 token type fits usize");
2601        if stop < word_start || start > word_stop {
2602            continue;
2603        }
2604        expected |= token_word_mask(
2605            start.max(word_start) - word_start,
2606            stop.min(word_stop) - word_start,
2607        );
2608    }
2609    expected
2610}
2611
2612const fn token_word_mask(start: usize, stop: usize) -> u64 {
2613    (!0_u64 << start) & (!0_u64 >> (u64::BITS as usize - 1 - stop))
2614}
2615
2616fn packed_u64(words: &[u32], section: Section, index: usize) -> u64 {
2617    let offset = section.offset + index * PACKED_U64_WORDS;
2618    u64::from(words[offset]) | (u64::from(words[offset + 1]) << u32::BITS)
2619}
2620
2621fn token_set_slot(value: i32) -> Option<usize> {
2622    if value == TOKEN_EOF {
2623        Some(0)
2624    } else if value > 0 {
2625        usize::try_from(value).ok()
2626    } else {
2627        None
2628    }
2629}
2630
2631fn next_section(
2632    cursor: &mut usize,
2633    count: usize,
2634    width: usize,
2635    name: &str,
2636) -> Result<Section, ParserAtnError> {
2637    let len = count.checked_mul(width).ok_or_else(|| {
2638        ParserAtnError::InvalidData(format!("{name} section length overflows usize"))
2639    })?;
2640    let section = Section {
2641        offset: *cursor,
2642        len,
2643    };
2644    *cursor = cursor.checked_add(len).ok_or_else(|| {
2645        ParserAtnError::InvalidData(format!("{name} section end overflows usize"))
2646    })?;
2647    Ok(section)
2648}
2649
2650fn write_section(
2651    words: &mut [u32],
2652    header_offset: usize,
2653    section: Section,
2654) -> Result<(), ParserAtnError> {
2655    words[header_offset] = compact_id("parser ATN section offset", section.offset)?;
2656    words[header_offset + 1] = compact_id("parser ATN section length", section.len)?;
2657    Ok(())
2658}
2659
2660fn encode_ids(words: &mut [u32], section: Section, ids: &[AtnStateId]) {
2661    for (target, id) in words[section.offset..section.offset + section.len]
2662        .iter_mut()
2663        .zip(ids)
2664    {
2665        *target = id.raw();
2666    }
2667}
2668
2669fn read_section(words: &[u32], header_offset: usize) -> Result<Section, ParserAtnError> {
2670    let offset = words[header_offset] as usize;
2671    let len = words[header_offset + 1] as usize;
2672    section_end(Section { offset, len }, words.len(), "declared")?;
2673    Ok(Section { offset, len })
2674}
2675
2676fn section_end(section: Section, total: usize, name: &str) -> Result<usize, ParserAtnError> {
2677    let end = section.offset.checked_add(section.len).ok_or_else(|| {
2678        ParserAtnError::InvalidData(format!("{name} section offset arithmetic overflow"))
2679    })?;
2680    if end > total {
2681        return Err(ParserAtnError::InvalidData(format!(
2682            "{name} section {0}..{end} exceeds stream length {total}",
2683            section.offset
2684        )));
2685    }
2686    Ok(end)
2687}
2688
2689fn expect_section_len(
2690    name: &str,
2691    section: Section,
2692    count: usize,
2693    width: usize,
2694) -> Result<(), ParserAtnError> {
2695    let expected = count.checked_mul(width).ok_or_else(|| {
2696        ParserAtnError::InvalidData(format!("{name} count/width multiplication overflow"))
2697    })?;
2698    if section.len != expected {
2699        return Err(ParserAtnError::InvalidData(format!(
2700            "{name} section has {} words; expected {expected}",
2701            section.len
2702        )));
2703    }
2704    Ok(())
2705}
2706
2707fn validate_index(value: u32, count: usize, name: &str) -> Result<(), ParserAtnError> {
2708    if value as usize >= count {
2709        return Err(ParserAtnError::InvalidData(format!(
2710            "{name} {value} outside 0..{count}"
2711        )));
2712    }
2713    Ok(())
2714}
2715
2716fn validate_optional_index(value: u32, count: usize, name: &str) -> Result<(), ParserAtnError> {
2717    if value == NO_INDEX {
2718        return Ok(());
2719    }
2720    validate_index(value, count, name)
2721}
2722
2723fn validate_bool(value: u32, name: &str) -> Result<(), ParserAtnError> {
2724    if value > 1 {
2725        return Err(ParserAtnError::InvalidData(format!(
2726            "{name} is {value}; expected 0 or 1"
2727        )));
2728    }
2729    Ok(())
2730}
2731
2732fn validate_range(start: u32, len: u32, count: usize, name: &str) -> Result<(), ParserAtnError> {
2733    let start = start as usize;
2734    let len = len as usize;
2735    let end = start
2736        .checked_add(len)
2737        .ok_or_else(|| ParserAtnError::InvalidData(format!("{name} range arithmetic overflow")))?;
2738    if end > count {
2739        return Err(ParserAtnError::InvalidData(format!(
2740            "{name} range {start}..{end} exceeds count {count}"
2741        )));
2742    }
2743    Ok(())
2744}
2745
2746#[cfg(test)]
2747mod tests {
2748    use super::*;
2749
2750    fn sample_atn() -> ParserAtn {
2751        let mut builder = ParserAtnBuilder::new(9);
2752        builder
2753            .add_state(AtnStateKind::RuleStart, Some(0))
2754            .expect("rule start");
2755        builder
2756            .add_state(AtnStateKind::RuleStop, Some(0))
2757            .expect("rule stop");
2758        builder
2759            .set_rule_to_start_state(vec![0])
2760            .expect("rule starts");
2761        builder.set_rule_to_stop_state(vec![1]).expect("rule stops");
2762        builder.add_decision_state(0).expect("decision");
2763        builder
2764            .add_transition(
2765                0,
2766                ParserTransitionSpec::Atom {
2767                    target: 1,
2768                    label: 7,
2769                },
2770            )
2771            .expect("transition");
2772        builder.finish().expect("packed parser ATN")
2773    }
2774
2775    fn token_set_atn(max_token_type: i32, ranges: &[(i32, i32)]) -> ParserAtn {
2776        let mut builder = ParserAtnBuilder::new(max_token_type);
2777        builder
2778            .add_interval_set(ranges.iter().copied())
2779            .expect("token set");
2780        builder.finish().expect("packed parser ATN")
2781    }
2782
2783    #[test]
2784    fn duplicate_transitions_reuse_the_existing_edge() {
2785        let mut builder = ParserAtnBuilder::new(1);
2786        builder
2787            .add_state(AtnStateKind::RuleStop, None)
2788            .expect("source");
2789        builder
2790            .add_state(AtnStateKind::Basic, None)
2791            .expect("target");
2792        let transition = ParserTransitionSpec::Epsilon { target: 1 };
2793
2794        let first = builder
2795            .add_transition(0, transition)
2796            .expect("first transition");
2797        let duplicate = builder
2798            .add_transition(0, transition)
2799            .expect("duplicate transition");
2800        assert_eq!(duplicate, first);
2801
2802        let atn = builder.finish().expect("packed parser ATN");
2803        assert_eq!(atn.transition_count(), 1);
2804    }
2805
2806    fn legacy_words(atn: &ParserAtn) -> Vec<u32> {
2807        let source = atn.packed_words();
2808        let source_layout = atn.layout;
2809        let set_count = source_layout.sets.len / source_layout.set_words;
2810        let mut cursor = LEGACY_HEADER_WORDS;
2811        let states = next_section(
2812            &mut cursor,
2813            source_layout.state_count,
2814            STATE_WORDS,
2815            "states",
2816        )
2817        .expect("legacy states");
2818        let transitions = next_section(
2819            &mut cursor,
2820            source_layout.transition_count,
2821            TRANSITION_WORDS,
2822            "transitions",
2823        )
2824        .expect("legacy transitions");
2825        let sets =
2826            next_section(&mut cursor, set_count, LEGACY_SET_WORDS, "sets").expect("legacy sets");
2827        let intervals = next_section(&mut cursor, source_layout.intervals.len / 2, 2, "intervals")
2828            .expect("legacy intervals");
2829        let decisions = next_section(&mut cursor, source_layout.decisions.len, 1, "decisions")
2830            .expect("legacy decisions");
2831        let rule_starts =
2832            next_section(&mut cursor, source_layout.rule_starts.len, 1, "rule starts")
2833                .expect("legacy rule starts");
2834        let rule_stops = next_section(&mut cursor, source_layout.rule_stops.len, 1, "rule stops")
2835            .expect("legacy rule stops");
2836        let mut words = vec![0; cursor];
2837        words[..=HEADER_RULE_COUNT].copy_from_slice(&source[..=HEADER_RULE_COUNT]);
2838        words[HEADER_VERSION] = 1;
2839        words[HEADER_SIZE] = LEGACY_HEADER_WORDS as u32;
2840        write_section(&mut words, HEADER_STATES_OFFSET, states).expect("states header");
2841        write_section(&mut words, HEADER_TRANSITIONS_OFFSET, transitions)
2842            .expect("transitions header");
2843        write_section(&mut words, HEADER_SETS_OFFSET, sets).expect("sets header");
2844        write_section(&mut words, HEADER_INTERVALS_OFFSET, intervals).expect("intervals header");
2845        write_section(&mut words, HEADER_DECISIONS_OFFSET, decisions).expect("decisions header");
2846        write_section(&mut words, HEADER_RULE_STARTS_OFFSET, rule_starts)
2847            .expect("rule starts header");
2848        write_section(&mut words, HEADER_RULE_STOPS_OFFSET, rule_stops).expect("rule stops header");
2849        words[HEADER_TOTAL_LEN] = cursor as u32;
2850        for (target, section) in [
2851            (states, source_layout.states),
2852            (transitions, source_layout.transitions),
2853            (intervals, source_layout.intervals),
2854            (decisions, source_layout.decisions),
2855            (rule_starts, source_layout.rule_starts),
2856            (rule_stops, source_layout.rule_stops),
2857        ] {
2858            words[target.offset..target.offset + target.len]
2859                .copy_from_slice(&source[section.offset..section.offset + section.len]);
2860        }
2861        for set in 0..set_count {
2862            let source_base = source_layout.sets.offset + set * source_layout.set_words;
2863            let target_base = sets.offset + set * LEGACY_SET_WORDS;
2864            words[target_base..target_base + LEGACY_SET_WORDS]
2865                .copy_from_slice(&source[source_base..source_base + LEGACY_SET_WORDS]);
2866        }
2867        words
2868    }
2869
2870    #[test]
2871    fn packed_views_preserve_state_and_transition_semantics() {
2872        let atn = sample_atn();
2873        let start = atn.state(0).expect("start");
2874        assert_eq!(start.kind(), AtnStateKind::RuleStart);
2875        assert_eq!(start.rule_index(), Some(0));
2876        assert!(start.has_consuming_transition());
2877        let transition = start.transitions().first().expect("transition");
2878        assert_eq!(
2879            transition.data(),
2880            ParserTransitionData::Atom {
2881                target: 1,
2882                label: 7
2883            }
2884        );
2885        assert!(transition.matches(7, 1, 9));
2886        assert!(!transition.matches(8, 1, 9));
2887        assert_eq!(atn.rule_to_stop_state().get(0), Some(1));
2888    }
2889
2890    #[test]
2891    fn static_format_is_allocation_free_and_version_checked() {
2892        let atn = sample_atn();
2893        let words = Box::leak(atn.packed_words().to_vec().into_boxed_slice());
2894        let borrowed = ParserAtn::from_static(words).expect("static packed ATN");
2895        assert!(matches!(borrowed.words, Cow::Borrowed(_)));
2896
2897        let mut wrong_version = words.to_vec();
2898        wrong_version[HEADER_VERSION] = PARSER_ATN_FORMAT_VERSION + 1;
2899        assert_eq!(
2900            ParserAtn::from_owned(wrong_version),
2901            Err(ParserAtnError::UnsupportedVersion {
2902                found: 3,
2903                minimum: 1,
2904                maximum: 2,
2905            })
2906        );
2907    }
2908
2909    #[test]
2910    fn legacy_interval_format_remains_readable() {
2911        let current = token_set_atn(200, &[(TOKEN_EOF, TOKEN_EOF), (2, 8), (150, 150)]);
2912        let legacy = ParserAtn::from_owned(legacy_words(&current)).expect("legacy packed ATN");
2913        let set = legacy.token_set(0).expect("legacy token set");
2914
2915        assert_eq!(legacy.format_version(), 1);
2916        assert_eq!(set.kind(), ParserTokenSetKind::Intervals);
2917        assert_eq!(
2918            set.ranges().collect::<Vec<_>>(),
2919            [(TOKEN_EOF, TOKEN_EOF), (2, 8), (150, 150)]
2920        );
2921        assert!(set.contains(TOKEN_EOF));
2922        assert!(set.contains(6));
2923        assert!(set.contains(150));
2924        assert!(!set.contains(149));
2925    }
2926
2927    #[test]
2928    fn adaptive_token_sets_cover_boundaries_and_safe_fallbacks() {
2929        let inline = token_set_atn(127, &[(TOKEN_EOF, TOKEN_EOF), (1, 1), (63, 64), (127, 127)]);
2930        let inline = inline.token_set(0).expect("inline set");
2931        assert_eq!(inline.kind(), ParserTokenSetKind::Inline128);
2932        for token in [TOKEN_EOF, 1, 63, 64, 127] {
2933            assert!(inline.contains(token), "missing token {token}");
2934        }
2935        for token in [-2, 0, 2, 62, 65, 126, 128] {
2936            assert!(!inline.contains(token), "unexpected token {token}");
2937        }
2938
2939        let singleton_atn = token_set_atn(127, &[(42, 42)]);
2940        let singleton = singleton_atn.token_set(0).expect("singleton set");
2941        assert_eq!(singleton.kind(), ParserTokenSetKind::Inline128);
2942        assert!(singleton.contains(42));
2943        assert!(!singleton.contains(41));
2944        assert!(!singleton.contains(43));
2945
2946        let dense_ranges = (1..=512)
2947            .step_by(2)
2948            .map(|token| (token, token))
2949            .collect::<Vec<_>>();
2950        let dense_atn = token_set_atn(512, &dense_ranges);
2951        let dense = dense_atn.token_set(0).expect("dense set");
2952        assert_eq!(dense.kind(), ParserTokenSetKind::Dense);
2953        assert!(dense.contains(511));
2954        assert!(!dense.contains(512));
2955
2956        let at_cap_max =
2957            i32::try_from(MAX_DENSE_TOKEN_SET_WORDS * u64::BITS as usize - 1).expect("test bound");
2958        assert_eq!(
2959            token_set_shape((1..=at_cap_max).step_by(2).map(|token| (token, token))),
2960            (ParserTokenSetKind::Dense, MAX_DENSE_TOKEN_SET_WORDS)
2961        );
2962        let over_cap_max = at_cap_max + 1;
2963        assert_eq!(
2964            token_set_shape(
2965                (1..=over_cap_max)
2966                    .step_by(2)
2967                    .map(|token| (token, token))
2968                    .chain([(over_cap_max, over_cap_max)])
2969            ),
2970            (ParserTokenSetKind::Intervals, 0)
2971        );
2972
2973        for ranges in [
2974            vec![(1, 1), (1_000_000, 1_000_000)],
2975            vec![(1, 1), (i32::MAX, i32::MAX)],
2976            vec![(-2, -2), (1, 4)],
2977            vec![(0, 4)],
2978        ] {
2979            let atn = token_set_atn(i32::MAX, &ranges);
2980            let set = atn.token_set(0).expect("interval set");
2981            assert_eq!(set.kind(), ParserTokenSetKind::Intervals, "{ranges:?}");
2982            assert_eq!(atn.stats().token_bitset_bytes, 0);
2983            for &(start, stop) in &ranges {
2984                assert!(set.contains(start));
2985                assert!(set.contains(stop));
2986            }
2987        }
2988
2989        let empty_atn = token_set_atn(0, &[]);
2990        let empty = empty_atn.token_set(0).expect("empty set");
2991        assert_eq!(empty.kind(), ParserTokenSetKind::Inline128);
2992        assert!(empty.is_empty());
2993        assert!(!empty.contains(TOKEN_EOF));
2994        assert!(!empty.contains(1));
2995        assert!(empty_atn.token_set(usize::MAX).is_none());
2996    }
2997
2998    #[test]
2999    fn adaptive_membership_matches_randomized_normalized_intervals() {
3000        let mut random = 0x9e37_79b9_7f4a_7c15_u64;
3001        for case in 0..256 {
3002            let range_count = (next_random(&mut random) % 24) as usize;
3003            let mut ranges = Vec::with_capacity(range_count);
3004            for _ in 0..range_count {
3005                let start = (next_random(&mut random) % 2_100) as i32 - 4;
3006                let width = (next_random(&mut random) % 24) as i32;
3007                ranges.push((start, start.saturating_add(width)));
3008            }
3009            if case % 17 == 0 {
3010                ranges.push((TOKEN_EOF, TOKEN_EOF));
3011            }
3012            if case % 29 == 0 {
3013                ranges.push((i32::MAX, i32::MAX));
3014            }
3015            let normalized = normalize_ranges(ranges);
3016            let atn = token_set_atn(i32::MAX, &normalized);
3017            let set = atn.token_set(0).expect("randomized set");
3018            for token in [TOKEN_EOF, -3, 0, 1, 63, 64, 127, 128, 2_048, i32::MAX] {
3019                let expected = normalized
3020                    .iter()
3021                    .any(|(start, stop)| (*start..=*stop).contains(&token));
3022                assert_eq!(
3023                    set.contains(token),
3024                    expected,
3025                    "case {case}, token {token}, kind {:?}, ranges {normalized:?}",
3026                    set.kind()
3027                );
3028            }
3029            for _ in 0..64 {
3030                let token = (next_random(&mut random) % 2_200) as i32 - 16;
3031                let expected = normalized
3032                    .iter()
3033                    .any(|(start, stop)| (*start..=*stop).contains(&token));
3034                assert_eq!(set.contains(token), expected, "case {case}, token {token}");
3035            }
3036        }
3037    }
3038
3039    fn next_random(state: &mut u64) -> u64 {
3040        *state ^= *state << 13;
3041        *state ^= *state >> 7;
3042        *state ^= *state << 17;
3043        *state
3044    }
3045
3046    #[cfg(target_pointer_width = "64")]
3047    #[test]
3048    fn header_encoding_rejects_values_outside_u32() {
3049        let builder = ParserAtnBuilder::new(0);
3050        let section = Section {
3051            offset: HEADER_WORDS,
3052            len: 0,
3053        };
3054        let mut layout = EncodedLayout {
3055            states: section,
3056            transitions: section,
3057            sets: section,
3058            intervals: section,
3059            token_bits: section,
3060            decisions: section,
3061            rule_starts: section,
3062            rule_stops: section,
3063            total_len: usize::MAX,
3064        };
3065        let mut words = [0; HEADER_WORDS];
3066
3067        assert_eq!(
3068            builder.encode_header(&mut words, layout),
3069            Err(ParserAtnError::Overflow {
3070                field: "packed parser ATN word",
3071                value: usize::MAX,
3072            })
3073        );
3074
3075        layout.states.offset = usize::MAX;
3076        layout.total_len = HEADER_WORDS;
3077        assert_eq!(
3078            builder.encode_header(&mut words, layout),
3079            Err(ParserAtnError::Overflow {
3080                field: "parser ATN section offset",
3081                value: usize::MAX,
3082            })
3083        );
3084    }
3085
3086    #[test]
3087    fn rejects_invalid_header_and_section_layout() {
3088        let atn = sample_atn();
3089        let cases = [
3090            (HEADER_MAGIC, 0, "magic"),
3091            (HEADER_BYTE_ORDER, 0x0403_0201, "byte-order marker"),
3092            (HEADER_SIZE, 0, "header length"),
3093            (HEADER_STATES_OFFSET, 0, "states section starts"),
3094            (HEADER_STATES_OFFSET + 1, 0, "states section has 0 words"),
3095            (HEADER_TOTAL_LEN, 0, "declared total length"),
3096        ];
3097        for (word, value, expected) in cases {
3098            let mut words = atn.packed_words().to_vec();
3099            words[word] = value;
3100            let error = ParserAtn::from_owned(words).expect_err("invalid format must fail");
3101            assert!(
3102                error.to_string().contains(expected),
3103                "{error} did not contain {expected:?}"
3104            );
3105        }
3106    }
3107
3108    #[test]
3109    fn rejects_non_contiguous_state_transition_ranges() {
3110        let atn = sample_atn();
3111        let mut words = atn.packed_words().to_vec();
3112        let second_state = atn.layout.states.offset + STATE_WORDS;
3113        words[second_state + 3] = 0;
3114        let error = ParserAtn::from_owned(words).expect_err("overlapping ranges must fail");
3115        assert!(error.to_string().contains("transition range starts"));
3116    }
3117
3118    #[test]
3119    fn interval_sets_share_one_range_pool() {
3120        let mut builder = ParserAtnBuilder::new(20);
3121        builder
3122            .add_state(AtnStateKind::RuleStart, Some(0))
3123            .expect("start");
3124        builder
3125            .add_state(AtnStateKind::RuleStop, Some(0))
3126            .expect("stop");
3127        builder
3128            .set_rule_to_start_state(vec![0])
3129            .expect("rule starts");
3130        builder.set_rule_to_stop_state(vec![1]).expect("rule stops");
3131        let set = builder
3132            .add_interval_set([(2, 4), (4, 8), (10, 10)])
3133            .expect("set");
3134        builder
3135            .add_transition(0, ParserTransitionSpec::Set { target: 1, set })
3136            .expect("set transition");
3137        let atn = builder.finish().expect("ATN");
3138        let transition = atn
3139            .state(0)
3140            .expect("start")
3141            .transitions()
3142            .first()
3143            .expect("transition");
3144        let ParserTransitionData::Set { set, .. } = transition.data() else {
3145            panic!("expected set transition");
3146        };
3147        assert_eq!(set.ranges().collect::<Vec<_>>(), vec![(2, 8), (10, 10)]);
3148        assert!(set.contains(7));
3149        assert!(!set.contains(9));
3150        assert_eq!(atn.stats().interval_ranges, 2);
3151    }
3152
3153    #[test]
3154    fn rejects_out_of_range_transition_target() {
3155        let atn = sample_atn();
3156        let mut words = atn.packed_words().to_vec();
3157        let target = atn.layout.transitions.offset + 1;
3158        words[target] = 99;
3159        assert!(matches!(
3160            ParserAtn::from_owned(words),
3161            Err(ParserAtnError::InvalidData(message))
3162                if message.contains("transition target")
3163        ));
3164    }
3165
3166    #[test]
3167    fn not_set_membership_preserves_vocabulary_bounds() {
3168        let mut builder = ParserAtnBuilder::new(5);
3169        builder
3170            .add_state(AtnStateKind::RuleStart, Some(0))
3171            .expect("start");
3172        builder
3173            .add_state(AtnStateKind::RuleStop, Some(0))
3174            .expect("stop");
3175        builder
3176            .set_rule_to_start_state(vec![0])
3177            .expect("rule starts");
3178        builder.set_rule_to_stop_state(vec![1]).expect("rule stops");
3179        let excluded = builder.add_interval_set([(2, 4)]).expect("excluded set");
3180        builder
3181            .add_transition(
3182                0,
3183                ParserTransitionSpec::NotSet {
3184                    target: 1,
3185                    set: excluded,
3186                },
3187            )
3188            .expect("not-set transition");
3189        let atn = builder.finish().expect("ATN");
3190        let transition = atn
3191            .state(0)
3192            .expect("start")
3193            .transitions()
3194            .first()
3195            .expect("transition");
3196
3197        assert!(transition.matches(1, 1, 5));
3198        assert!(!transition.matches(2, 1, 5));
3199        assert!(!transition.matches(4, 1, 5));
3200        assert!(transition.matches(5, 1, 5));
3201        assert!(!transition.matches(TOKEN_EOF, 1, 5));
3202        assert!(!transition.matches(0, 1, 5));
3203        assert!(!transition.matches(6, 1, 5));
3204    }
3205
3206    #[test]
3207    fn rejects_inconsistent_adaptive_token_set_bits() {
3208        let atn = token_set_atn(127, &[(1, 3), (63, 64), (127, 127)]);
3209        let mut words = atn.packed_words().to_vec();
3210        words[atn.layout.token_bits.offset] ^= 1 << 1;
3211        let error = ParserAtn::from_owned(words).expect_err("corrupted token bits must fail");
3212        assert!(error.to_string().contains("bit word"), "{error}");
3213
3214        let mut words = atn.packed_words().to_vec();
3215        words[atn.layout.sets.offset + 2] = 99;
3216        let error = ParserAtn::from_owned(words).expect_err("unknown token-set kind must fail");
3217        assert!(error.to_string().contains("token-set kind"), "{error}");
3218    }
3219
3220    #[cfg(feature = "perf-counters")]
3221    #[test]
3222    fn token_set_counters_report_selection_and_probes() {
3223        crate::perf::reset();
3224        let before = crate::perf::parser_token_set_snapshot();
3225        let inline_atn = token_set_atn(10, &[(1, 4)]);
3226        let dense_ranges = (1..=256)
3227            .step_by(2)
3228            .map(|token| (token, token))
3229            .collect::<Vec<_>>();
3230        let dense_atn = token_set_atn(256, &dense_ranges);
3231        let interval_atn = token_set_atn(i32::MAX, &[(1, 1), (i32::MAX, i32::MAX)]);
3232        let inline = inline_atn.token_set(0).expect("inline");
3233        let dense = dense_atn.token_set(0).expect("dense");
3234        let intervals = interval_atn.token_set(0).expect("intervals");
3235
3236        assert!(inline.contains(2));
3237        assert!(!inline.contains(9));
3238        assert!(dense.contains(255));
3239        assert!(!dense.contains(256));
3240        assert!(intervals.contains(i32::MAX));
3241        assert!(!intervals.contains(2));
3242
3243        let after = crate::perf::parser_token_set_snapshot();
3244        assert!(after[0] > before[0], "{before:?} -> {after:?}");
3245        assert!(after[1] > before[1], "{before:?} -> {after:?}");
3246        assert!(after[2] > before[2], "{before:?} -> {after:?}");
3247        assert_eq!(after[5] - before[5], 1);
3248        assert_eq!(after[6] - before[6], 1);
3249        assert_eq!(after[7] - before[7], 1);
3250        assert_eq!(after[8] - before[8], 1);
3251        assert_eq!(after[9] - before[9], 1);
3252        assert_eq!(after[10] - before[10], 1);
3253        assert_eq!(after[11] - before[11], 4);
3254        assert_eq!(after[12] - before[12], 2);
3255    }
3256
3257    #[test]
3258    fn eof_interval_is_preserved_as_signed_data() {
3259        let mut builder = ParserAtnBuilder::new(3);
3260        builder
3261            .add_state(AtnStateKind::RuleStart, Some(0))
3262            .expect("start");
3263        builder
3264            .add_state(AtnStateKind::RuleStop, Some(0))
3265            .expect("stop");
3266        builder
3267            .set_rule_to_start_state(vec![0])
3268            .expect("rule starts");
3269        builder.set_rule_to_stop_state(vec![1]).expect("rule stops");
3270        let set = builder
3271            .add_interval_set([(TOKEN_EOF, TOKEN_EOF)])
3272            .expect("set");
3273        builder
3274            .add_transition(0, ParserTransitionSpec::Set { target: 1, set })
3275            .expect("transition");
3276        let atn = builder.finish().expect("ATN");
3277        let transition = atn
3278            .state(0)
3279            .expect("start")
3280            .transitions()
3281            .first()
3282            .expect("transition");
3283        assert!(transition.matches(TOKEN_EOF, 1, 3));
3284    }
3285}