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