Skip to main content

antlr4_runtime/atn/
parser_atn.rs

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