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        let record = self.transition_record(source, transition)?;
1292        let id = TransitionId::try_from(self.transitions.len())?;
1293        self.transitions.push(record);
1294        Ok(id)
1295    }
1296
1297    pub fn set_rule_to_start_state(&mut self, states: Vec<usize>) -> Result<(), ParserAtnError> {
1298        self.rule_starts = self.checked_states(states, "rule start state")?;
1299        Ok(())
1300    }
1301
1302    pub fn set_rule_to_stop_state(&mut self, states: Vec<usize>) -> Result<(), ParserAtnError> {
1303        self.rule_stops = self.checked_states(states, "rule stop state")?;
1304        Ok(())
1305    }
1306
1307    pub fn add_decision_state(&mut self, state: usize) -> Result<(), ParserAtnError> {
1308        let state = self.checked_state(state, "decision state")?;
1309        self.decisions.push(state);
1310        Ok(())
1311    }
1312
1313    pub fn state_kind(&self, state: usize) -> Option<AtnStateKind> {
1314        self.states.get(state).map(|record| record.kind)
1315    }
1316
1317    pub const fn state_count(&self) -> usize {
1318        self.states.len()
1319    }
1320
1321    pub fn state_rule_index(&self, state: usize) -> Option<usize> {
1322        self.states
1323            .get(state)
1324            .and_then(|record| unpack_index(record.rule_index))
1325    }
1326
1327    pub fn rule_stop_state(&self, rule: usize) -> Option<usize> {
1328        self.rule_stops.get(rule).copied().map(AtnStateId::index)
1329    }
1330
1331    pub fn transitions_from(
1332        &self,
1333        source: usize,
1334    ) -> impl DoubleEndedIterator<Item = ParserTransitionSpec> + '_ {
1335        self.transitions
1336            .iter()
1337            .filter(move |transition| transition.source.index() == source)
1338            .map(TransitionBuild::spec)
1339    }
1340
1341    pub fn finish(mut self) -> Result<ParserAtn, ParserAtnError> {
1342        self.mark_precedence_decisions();
1343        self.transitions.sort_by_key(|transition| transition.source);
1344        let transition_ranges = self.transition_ranges()?;
1345        self.precompute_state_flags(&transition_ranges);
1346        let words = self.encode(&transition_ranges)?;
1347        ParserAtn::from_owned(words)
1348    }
1349
1350    fn state_mut(&mut self, state: usize, label: &str) -> Result<&mut StateBuild, ParserAtnError> {
1351        self.states.get_mut(state).ok_or_else(|| {
1352            ParserAtnError::InvalidData(format!("{label} {state} outside state list"))
1353        })
1354    }
1355
1356    fn checked_state(&self, state: usize, label: &str) -> Result<AtnStateId, ParserAtnError> {
1357        let id = AtnStateId::try_from(state)?;
1358        if state >= self.states.len() {
1359            return Err(ParserAtnError::InvalidData(format!(
1360                "{label} {state} outside state list"
1361            )));
1362        }
1363        Ok(id)
1364    }
1365
1366    fn checked_states(
1367        &self,
1368        states: Vec<usize>,
1369        label: &str,
1370    ) -> Result<Vec<AtnStateId>, ParserAtnError> {
1371        states
1372            .into_iter()
1373            .map(|state| self.checked_state(state, label))
1374            .collect()
1375    }
1376
1377    fn transition_record(
1378        &self,
1379        source: AtnStateId,
1380        spec: ParserTransitionSpec,
1381    ) -> Result<TransitionBuild, ParserAtnError> {
1382        let target = self.checked_state(spec.target(), "transition target")?;
1383        let (kind, arg0, arg1, arg2) = match spec {
1384            ParserTransitionSpec::Epsilon { .. } => (ParserTransitionKind::Epsilon, 0, 0, 0),
1385            ParserTransitionSpec::Atom { label, .. } => {
1386                (ParserTransitionKind::Atom, pack_i32(label), 0, 0)
1387            }
1388            ParserTransitionSpec::Range { start, stop, .. } => (
1389                ParserTransitionKind::Range,
1390                pack_i32(start),
1391                pack_i32(stop),
1392                0,
1393            ),
1394            ParserTransitionSpec::Set { set, .. } => {
1395                self.checked_set(set)?;
1396                (ParserTransitionKind::Set, set.raw(), 0, 0)
1397            }
1398            ParserTransitionSpec::NotSet { set, .. } => {
1399                self.checked_set(set)?;
1400                (ParserTransitionKind::NotSet, set.raw(), 0, 0)
1401            }
1402            ParserTransitionSpec::Wildcard { .. } => (ParserTransitionKind::Wildcard, 0, 0, 0),
1403            ParserTransitionSpec::Rule {
1404                rule_index,
1405                follow_state,
1406                precedence,
1407                ..
1408            } => (
1409                ParserTransitionKind::Rule,
1410                compact_id("rule transition rule", rule_index)?,
1411                self.checked_state(follow_state, "rule follow state")?.raw(),
1412                pack_i32(precedence),
1413            ),
1414            ParserTransitionSpec::Predicate {
1415                rule_index,
1416                pred_index,
1417                context_dependent,
1418                ..
1419            } => (
1420                ParserTransitionKind::Predicate,
1421                compact_id("predicate rule", rule_index)?,
1422                compact_id("predicate index", pred_index)?,
1423                u32::from(context_dependent),
1424            ),
1425            ParserTransitionSpec::Action {
1426                rule_index,
1427                action_index,
1428                context_dependent,
1429                ..
1430            } => (
1431                ParserTransitionKind::Action,
1432                compact_id("action rule", rule_index)?,
1433                pack_optional_index("action", action_index)?,
1434                u32::from(context_dependent),
1435            ),
1436            ParserTransitionSpec::Precedence { precedence, .. } => {
1437                (ParserTransitionKind::Precedence, pack_i32(precedence), 0, 0)
1438            }
1439        };
1440        Ok(TransitionBuild {
1441            source,
1442            kind,
1443            target,
1444            arg0,
1445            arg1,
1446            arg2,
1447        })
1448    }
1449
1450    fn checked_set(&self, set: ParserIntervalSetId) -> Result<(), ParserAtnError> {
1451        if set.index() >= self.interval_sets.len() {
1452            return Err(ParserAtnError::InvalidData(format!(
1453                "interval set {} outside set list",
1454                set.index()
1455            )));
1456        }
1457        Ok(())
1458    }
1459
1460    fn transition_ranges(&self) -> Result<Vec<(u32, u32)>, ParserAtnError> {
1461        let mut ranges = vec![(0, 0); self.states.len()];
1462        let mut cursor = 0;
1463        for (state, range) in ranges.iter_mut().enumerate() {
1464            let start = cursor;
1465            while cursor < self.transitions.len()
1466                && self.transitions[cursor].source.index() == state
1467            {
1468                cursor += 1;
1469            }
1470            *range = (
1471                compact_id("state transition start", start)?,
1472                compact_id("state transition count", cursor - start)?,
1473            );
1474        }
1475        Ok(ranges)
1476    }
1477
1478    fn precompute_state_flags(&mut self, ranges: &[(u32, u32)]) {
1479        for (state, &(start, len)) in self.states.iter_mut().zip(ranges) {
1480            let transitions = &self.transitions[start as usize..start as usize + len as usize];
1481            if !transitions.is_empty()
1482                && transitions
1483                    .iter()
1484                    .all(|transition| transition.kind.is_epsilon())
1485            {
1486                state.flags |= FLAG_EPSILON_ONLY;
1487            }
1488            if transitions
1489                .iter()
1490                .any(|transition| transition.kind.is_consuming())
1491            {
1492                state.flags |= FLAG_HAS_CONSUMING;
1493            }
1494            if transitions
1495                .iter()
1496                .any(|transition| transition.kind.is_semantic())
1497            {
1498                state.flags |= FLAG_HAS_SEMANTIC;
1499            }
1500        }
1501    }
1502
1503    fn mark_precedence_decisions(&mut self) {
1504        let candidates = (0..self.states.len())
1505            .filter(|&state| self.is_precedence_decision(state))
1506            .collect::<Vec<_>>();
1507        for state in candidates {
1508            self.states[state].flags |= FLAG_PRECEDENCE_DECISION;
1509        }
1510    }
1511
1512    fn is_precedence_decision(&self, state: usize) -> bool {
1513        let record = &self.states[state];
1514        if record.kind != AtnStateKind::StarLoopEntry {
1515            return false;
1516        }
1517        let Some(rule_index) = unpack_index(record.rule_index) else {
1518            return false;
1519        };
1520        let Some(rule_start) = self.rule_starts.get(rule_index) else {
1521            return false;
1522        };
1523        if self.states[rule_start.index()].flags & FLAG_LEFT_RECURSIVE_RULE == 0 {
1524            return false;
1525        }
1526        let Some(loop_end) = self.transitions_from(state).next_back() else {
1527            return false;
1528        };
1529        let loop_end = loop_end.target();
1530        if self.state_kind(loop_end) != Some(AtnStateKind::LoopEnd) {
1531            return false;
1532        }
1533        self.transitions_from(loop_end)
1534            .next()
1535            .and_then(|transition| self.state_kind(transition.target()))
1536            == Some(AtnStateKind::RuleStop)
1537    }
1538
1539    fn encode(&self, transition_ranges: &[(u32, u32)]) -> Result<Vec<u32>, ParserAtnError> {
1540        let layout = EncodedLayout::new(self)?;
1541        let mut words = vec![0; layout.total_len];
1542        self.encode_header(&mut words, layout)?;
1543        self.encode_states(&mut words, layout.states, transition_ranges);
1544        self.encode_transitions(&mut words, layout.transitions);
1545        self.encode_sets(&mut words, layout.sets);
1546        self.encode_intervals(&mut words, layout.intervals);
1547        self.encode_token_bits(&mut words, layout.token_bits);
1548        encode_ids(&mut words, layout.decisions, &self.decisions);
1549        encode_ids(&mut words, layout.rule_starts, &self.rule_starts);
1550        encode_ids(&mut words, layout.rule_stops, &self.rule_stops);
1551        Ok(words)
1552    }
1553
1554    fn encode_header(
1555        &self,
1556        words: &mut [u32],
1557        layout: EncodedLayout,
1558    ) -> Result<(), ParserAtnError> {
1559        words[HEADER_MAGIC] = PARSER_ATN_MAGIC;
1560        words[HEADER_VERSION] = PARSER_ATN_FORMAT_VERSION;
1561        words[HEADER_BYTE_ORDER] = PARSER_ATN_BYTE_ORDER;
1562        words[HEADER_SIZE] = compact_id("parser ATN header size", HEADER_WORDS)?;
1563        words[HEADER_MAX_TOKEN_TYPE] = pack_i32(self.max_token_type);
1564        words[HEADER_STATE_COUNT] = compact_id("parser ATN state count", self.states.len())?;
1565        words[HEADER_TRANSITION_COUNT] =
1566            compact_id("parser ATN transition count", self.transitions.len())?;
1567        words[HEADER_SET_COUNT] =
1568            compact_id("parser ATN interval-set count", self.interval_sets.len())?;
1569        words[HEADER_INTERVAL_COUNT] =
1570            compact_id("parser ATN interval count", self.interval_ranges.len())?;
1571        words[HEADER_DECISION_COUNT] =
1572            compact_id("parser ATN decision count", self.decisions.len())?;
1573        words[HEADER_RULE_COUNT] = compact_id("parser ATN rule count", self.rule_starts.len())?;
1574        write_section(words, HEADER_STATES_OFFSET, layout.states)?;
1575        write_section(words, HEADER_TRANSITIONS_OFFSET, layout.transitions)?;
1576        write_section(words, HEADER_SETS_OFFSET, layout.sets)?;
1577        write_section(words, HEADER_INTERVALS_OFFSET, layout.intervals)?;
1578        words[HEADER_TOKEN_BIT_WORD_COUNT] = compact_id(
1579            "parser token-set bit word count",
1580            self.token_bit_words.len(),
1581        )?;
1582        write_section(words, HEADER_TOKEN_BITS_OFFSET, layout.token_bits)?;
1583        write_section(words, HEADER_DECISIONS_OFFSET, layout.decisions)?;
1584        write_section(words, HEADER_RULE_STARTS_OFFSET, layout.rule_starts)?;
1585        write_section(words, HEADER_RULE_STOPS_OFFSET, layout.rule_stops)?;
1586        words[HEADER_TOTAL_LEN] = compact_id("packed parser ATN word", layout.total_len)?;
1587        Ok(())
1588    }
1589
1590    fn encode_states(&self, words: &mut [u32], section: Section, transition_ranges: &[(u32, u32)]) {
1591        for (index, (state, &(start, len))) in self.states.iter().zip(transition_ranges).enumerate()
1592        {
1593            let base = section.offset + index * STATE_WORDS;
1594            words[base] = state_kind_word(state.kind);
1595            words[base + 1] = state.rule_index;
1596            words[base + 2] = state.flags;
1597            words[base + 3] = start;
1598            words[base + 4] = len;
1599            words[base + 5] = state.end_state;
1600            words[base + 6] = state.loop_back_state;
1601        }
1602    }
1603
1604    fn encode_transitions(&self, words: &mut [u32], section: Section) {
1605        for (index, transition) in self.transitions.iter().enumerate() {
1606            let base = section.offset + index * TRANSITION_WORDS;
1607            words[base] = transition.kind as u32;
1608            words[base + 1] = transition.target.raw();
1609            words[base + 2] = transition.arg0;
1610            words[base + 3] = transition.arg1;
1611            words[base + 4] = transition.arg2;
1612        }
1613    }
1614
1615    fn encode_sets(&self, words: &mut [u32], section: Section) {
1616        for (index, set) in self.interval_sets.iter().enumerate() {
1617            let base = section.offset + index * SET_WORDS;
1618            words[base] = set.interval_start;
1619            words[base + 1] = set.interval_len;
1620            words[base + 2] = set.kind as u32;
1621            words[base + 3] = set.bit_start;
1622            words[base + 4] = set.bit_len;
1623        }
1624    }
1625
1626    fn encode_intervals(&self, words: &mut [u32], section: Section) {
1627        for (index, &(start, stop)) in self.interval_ranges.iter().enumerate() {
1628            let base = section.offset + index * 2;
1629            words[base] = pack_i32(start);
1630            words[base + 1] = pack_i32(stop);
1631        }
1632    }
1633
1634    fn encode_token_bits(&self, words: &mut [u32], section: Section) {
1635        for (index, &bits) in self.token_bit_words.iter().enumerate() {
1636            let base = section.offset + index * PACKED_U64_WORDS;
1637            words[base] = bits as u32;
1638            words[base + 1] = (bits >> u32::BITS) as u32;
1639        }
1640    }
1641}
1642
1643/// Transient semantic transition accepted by [`ParserAtnBuilder`].
1644#[derive(Clone, Copy, Debug, Eq, PartialEq)]
1645pub enum ParserTransitionSpec {
1646    Epsilon {
1647        target: usize,
1648    },
1649    Atom {
1650        target: usize,
1651        label: i32,
1652    },
1653    Range {
1654        target: usize,
1655        start: i32,
1656        stop: i32,
1657    },
1658    Set {
1659        target: usize,
1660        set: ParserIntervalSetId,
1661    },
1662    NotSet {
1663        target: usize,
1664        set: ParserIntervalSetId,
1665    },
1666    Wildcard {
1667        target: usize,
1668    },
1669    Rule {
1670        target: usize,
1671        rule_index: usize,
1672        follow_state: usize,
1673        precedence: i32,
1674    },
1675    Predicate {
1676        target: usize,
1677        rule_index: usize,
1678        pred_index: usize,
1679        context_dependent: bool,
1680    },
1681    Action {
1682        target: usize,
1683        rule_index: usize,
1684        action_index: Option<usize>,
1685        context_dependent: bool,
1686    },
1687    Precedence {
1688        target: usize,
1689        precedence: i32,
1690    },
1691}
1692
1693impl ParserTransitionSpec {
1694    pub const fn target(self) -> usize {
1695        match self {
1696            Self::Epsilon { target }
1697            | Self::Atom { target, .. }
1698            | Self::Range { target, .. }
1699            | Self::Set { target, .. }
1700            | Self::NotSet { target, .. }
1701            | Self::Wildcard { target }
1702            | Self::Rule { target, .. }
1703            | Self::Predicate { target, .. }
1704            | Self::Action { target, .. }
1705            | Self::Precedence { target, .. } => target,
1706        }
1707    }
1708}
1709
1710#[derive(Clone, Copy, Debug, Eq, PartialEq)]
1711struct ParserAtnLayout {
1712    format_version: u32,
1713    max_token_type: i32,
1714    state_count: usize,
1715    transition_count: usize,
1716    set_words: usize,
1717    states: Section,
1718    transitions: Section,
1719    sets: Section,
1720    intervals: Section,
1721    token_bits: Section,
1722    decisions: Section,
1723    rule_starts: Section,
1724    rule_stops: Section,
1725}
1726
1727#[derive(Clone, Copy, Debug, Eq, PartialEq)]
1728struct Section {
1729    offset: usize,
1730    len: usize,
1731}
1732
1733#[derive(Clone, Copy, Debug)]
1734struct EncodedLayout {
1735    states: Section,
1736    transitions: Section,
1737    sets: Section,
1738    intervals: Section,
1739    token_bits: Section,
1740    decisions: Section,
1741    rule_starts: Section,
1742    rule_stops: Section,
1743    total_len: usize,
1744}
1745
1746impl EncodedLayout {
1747    fn new(builder: &ParserAtnBuilder) -> Result<Self, ParserAtnError> {
1748        let mut cursor = HEADER_WORDS;
1749        let states = next_section(&mut cursor, builder.states.len(), STATE_WORDS, "states")?;
1750        let transitions = next_section(
1751            &mut cursor,
1752            builder.transitions.len(),
1753            TRANSITION_WORDS,
1754            "transitions",
1755        )?;
1756        let sets = next_section(
1757            &mut cursor,
1758            builder.interval_sets.len(),
1759            SET_WORDS,
1760            "interval sets",
1761        )?;
1762        let intervals = next_section(
1763            &mut cursor,
1764            builder.interval_ranges.len(),
1765            2,
1766            "interval ranges",
1767        )?;
1768        let token_bits = next_section(
1769            &mut cursor,
1770            builder.token_bit_words.len(),
1771            PACKED_U64_WORDS,
1772            "token-set bits",
1773        )?;
1774        let decisions = next_section(&mut cursor, builder.decisions.len(), 1, "decisions")?;
1775        let rule_starts = next_section(&mut cursor, builder.rule_starts.len(), 1, "rule starts")?;
1776        let rule_stops = next_section(&mut cursor, builder.rule_stops.len(), 1, "rule stops")?;
1777        compact_id("packed parser ATN word", cursor)?;
1778        Ok(Self {
1779            states,
1780            transitions,
1781            sets,
1782            intervals,
1783            token_bits,
1784            decisions,
1785            rule_starts,
1786            rule_stops,
1787            total_len: cursor,
1788        })
1789    }
1790}
1791
1792#[derive(Clone, Debug)]
1793struct StateBuild {
1794    kind: AtnStateKind,
1795    rule_index: u32,
1796    flags: u32,
1797    end_state: u32,
1798    loop_back_state: u32,
1799}
1800
1801#[derive(Clone, Debug)]
1802struct TokenSetBuild {
1803    interval_start: u32,
1804    interval_len: u32,
1805    kind: ParserTokenSetKind,
1806    bit_start: u32,
1807    bit_len: u32,
1808}
1809
1810#[derive(Debug)]
1811struct PreparedTokenSet {
1812    kind: ParserTokenSetKind,
1813    words: Vec<u64>,
1814}
1815
1816#[derive(Clone, Debug)]
1817struct TransitionBuild {
1818    source: AtnStateId,
1819    kind: ParserTransitionKind,
1820    target: AtnStateId,
1821    arg0: u32,
1822    arg1: u32,
1823    arg2: u32,
1824}
1825
1826impl TransitionBuild {
1827    const fn spec(&self) -> ParserTransitionSpec {
1828        let target = self.target.index();
1829        match self.kind {
1830            ParserTransitionKind::Epsilon => ParserTransitionSpec::Epsilon { target },
1831            ParserTransitionKind::Atom => ParserTransitionSpec::Atom {
1832                target,
1833                label: unpack_i32(self.arg0),
1834            },
1835            ParserTransitionKind::Range => ParserTransitionSpec::Range {
1836                target,
1837                start: unpack_i32(self.arg0),
1838                stop: unpack_i32(self.arg1),
1839            },
1840            ParserTransitionKind::Set => ParserTransitionSpec::Set {
1841                target,
1842                set: ParserIntervalSetId(self.arg0),
1843            },
1844            ParserTransitionKind::NotSet => ParserTransitionSpec::NotSet {
1845                target,
1846                set: ParserIntervalSetId(self.arg0),
1847            },
1848            ParserTransitionKind::Wildcard => ParserTransitionSpec::Wildcard { target },
1849            ParserTransitionKind::Rule => ParserTransitionSpec::Rule {
1850                target,
1851                rule_index: self.arg0 as usize,
1852                follow_state: self.arg1 as usize,
1853                precedence: unpack_i32(self.arg2),
1854            },
1855            ParserTransitionKind::Predicate => ParserTransitionSpec::Predicate {
1856                target,
1857                rule_index: self.arg0 as usize,
1858                pred_index: self.arg1 as usize,
1859                context_dependent: self.arg2 != 0,
1860            },
1861            ParserTransitionKind::Action => ParserTransitionSpec::Action {
1862                target,
1863                rule_index: self.arg0 as usize,
1864                action_index: unpack_index(self.arg1),
1865                context_dependent: self.arg2 != 0,
1866            },
1867            ParserTransitionKind::Precedence => ParserTransitionSpec::Precedence {
1868                target,
1869                precedence: unpack_i32(self.arg0),
1870            },
1871        }
1872    }
1873}
1874
1875impl ParserTransitionKind {
1876    const fn is_epsilon(self) -> bool {
1877        matches!(
1878            self,
1879            Self::Epsilon | Self::Rule | Self::Predicate | Self::Action | Self::Precedence
1880        )
1881    }
1882
1883    const fn is_consuming(self) -> bool {
1884        matches!(
1885            self,
1886            Self::Atom | Self::Range | Self::Set | Self::NotSet | Self::Wildcard
1887        )
1888    }
1889
1890    const fn is_semantic(self) -> bool {
1891        matches!(self, Self::Predicate | Self::Action | Self::Precedence)
1892    }
1893}
1894
1895fn validate_packed(words: &[u32]) -> Result<ParserAtnLayout, ParserAtnError> {
1896    validate_header(words)?;
1897    let layout = read_layout(words)?;
1898    validate_sections(words, layout)?;
1899    validate_states(words, layout)?;
1900    validate_transitions(words, layout)?;
1901    validate_state_flags(words, layout)?;
1902    validate_sets(words, layout)?;
1903    validate_side_tables(words, layout)?;
1904    Ok(layout)
1905}
1906
1907fn validate_header(words: &[u32]) -> Result<(), ParserAtnError> {
1908    if words.len() < LEGACY_HEADER_WORDS {
1909        return Err(ParserAtnError::InvalidData(format!(
1910            "header has {} words; expected at least {LEGACY_HEADER_WORDS}",
1911            words.len()
1912        )));
1913    }
1914    if words[HEADER_MAGIC] != PARSER_ATN_MAGIC {
1915        return Err(ParserAtnError::InvalidData(format!(
1916            "magic 0x{:08x}; expected 0x{PARSER_ATN_MAGIC:08x}",
1917            words[HEADER_MAGIC]
1918        )));
1919    }
1920    let version = words[HEADER_VERSION];
1921    if !(PARSER_ATN_MIN_FORMAT_VERSION..=PARSER_ATN_MAX_FORMAT_VERSION).contains(&version) {
1922        return Err(ParserAtnError::UnsupportedVersion {
1923            found: version,
1924            minimum: PARSER_ATN_MIN_FORMAT_VERSION,
1925            maximum: PARSER_ATN_MAX_FORMAT_VERSION,
1926        });
1927    }
1928    let header_words = if version == 1 {
1929        LEGACY_HEADER_WORDS
1930    } else {
1931        HEADER_WORDS
1932    };
1933    if words.len() < header_words {
1934        return Err(ParserAtnError::InvalidData(format!(
1935            "format {version} header has {} words; expected at least {header_words}",
1936            words.len()
1937        )));
1938    }
1939    if words[HEADER_BYTE_ORDER] != PARSER_ATN_BYTE_ORDER {
1940        return Err(ParserAtnError::InvalidData(format!(
1941            "byte-order marker 0x{:08x}; expected 0x{PARSER_ATN_BYTE_ORDER:08x}",
1942            words[HEADER_BYTE_ORDER]
1943        )));
1944    }
1945    if words[HEADER_SIZE] as usize != header_words {
1946        return Err(ParserAtnError::InvalidData(format!(
1947            "format {version} header length {}; expected {header_words}",
1948            words[HEADER_SIZE],
1949        )));
1950    }
1951    if words[HEADER_TOTAL_LEN] as usize != words.len() {
1952        return Err(ParserAtnError::InvalidData(format!(
1953            "declared total length {} does not match {} words",
1954            words[HEADER_TOTAL_LEN],
1955            words.len()
1956        )));
1957    }
1958    Ok(())
1959}
1960
1961fn read_layout(words: &[u32]) -> Result<ParserAtnLayout, ParserAtnError> {
1962    let format_version = words[HEADER_VERSION];
1963    let set_words = if format_version == 1 {
1964        LEGACY_SET_WORDS
1965    } else {
1966        SET_WORDS
1967    };
1968    let states = read_section(words, HEADER_STATES_OFFSET)?;
1969    let transitions = read_section(words, HEADER_TRANSITIONS_OFFSET)?;
1970    let sets = read_section(words, HEADER_SETS_OFFSET)?;
1971    let intervals = read_section(words, HEADER_INTERVALS_OFFSET)?;
1972    let token_bits = if format_version == 1 {
1973        Section {
1974            offset: intervals.offset + intervals.len,
1975            len: 0,
1976        }
1977    } else {
1978        read_section(words, HEADER_TOKEN_BITS_OFFSET)?
1979    };
1980    let decisions = read_section(words, HEADER_DECISIONS_OFFSET)?;
1981    let rule_starts = read_section(words, HEADER_RULE_STARTS_OFFSET)?;
1982    let rule_stops = read_section(words, HEADER_RULE_STOPS_OFFSET)?;
1983    let state_count = words[HEADER_STATE_COUNT] as usize;
1984    let transition_count = words[HEADER_TRANSITION_COUNT] as usize;
1985    expect_section_len("states", states, state_count, STATE_WORDS)?;
1986    expect_section_len(
1987        "transitions",
1988        transitions,
1989        transition_count,
1990        TRANSITION_WORDS,
1991    )?;
1992    expect_section_len(
1993        "interval sets",
1994        sets,
1995        words[HEADER_SET_COUNT] as usize,
1996        set_words,
1997    )?;
1998    expect_section_len(
1999        "intervals",
2000        intervals,
2001        words[HEADER_INTERVAL_COUNT] as usize,
2002        2,
2003    )?;
2004    if format_version != 1 {
2005        expect_section_len(
2006            "token-set bits",
2007            token_bits,
2008            words[HEADER_TOKEN_BIT_WORD_COUNT] as usize,
2009            PACKED_U64_WORDS,
2010        )?;
2011    }
2012    expect_section_len(
2013        "decisions",
2014        decisions,
2015        words[HEADER_DECISION_COUNT] as usize,
2016        1,
2017    )?;
2018    expect_section_len(
2019        "rule starts",
2020        rule_starts,
2021        words[HEADER_RULE_COUNT] as usize,
2022        1,
2023    )?;
2024    expect_section_len(
2025        "rule stops",
2026        rule_stops,
2027        words[HEADER_RULE_COUNT] as usize,
2028        1,
2029    )?;
2030    Ok(ParserAtnLayout {
2031        format_version,
2032        max_token_type: unpack_i32(words[HEADER_MAX_TOKEN_TYPE]),
2033        state_count,
2034        transition_count,
2035        set_words,
2036        states,
2037        transitions,
2038        sets,
2039        intervals,
2040        token_bits,
2041        decisions,
2042        rule_starts,
2043        rule_stops,
2044    })
2045}
2046
2047fn validate_sections(words: &[u32], layout: ParserAtnLayout) -> Result<(), ParserAtnError> {
2048    let sections = [
2049        ("states", layout.states),
2050        ("transitions", layout.transitions),
2051        ("sets", layout.sets),
2052        ("intervals", layout.intervals),
2053        ("token-set bits", layout.token_bits),
2054        ("decisions", layout.decisions),
2055        ("rule starts", layout.rule_starts),
2056        ("rule stops", layout.rule_stops),
2057    ];
2058    let mut expected_offset = if layout.format_version == 1 {
2059        LEGACY_HEADER_WORDS
2060    } else {
2061        HEADER_WORDS
2062    };
2063    for (name, section) in sections {
2064        if section.offset != expected_offset {
2065            return Err(ParserAtnError::InvalidData(format!(
2066                "{name} section starts at {}, expected {expected_offset}",
2067                section.offset
2068            )));
2069        }
2070        expected_offset = section_end(section, words.len(), name)?;
2071    }
2072    if expected_offset != words.len() {
2073        return Err(ParserAtnError::InvalidData(format!(
2074            "sections end at {expected_offset}, stream ends at {}",
2075            words.len()
2076        )));
2077    }
2078    Ok(())
2079}
2080
2081fn validate_states(words: &[u32], layout: ParserAtnLayout) -> Result<(), ParserAtnError> {
2082    let mut transition_cursor = 0;
2083    for state in 0..layout.state_count {
2084        let base = layout.states.offset + state * STATE_WORDS;
2085        decode_state_kind(words[base])?;
2086        let flags = words[base + 2];
2087        if flags & !STATE_FLAGS != 0 {
2088            return Err(ParserAtnError::InvalidData(format!(
2089                "state {state} has unknown flags 0x{:x}",
2090                flags & !STATE_FLAGS
2091            )));
2092        }
2093        validate_optional_index(words[base + 1], layout.rule_starts.len, "state rule index")?;
2094        let transition_start = words[base + 3] as usize;
2095        if transition_start != transition_cursor {
2096            return Err(ParserAtnError::InvalidData(format!(
2097                "state {state} transition range starts at {transition_start}, expected {transition_cursor}"
2098            )));
2099        }
2100        validate_range(
2101            words[base + 3],
2102            words[base + 4],
2103            layout.transition_count,
2104            "state transition",
2105        )?;
2106        transition_cursor += words[base + 4] as usize;
2107        validate_optional_index(words[base + 5], layout.state_count, "block end state")?;
2108        validate_optional_index(words[base + 6], layout.state_count, "loop back state")?;
2109    }
2110    if transition_cursor != layout.transition_count {
2111        return Err(ParserAtnError::InvalidData(format!(
2112            "state transition ranges cover {transition_cursor} transitions; expected {}",
2113            layout.transition_count
2114        )));
2115    }
2116    Ok(())
2117}
2118
2119fn validate_transitions(words: &[u32], layout: ParserAtnLayout) -> Result<(), ParserAtnError> {
2120    for transition in 0..layout.transition_count {
2121        let base = layout.transitions.offset + transition * TRANSITION_WORDS;
2122        let kind = decode_transition_kind(words[base])?;
2123        validate_index(words[base + 1], layout.state_count, "transition target")?;
2124        match kind {
2125            ParserTransitionKind::Range => {
2126                let start = unpack_i32(words[base + 2]);
2127                let stop = unpack_i32(words[base + 3]);
2128                if start > stop {
2129                    return Err(ParserAtnError::InvalidData(format!(
2130                        "transition {transition} range starts at {start} after stop {stop}"
2131                    )));
2132                }
2133            }
2134            ParserTransitionKind::Set | ParserTransitionKind::NotSet => {
2135                validate_index(
2136                    words[base + 2],
2137                    layout.sets.len / layout.set_words,
2138                    "interval set",
2139                )?;
2140            }
2141            ParserTransitionKind::Rule => {
2142                validate_index(words[base + 2], layout.rule_starts.len, "rule index")?;
2143                validate_index(words[base + 3], layout.state_count, "rule follow state")?;
2144            }
2145            ParserTransitionKind::Predicate => {
2146                validate_index(words[base + 2], layout.rule_starts.len, "predicate rule")?;
2147                validate_bool(words[base + 4], "predicate context-dependent flag")?;
2148            }
2149            ParserTransitionKind::Action => {
2150                validate_index(words[base + 2], layout.rule_starts.len, "action rule")?;
2151                validate_bool(words[base + 4], "action context-dependent flag")?;
2152            }
2153            ParserTransitionKind::Epsilon
2154            | ParserTransitionKind::Atom
2155            | ParserTransitionKind::Wildcard
2156            | ParserTransitionKind::Precedence => {}
2157        }
2158    }
2159    Ok(())
2160}
2161
2162fn validate_state_flags(words: &[u32], layout: ParserAtnLayout) -> Result<(), ParserAtnError> {
2163    for state in 0..layout.state_count {
2164        let base = layout.states.offset + state * STATE_WORDS;
2165        let kind = decode_state_kind(words[base])?;
2166        let start = words[base + 3] as usize;
2167        let len = words[base + 4] as usize;
2168        let mut all_epsilon = len != 0;
2169        let mut has_consuming = false;
2170        let mut has_semantic = false;
2171        for transition in start..start + len {
2172            let base = layout.transitions.offset + transition * TRANSITION_WORDS;
2173            let kind = decode_transition_kind(words[base])
2174                .expect("packed parser transition kind was already validated");
2175            all_epsilon &= kind.is_epsilon();
2176            has_consuming |= kind.is_consuming();
2177            has_semantic |= kind.is_semantic();
2178        }
2179        let mut expected = u32::from(kind == AtnStateKind::RuleStop) * FLAG_RULE_STOP;
2180        expected |= u32::from(all_epsilon) * FLAG_EPSILON_ONLY;
2181        expected |= u32::from(has_consuming) * FLAG_HAS_CONSUMING;
2182        expected |= u32::from(has_semantic) * FLAG_HAS_SEMANTIC;
2183        let derived = words[base + 2]
2184            & (FLAG_EPSILON_ONLY | FLAG_RULE_STOP | FLAG_HAS_CONSUMING | FLAG_HAS_SEMANTIC);
2185        if derived != expected {
2186            return Err(ParserAtnError::InvalidData(format!(
2187                "state {state} has inconsistent precomputed flags 0x{derived:x}; expected 0x{expected:x}"
2188            )));
2189        }
2190    }
2191    Ok(())
2192}
2193
2194fn validate_sets(words: &[u32], layout: ParserAtnLayout) -> Result<(), ParserAtnError> {
2195    let set_count = layout.sets.len / layout.set_words;
2196    let mut bit_cursor = 0;
2197    for set in 0..set_count {
2198        let base = layout.sets.offset + set * layout.set_words;
2199        validate_range(
2200            words[base],
2201            words[base + 1],
2202            layout.intervals.len / 2,
2203            "interval set",
2204        )?;
2205        let start = words[base] as usize;
2206        let len = words[base + 1] as usize;
2207        let mut previous_stop: Option<i32> = None;
2208        for interval in start..start + len {
2209            let interval_base = layout.intervals.offset + interval * 2;
2210            let range_start = unpack_i32(words[interval_base]);
2211            let range_stop = unpack_i32(words[interval_base + 1]);
2212            if range_start > range_stop {
2213                return Err(ParserAtnError::InvalidData(format!(
2214                    "interval {interval} starts at {range_start} after stop {range_stop}"
2215                )));
2216            }
2217            if previous_stop.is_some_and(|stop| range_start <= stop.saturating_add(1)) {
2218                return Err(ParserAtnError::InvalidData(format!(
2219                    "interval set {set} is not sorted and coalesced"
2220                )));
2221            }
2222            previous_stop = Some(range_stop);
2223        }
2224        if layout.format_version == 1 {
2225            continue;
2226        }
2227        let kind = decode_token_set_kind(words[base + 2])?;
2228        let bit_start = words[base + 3];
2229        let bit_len = words[base + 4];
2230        if bit_start as usize != bit_cursor {
2231            return Err(ParserAtnError::InvalidData(format!(
2232                "parser token set {set} bit range starts at {bit_start}, expected {bit_cursor}"
2233            )));
2234        }
2235        validate_range(
2236            bit_start,
2237            bit_len,
2238            layout.token_bits.len / PACKED_U64_WORDS,
2239            "parser token-set bits",
2240        )?;
2241        let (expected_kind, expected_bit_len) =
2242            token_set_shape((start..start + len).map(|interval| {
2243                let interval_base = layout.intervals.offset + interval * 2;
2244                (
2245                    unpack_i32(words[interval_base]),
2246                    unpack_i32(words[interval_base + 1]),
2247                )
2248            }));
2249        if kind != expected_kind || bit_len as usize != expected_bit_len {
2250            return Err(ParserAtnError::InvalidData(format!(
2251                "parser token set {set} uses {kind:?} with {bit_len} words; \
2252                 expected {expected_kind:?} with {expected_bit_len} words"
2253            )));
2254        }
2255        for bit_word in 0..expected_bit_len {
2256            let expected = expected_token_set_word(
2257                (start..start + len).map(|interval| {
2258                    let interval_base = layout.intervals.offset + interval * 2;
2259                    (
2260                        unpack_i32(words[interval_base]),
2261                        unpack_i32(words[interval_base + 1]),
2262                    )
2263                }),
2264                bit_word,
2265            );
2266            let actual = packed_u64(words, layout.token_bits, bit_cursor + bit_word);
2267            if actual != expected {
2268                return Err(ParserAtnError::InvalidData(format!(
2269                    "parser token set {set} bit word {bit_word} is 0x{actual:016x}; \
2270                     expected 0x{expected:016x}"
2271                )));
2272            }
2273        }
2274        bit_cursor += expected_bit_len;
2275    }
2276    if layout.format_version != 1 && bit_cursor != layout.token_bits.len / PACKED_U64_WORDS {
2277        return Err(ParserAtnError::InvalidData(format!(
2278            "parser token sets cover {bit_cursor} bit words; expected {}",
2279            layout.token_bits.len / PACKED_U64_WORDS
2280        )));
2281    }
2282    Ok(())
2283}
2284
2285fn validate_side_tables(words: &[u32], layout: ParserAtnLayout) -> Result<(), ParserAtnError> {
2286    for (name, section) in [
2287        ("decision state", layout.decisions),
2288        ("rule start state", layout.rule_starts),
2289        ("rule stop state", layout.rule_stops),
2290    ] {
2291        for &state in &words[section.offset..section.offset + section.len] {
2292            validate_index(state, layout.state_count, name)?;
2293        }
2294    }
2295    Ok(())
2296}
2297
2298#[inline(always)]
2299fn decode_state_kind(value: u32) -> Result<AtnStateKind, ParserAtnError> {
2300    let kind = match value {
2301        0 => AtnStateKind::Invalid,
2302        1 => AtnStateKind::Basic,
2303        2 => AtnStateKind::RuleStart,
2304        3 => AtnStateKind::BlockStart,
2305        4 => AtnStateKind::PlusBlockStart,
2306        5 => AtnStateKind::StarBlockStart,
2307        6 => AtnStateKind::TokenStart,
2308        7 => AtnStateKind::RuleStop,
2309        8 => AtnStateKind::BlockEnd,
2310        9 => AtnStateKind::StarLoopBack,
2311        10 => AtnStateKind::StarLoopEntry,
2312        11 => AtnStateKind::PlusLoopBack,
2313        12 => AtnStateKind::LoopEnd,
2314        other => {
2315            return Err(ParserAtnError::InvalidData(format!(
2316                "parser ATN state kind {other}"
2317            )));
2318        }
2319    };
2320    Ok(kind)
2321}
2322
2323#[inline(always)]
2324fn decode_transition_kind(value: u32) -> Result<ParserTransitionKind, ParserAtnError> {
2325    let kind = match value {
2326        1 => ParserTransitionKind::Epsilon,
2327        2 => ParserTransitionKind::Range,
2328        3 => ParserTransitionKind::Rule,
2329        4 => ParserTransitionKind::Predicate,
2330        5 => ParserTransitionKind::Atom,
2331        6 => ParserTransitionKind::Action,
2332        7 => ParserTransitionKind::Set,
2333        8 => ParserTransitionKind::NotSet,
2334        9 => ParserTransitionKind::Wildcard,
2335        10 => ParserTransitionKind::Precedence,
2336        other => {
2337            return Err(ParserAtnError::InvalidData(format!(
2338                "parser ATN transition kind {other}"
2339            )));
2340        }
2341    };
2342    Ok(kind)
2343}
2344
2345fn decode_token_set_kind(value: u32) -> Result<ParserTokenSetKind, ParserAtnError> {
2346    match value {
2347        0 => Ok(ParserTokenSetKind::Intervals),
2348        1 => Ok(ParserTokenSetKind::Inline128),
2349        2 => Ok(ParserTokenSetKind::Dense),
2350        other => Err(ParserAtnError::InvalidData(format!(
2351            "parser token-set kind {other}"
2352        ))),
2353    }
2354}
2355
2356const fn state_kind_word(kind: AtnStateKind) -> u32 {
2357    match kind {
2358        AtnStateKind::Invalid => 0,
2359        AtnStateKind::Basic => 1,
2360        AtnStateKind::RuleStart => 2,
2361        AtnStateKind::BlockStart => 3,
2362        AtnStateKind::PlusBlockStart => 4,
2363        AtnStateKind::StarBlockStart => 5,
2364        AtnStateKind::TokenStart => 6,
2365        AtnStateKind::RuleStop => 7,
2366        AtnStateKind::BlockEnd => 8,
2367        AtnStateKind::StarLoopBack => 9,
2368        AtnStateKind::StarLoopEntry => 10,
2369        AtnStateKind::PlusLoopBack => 11,
2370        AtnStateKind::LoopEnd => 12,
2371    }
2372}
2373
2374fn compact_id(field: &'static str, value: usize) -> Result<u32, ParserAtnError> {
2375    u32::try_from(value).map_err(|_| ParserAtnError::Overflow { field, value })
2376}
2377
2378fn pack_optional_index(field: &'static str, value: Option<usize>) -> Result<u32, ParserAtnError> {
2379    match value {
2380        Some(value) => {
2381            let compact = compact_id(field, value)?;
2382            if compact == NO_INDEX {
2383                return Err(ParserAtnError::Overflow { field, value });
2384            }
2385            Ok(compact)
2386        }
2387        None => Ok(NO_INDEX),
2388    }
2389}
2390
2391const fn unpack_index(value: u32) -> Option<usize> {
2392    if value == NO_INDEX {
2393        None
2394    } else {
2395        Some(value as usize)
2396    }
2397}
2398
2399const fn pack_i32(value: i32) -> u32 {
2400    u32::from_le_bytes(value.to_le_bytes())
2401}
2402
2403const fn unpack_i32(value: u32) -> i32 {
2404    i32::from_le_bytes(value.to_le_bytes())
2405}
2406
2407fn normalize_ranges(ranges: impl IntoIterator<Item = (i32, i32)>) -> Vec<(i32, i32)> {
2408    let mut ranges = ranges
2409        .into_iter()
2410        .map(|(start, stop)| {
2411            if start <= stop {
2412                (start, stop)
2413            } else {
2414                (stop, start)
2415            }
2416        })
2417        .collect::<Vec<_>>();
2418    ranges.sort_unstable();
2419    let mut normalized: Vec<(i32, i32)> = Vec::with_capacity(ranges.len());
2420    for (start, stop) in ranges {
2421        if let Some((_, previous_stop)) = normalized.last_mut()
2422            && start <= previous_stop.saturating_add(1)
2423        {
2424            *previous_stop = (*previous_stop).max(stop);
2425            continue;
2426        }
2427        normalized.push((start, stop));
2428    }
2429    normalized
2430}
2431
2432/// Selects token-set storage without allocating from an unchecked maximum.
2433///
2434/// Every compatible set at or below token slot 127 uses two inline words.
2435/// Larger sets use dense words only when the payload is at most 64 KiB and
2436/// either no larger than interval storage, or at most twice that storage while
2437/// covering at least one eighth of the indexed domain. Sparse, malformed, and
2438/// very large domains retain normalized interval lookup.
2439fn token_set_shape(ranges: impl IntoIterator<Item = (i32, i32)>) -> (ParserTokenSetKind, usize) {
2440    let mut compatible = true;
2441    let mut max_slot = 0;
2442    let mut represented = 0_u64;
2443    let mut range_count = 0_usize;
2444    for (start, stop) in ranges {
2445        range_count += 1;
2446        represented = represented.saturating_add(
2447            u64::try_from(i64::from(stop) - i64::from(start) + 1).unwrap_or(u64::MAX),
2448        );
2449        if start == TOKEN_EOF && stop == TOKEN_EOF {
2450            continue;
2451        }
2452        if start < 1 {
2453            compatible = false;
2454            continue;
2455        }
2456        let stop = usize::try_from(stop).expect("positive i32 token type fits usize");
2457        max_slot = max_slot.max(stop);
2458    }
2459    if !compatible {
2460        return (ParserTokenSetKind::Intervals, 0);
2461    }
2462    if max_slot <= INLINE_TOKEN_SET_MAX_SLOT {
2463        return (ParserTokenSetKind::Inline128, INLINE_TOKEN_SET_WORDS);
2464    }
2465    let word_len = max_slot / u64::BITS as usize + 1;
2466    let Some(dense_bytes) = word_len.checked_mul(size_of::<u64>()) else {
2467        return (ParserTokenSetKind::Intervals, 0);
2468    };
2469    let interval_bytes = range_count.saturating_mul(size_of::<(i32, i32)>());
2470    let dense_enough = represented.saturating_mul(DENSE_TOKEN_SET_MIN_DENSITY_DENOMINATOR)
2471        >= u64::try_from(max_slot)
2472            .unwrap_or(u64::MAX)
2473            .saturating_add(1);
2474    let cost_effective = dense_bytes <= interval_bytes
2475        || (dense_bytes <= interval_bytes.saturating_mul(DENSE_TOKEN_SET_COST_MULTIPLIER)
2476            && dense_enough);
2477    if word_len <= MAX_DENSE_TOKEN_SET_WORDS && cost_effective {
2478        (ParserTokenSetKind::Dense, word_len)
2479    } else {
2480        (ParserTokenSetKind::Intervals, 0)
2481    }
2482}
2483
2484fn prepare_token_set(ranges: &[(i32, i32)]) -> PreparedTokenSet {
2485    let (kind, word_len) = token_set_shape(ranges.iter().copied());
2486    let mut words = vec![0; word_len];
2487    for &(start, stop) in ranges {
2488        insert_token_set_range(&mut words, start, stop);
2489    }
2490    PreparedTokenSet { kind, words }
2491}
2492
2493fn insert_token_set_range(words: &mut [u64], start: i32, stop: i32) {
2494    if words.is_empty() {
2495        return;
2496    }
2497    if start == TOKEN_EOF && stop == TOKEN_EOF {
2498        words[0] |= 1;
2499        return;
2500    }
2501    debug_assert!(start >= 1 && stop >= start);
2502    let start = usize::try_from(start).expect("positive i32 token type fits usize");
2503    let stop = usize::try_from(stop).expect("positive i32 token type fits usize");
2504    let start_word = start / u64::BITS as usize;
2505    let stop_word = stop / u64::BITS as usize;
2506    if start_word == stop_word {
2507        words[start_word] |= token_word_mask(start % u64::BITS as usize, stop % u64::BITS as usize);
2508        return;
2509    }
2510    words[start_word] |= !0_u64 << (start % u64::BITS as usize);
2511    words[(start_word + 1)..stop_word].fill(!0);
2512    words[stop_word] |= !0_u64 >> (u64::BITS as usize - 1 - stop % u64::BITS as usize);
2513}
2514
2515fn expected_token_set_word(ranges: impl IntoIterator<Item = (i32, i32)>, word_index: usize) -> u64 {
2516    let word_start = word_index * u64::BITS as usize;
2517    let word_stop = word_start + u64::BITS as usize - 1;
2518    let mut expected = 0;
2519    for (start, stop) in ranges {
2520        if start == TOKEN_EOF && stop == TOKEN_EOF {
2521            if word_index == 0 {
2522                expected |= 1;
2523            }
2524            continue;
2525        }
2526        let start = usize::try_from(start).expect("positive i32 token type fits usize");
2527        let stop = usize::try_from(stop).expect("positive i32 token type fits usize");
2528        if stop < word_start || start > word_stop {
2529            continue;
2530        }
2531        expected |= token_word_mask(
2532            start.max(word_start) - word_start,
2533            stop.min(word_stop) - word_start,
2534        );
2535    }
2536    expected
2537}
2538
2539const fn token_word_mask(start: usize, stop: usize) -> u64 {
2540    (!0_u64 << start) & (!0_u64 >> (u64::BITS as usize - 1 - stop))
2541}
2542
2543fn packed_u64(words: &[u32], section: Section, index: usize) -> u64 {
2544    let offset = section.offset + index * PACKED_U64_WORDS;
2545    u64::from(words[offset]) | (u64::from(words[offset + 1]) << u32::BITS)
2546}
2547
2548fn token_set_slot(value: i32) -> Option<usize> {
2549    if value == TOKEN_EOF {
2550        Some(0)
2551    } else if value > 0 {
2552        usize::try_from(value).ok()
2553    } else {
2554        None
2555    }
2556}
2557
2558fn next_section(
2559    cursor: &mut usize,
2560    count: usize,
2561    width: usize,
2562    name: &str,
2563) -> Result<Section, ParserAtnError> {
2564    let len = count.checked_mul(width).ok_or_else(|| {
2565        ParserAtnError::InvalidData(format!("{name} section length overflows usize"))
2566    })?;
2567    let section = Section {
2568        offset: *cursor,
2569        len,
2570    };
2571    *cursor = cursor.checked_add(len).ok_or_else(|| {
2572        ParserAtnError::InvalidData(format!("{name} section end overflows usize"))
2573    })?;
2574    Ok(section)
2575}
2576
2577fn write_section(
2578    words: &mut [u32],
2579    header_offset: usize,
2580    section: Section,
2581) -> Result<(), ParserAtnError> {
2582    words[header_offset] = compact_id("parser ATN section offset", section.offset)?;
2583    words[header_offset + 1] = compact_id("parser ATN section length", section.len)?;
2584    Ok(())
2585}
2586
2587fn encode_ids(words: &mut [u32], section: Section, ids: &[AtnStateId]) {
2588    for (target, id) in words[section.offset..section.offset + section.len]
2589        .iter_mut()
2590        .zip(ids)
2591    {
2592        *target = id.raw();
2593    }
2594}
2595
2596fn read_section(words: &[u32], header_offset: usize) -> Result<Section, ParserAtnError> {
2597    let offset = words[header_offset] as usize;
2598    let len = words[header_offset + 1] as usize;
2599    section_end(Section { offset, len }, words.len(), "declared")?;
2600    Ok(Section { offset, len })
2601}
2602
2603fn section_end(section: Section, total: usize, name: &str) -> Result<usize, ParserAtnError> {
2604    let end = section.offset.checked_add(section.len).ok_or_else(|| {
2605        ParserAtnError::InvalidData(format!("{name} section offset arithmetic overflow"))
2606    })?;
2607    if end > total {
2608        return Err(ParserAtnError::InvalidData(format!(
2609            "{name} section {0}..{end} exceeds stream length {total}",
2610            section.offset
2611        )));
2612    }
2613    Ok(end)
2614}
2615
2616fn expect_section_len(
2617    name: &str,
2618    section: Section,
2619    count: usize,
2620    width: usize,
2621) -> Result<(), ParserAtnError> {
2622    let expected = count.checked_mul(width).ok_or_else(|| {
2623        ParserAtnError::InvalidData(format!("{name} count/width multiplication overflow"))
2624    })?;
2625    if section.len != expected {
2626        return Err(ParserAtnError::InvalidData(format!(
2627            "{name} section has {} words; expected {expected}",
2628            section.len
2629        )));
2630    }
2631    Ok(())
2632}
2633
2634fn validate_index(value: u32, count: usize, name: &str) -> Result<(), ParserAtnError> {
2635    if value as usize >= count {
2636        return Err(ParserAtnError::InvalidData(format!(
2637            "{name} {value} outside 0..{count}"
2638        )));
2639    }
2640    Ok(())
2641}
2642
2643fn validate_optional_index(value: u32, count: usize, name: &str) -> Result<(), ParserAtnError> {
2644    if value == NO_INDEX {
2645        return Ok(());
2646    }
2647    validate_index(value, count, name)
2648}
2649
2650fn validate_bool(value: u32, name: &str) -> Result<(), ParserAtnError> {
2651    if value > 1 {
2652        return Err(ParserAtnError::InvalidData(format!(
2653            "{name} is {value}; expected 0 or 1"
2654        )));
2655    }
2656    Ok(())
2657}
2658
2659fn validate_range(start: u32, len: u32, count: usize, name: &str) -> Result<(), ParserAtnError> {
2660    let start = start as usize;
2661    let len = len as usize;
2662    let end = start
2663        .checked_add(len)
2664        .ok_or_else(|| ParserAtnError::InvalidData(format!("{name} range arithmetic overflow")))?;
2665    if end > count {
2666        return Err(ParserAtnError::InvalidData(format!(
2667            "{name} range {start}..{end} exceeds count {count}"
2668        )));
2669    }
2670    Ok(())
2671}
2672
2673#[cfg(test)]
2674mod tests {
2675    use super::*;
2676
2677    fn sample_atn() -> ParserAtn {
2678        let mut builder = ParserAtnBuilder::new(9);
2679        builder
2680            .add_state(AtnStateKind::RuleStart, Some(0))
2681            .expect("rule start");
2682        builder
2683            .add_state(AtnStateKind::RuleStop, Some(0))
2684            .expect("rule stop");
2685        builder
2686            .set_rule_to_start_state(vec![0])
2687            .expect("rule starts");
2688        builder.set_rule_to_stop_state(vec![1]).expect("rule stops");
2689        builder.add_decision_state(0).expect("decision");
2690        builder
2691            .add_transition(
2692                0,
2693                ParserTransitionSpec::Atom {
2694                    target: 1,
2695                    label: 7,
2696                },
2697            )
2698            .expect("transition");
2699        builder.finish().expect("packed parser ATN")
2700    }
2701
2702    fn token_set_atn(max_token_type: i32, ranges: &[(i32, i32)]) -> ParserAtn {
2703        let mut builder = ParserAtnBuilder::new(max_token_type);
2704        builder
2705            .add_interval_set(ranges.iter().copied())
2706            .expect("token set");
2707        builder.finish().expect("packed parser ATN")
2708    }
2709
2710    fn legacy_words(atn: &ParserAtn) -> Vec<u32> {
2711        let source = atn.packed_words();
2712        let source_layout = atn.layout;
2713        let set_count = source_layout.sets.len / source_layout.set_words;
2714        let mut cursor = LEGACY_HEADER_WORDS;
2715        let states = next_section(
2716            &mut cursor,
2717            source_layout.state_count,
2718            STATE_WORDS,
2719            "states",
2720        )
2721        .expect("legacy states");
2722        let transitions = next_section(
2723            &mut cursor,
2724            source_layout.transition_count,
2725            TRANSITION_WORDS,
2726            "transitions",
2727        )
2728        .expect("legacy transitions");
2729        let sets =
2730            next_section(&mut cursor, set_count, LEGACY_SET_WORDS, "sets").expect("legacy sets");
2731        let intervals = next_section(&mut cursor, source_layout.intervals.len / 2, 2, "intervals")
2732            .expect("legacy intervals");
2733        let decisions = next_section(&mut cursor, source_layout.decisions.len, 1, "decisions")
2734            .expect("legacy decisions");
2735        let rule_starts =
2736            next_section(&mut cursor, source_layout.rule_starts.len, 1, "rule starts")
2737                .expect("legacy rule starts");
2738        let rule_stops = next_section(&mut cursor, source_layout.rule_stops.len, 1, "rule stops")
2739            .expect("legacy rule stops");
2740        let mut words = vec![0; cursor];
2741        words[..=HEADER_RULE_COUNT].copy_from_slice(&source[..=HEADER_RULE_COUNT]);
2742        words[HEADER_VERSION] = 1;
2743        words[HEADER_SIZE] = LEGACY_HEADER_WORDS as u32;
2744        write_section(&mut words, HEADER_STATES_OFFSET, states).expect("states header");
2745        write_section(&mut words, HEADER_TRANSITIONS_OFFSET, transitions)
2746            .expect("transitions header");
2747        write_section(&mut words, HEADER_SETS_OFFSET, sets).expect("sets header");
2748        write_section(&mut words, HEADER_INTERVALS_OFFSET, intervals).expect("intervals header");
2749        write_section(&mut words, HEADER_DECISIONS_OFFSET, decisions).expect("decisions header");
2750        write_section(&mut words, HEADER_RULE_STARTS_OFFSET, rule_starts)
2751            .expect("rule starts header");
2752        write_section(&mut words, HEADER_RULE_STOPS_OFFSET, rule_stops).expect("rule stops header");
2753        words[HEADER_TOTAL_LEN] = cursor as u32;
2754        for (target, section) in [
2755            (states, source_layout.states),
2756            (transitions, source_layout.transitions),
2757            (intervals, source_layout.intervals),
2758            (decisions, source_layout.decisions),
2759            (rule_starts, source_layout.rule_starts),
2760            (rule_stops, source_layout.rule_stops),
2761        ] {
2762            words[target.offset..target.offset + target.len]
2763                .copy_from_slice(&source[section.offset..section.offset + section.len]);
2764        }
2765        for set in 0..set_count {
2766            let source_base = source_layout.sets.offset + set * source_layout.set_words;
2767            let target_base = sets.offset + set * LEGACY_SET_WORDS;
2768            words[target_base..target_base + LEGACY_SET_WORDS]
2769                .copy_from_slice(&source[source_base..source_base + LEGACY_SET_WORDS]);
2770        }
2771        words
2772    }
2773
2774    #[test]
2775    fn packed_views_preserve_state_and_transition_semantics() {
2776        let atn = sample_atn();
2777        let start = atn.state(0).expect("start");
2778        assert_eq!(start.kind(), AtnStateKind::RuleStart);
2779        assert_eq!(start.rule_index(), Some(0));
2780        assert!(start.has_consuming_transition());
2781        let transition = start.transitions().first().expect("transition");
2782        assert_eq!(
2783            transition.data(),
2784            ParserTransitionData::Atom {
2785                target: 1,
2786                label: 7
2787            }
2788        );
2789        assert!(transition.matches(7, 1, 9));
2790        assert!(!transition.matches(8, 1, 9));
2791        assert_eq!(atn.rule_to_stop_state().get(0), Some(1));
2792    }
2793
2794    #[test]
2795    fn static_format_is_allocation_free_and_version_checked() {
2796        let atn = sample_atn();
2797        let words = Box::leak(atn.packed_words().to_vec().into_boxed_slice());
2798        let borrowed = ParserAtn::from_static(words).expect("static packed ATN");
2799        assert!(matches!(borrowed.words, Cow::Borrowed(_)));
2800
2801        let mut wrong_version = words.to_vec();
2802        wrong_version[HEADER_VERSION] = PARSER_ATN_FORMAT_VERSION + 1;
2803        assert_eq!(
2804            ParserAtn::from_owned(wrong_version),
2805            Err(ParserAtnError::UnsupportedVersion {
2806                found: 3,
2807                minimum: 1,
2808                maximum: 2,
2809            })
2810        );
2811    }
2812
2813    #[test]
2814    fn legacy_interval_format_remains_readable() {
2815        let current = token_set_atn(200, &[(TOKEN_EOF, TOKEN_EOF), (2, 8), (150, 150)]);
2816        let legacy = ParserAtn::from_owned(legacy_words(&current)).expect("legacy packed ATN");
2817        let set = legacy.token_set(0).expect("legacy token set");
2818
2819        assert_eq!(legacy.format_version(), 1);
2820        assert_eq!(set.kind(), ParserTokenSetKind::Intervals);
2821        assert_eq!(
2822            set.ranges().collect::<Vec<_>>(),
2823            [(TOKEN_EOF, TOKEN_EOF), (2, 8), (150, 150)]
2824        );
2825        assert!(set.contains(TOKEN_EOF));
2826        assert!(set.contains(6));
2827        assert!(set.contains(150));
2828        assert!(!set.contains(149));
2829    }
2830
2831    #[test]
2832    fn adaptive_token_sets_cover_boundaries_and_safe_fallbacks() {
2833        let inline = token_set_atn(127, &[(TOKEN_EOF, TOKEN_EOF), (1, 1), (63, 64), (127, 127)]);
2834        let inline = inline.token_set(0).expect("inline set");
2835        assert_eq!(inline.kind(), ParserTokenSetKind::Inline128);
2836        for token in [TOKEN_EOF, 1, 63, 64, 127] {
2837            assert!(inline.contains(token), "missing token {token}");
2838        }
2839        for token in [-2, 0, 2, 62, 65, 126, 128] {
2840            assert!(!inline.contains(token), "unexpected token {token}");
2841        }
2842
2843        let singleton_atn = token_set_atn(127, &[(42, 42)]);
2844        let singleton = singleton_atn.token_set(0).expect("singleton set");
2845        assert_eq!(singleton.kind(), ParserTokenSetKind::Inline128);
2846        assert!(singleton.contains(42));
2847        assert!(!singleton.contains(41));
2848        assert!(!singleton.contains(43));
2849
2850        let dense_ranges = (1..=512)
2851            .step_by(2)
2852            .map(|token| (token, token))
2853            .collect::<Vec<_>>();
2854        let dense_atn = token_set_atn(512, &dense_ranges);
2855        let dense = dense_atn.token_set(0).expect("dense set");
2856        assert_eq!(dense.kind(), ParserTokenSetKind::Dense);
2857        assert!(dense.contains(511));
2858        assert!(!dense.contains(512));
2859
2860        let at_cap_max =
2861            i32::try_from(MAX_DENSE_TOKEN_SET_WORDS * u64::BITS as usize - 1).expect("test bound");
2862        assert_eq!(
2863            token_set_shape((1..=at_cap_max).step_by(2).map(|token| (token, token))),
2864            (ParserTokenSetKind::Dense, MAX_DENSE_TOKEN_SET_WORDS)
2865        );
2866        let over_cap_max = at_cap_max + 1;
2867        assert_eq!(
2868            token_set_shape(
2869                (1..=over_cap_max)
2870                    .step_by(2)
2871                    .map(|token| (token, token))
2872                    .chain([(over_cap_max, over_cap_max)])
2873            ),
2874            (ParserTokenSetKind::Intervals, 0)
2875        );
2876
2877        for ranges in [
2878            vec![(1, 1), (1_000_000, 1_000_000)],
2879            vec![(1, 1), (i32::MAX, i32::MAX)],
2880            vec![(-2, -2), (1, 4)],
2881            vec![(0, 4)],
2882        ] {
2883            let atn = token_set_atn(i32::MAX, &ranges);
2884            let set = atn.token_set(0).expect("interval set");
2885            assert_eq!(set.kind(), ParserTokenSetKind::Intervals, "{ranges:?}");
2886            assert_eq!(atn.stats().token_bitset_bytes, 0);
2887            for &(start, stop) in &ranges {
2888                assert!(set.contains(start));
2889                assert!(set.contains(stop));
2890            }
2891        }
2892
2893        let empty_atn = token_set_atn(0, &[]);
2894        let empty = empty_atn.token_set(0).expect("empty set");
2895        assert_eq!(empty.kind(), ParserTokenSetKind::Inline128);
2896        assert!(empty.is_empty());
2897        assert!(!empty.contains(TOKEN_EOF));
2898        assert!(!empty.contains(1));
2899        assert!(empty_atn.token_set(usize::MAX).is_none());
2900    }
2901
2902    #[test]
2903    fn adaptive_membership_matches_randomized_normalized_intervals() {
2904        let mut random = 0x9e37_79b9_7f4a_7c15_u64;
2905        for case in 0..256 {
2906            let range_count = (next_random(&mut random) % 24) as usize;
2907            let mut ranges = Vec::with_capacity(range_count);
2908            for _ in 0..range_count {
2909                let start = (next_random(&mut random) % 2_100) as i32 - 4;
2910                let width = (next_random(&mut random) % 24) as i32;
2911                ranges.push((start, start.saturating_add(width)));
2912            }
2913            if case % 17 == 0 {
2914                ranges.push((TOKEN_EOF, TOKEN_EOF));
2915            }
2916            if case % 29 == 0 {
2917                ranges.push((i32::MAX, i32::MAX));
2918            }
2919            let normalized = normalize_ranges(ranges);
2920            let atn = token_set_atn(i32::MAX, &normalized);
2921            let set = atn.token_set(0).expect("randomized set");
2922            for token in [TOKEN_EOF, -3, 0, 1, 63, 64, 127, 128, 2_048, i32::MAX] {
2923                let expected = normalized
2924                    .iter()
2925                    .any(|(start, stop)| (*start..=*stop).contains(&token));
2926                assert_eq!(
2927                    set.contains(token),
2928                    expected,
2929                    "case {case}, token {token}, kind {:?}, ranges {normalized:?}",
2930                    set.kind()
2931                );
2932            }
2933            for _ in 0..64 {
2934                let token = (next_random(&mut random) % 2_200) as i32 - 16;
2935                let expected = normalized
2936                    .iter()
2937                    .any(|(start, stop)| (*start..=*stop).contains(&token));
2938                assert_eq!(set.contains(token), expected, "case {case}, token {token}");
2939            }
2940        }
2941    }
2942
2943    fn next_random(state: &mut u64) -> u64 {
2944        *state ^= *state << 13;
2945        *state ^= *state >> 7;
2946        *state ^= *state << 17;
2947        *state
2948    }
2949
2950    #[cfg(target_pointer_width = "64")]
2951    #[test]
2952    fn header_encoding_rejects_values_outside_u32() {
2953        let builder = ParserAtnBuilder::new(0);
2954        let section = Section {
2955            offset: HEADER_WORDS,
2956            len: 0,
2957        };
2958        let mut layout = EncodedLayout {
2959            states: section,
2960            transitions: section,
2961            sets: section,
2962            intervals: section,
2963            token_bits: section,
2964            decisions: section,
2965            rule_starts: section,
2966            rule_stops: section,
2967            total_len: usize::MAX,
2968        };
2969        let mut words = [0; HEADER_WORDS];
2970
2971        assert_eq!(
2972            builder.encode_header(&mut words, layout),
2973            Err(ParserAtnError::Overflow {
2974                field: "packed parser ATN word",
2975                value: usize::MAX,
2976            })
2977        );
2978
2979        layout.states.offset = usize::MAX;
2980        layout.total_len = HEADER_WORDS;
2981        assert_eq!(
2982            builder.encode_header(&mut words, layout),
2983            Err(ParserAtnError::Overflow {
2984                field: "parser ATN section offset",
2985                value: usize::MAX,
2986            })
2987        );
2988    }
2989
2990    #[test]
2991    fn rejects_invalid_header_and_section_layout() {
2992        let atn = sample_atn();
2993        let cases = [
2994            (HEADER_MAGIC, 0, "magic"),
2995            (HEADER_BYTE_ORDER, 0x0403_0201, "byte-order marker"),
2996            (HEADER_SIZE, 0, "header length"),
2997            (HEADER_STATES_OFFSET, 0, "states section starts"),
2998            (HEADER_STATES_OFFSET + 1, 0, "states section has 0 words"),
2999            (HEADER_TOTAL_LEN, 0, "declared total length"),
3000        ];
3001        for (word, value, expected) in cases {
3002            let mut words = atn.packed_words().to_vec();
3003            words[word] = value;
3004            let error = ParserAtn::from_owned(words).expect_err("invalid format must fail");
3005            assert!(
3006                error.to_string().contains(expected),
3007                "{error} did not contain {expected:?}"
3008            );
3009        }
3010    }
3011
3012    #[test]
3013    fn rejects_non_contiguous_state_transition_ranges() {
3014        let atn = sample_atn();
3015        let mut words = atn.packed_words().to_vec();
3016        let second_state = atn.layout.states.offset + STATE_WORDS;
3017        words[second_state + 3] = 0;
3018        let error = ParserAtn::from_owned(words).expect_err("overlapping ranges must fail");
3019        assert!(error.to_string().contains("transition range starts"));
3020    }
3021
3022    #[test]
3023    fn interval_sets_share_one_range_pool() {
3024        let mut builder = ParserAtnBuilder::new(20);
3025        builder
3026            .add_state(AtnStateKind::RuleStart, Some(0))
3027            .expect("start");
3028        builder
3029            .add_state(AtnStateKind::RuleStop, Some(0))
3030            .expect("stop");
3031        builder
3032            .set_rule_to_start_state(vec![0])
3033            .expect("rule starts");
3034        builder.set_rule_to_stop_state(vec![1]).expect("rule stops");
3035        let set = builder
3036            .add_interval_set([(2, 4), (4, 8), (10, 10)])
3037            .expect("set");
3038        builder
3039            .add_transition(0, ParserTransitionSpec::Set { target: 1, set })
3040            .expect("set transition");
3041        let atn = builder.finish().expect("ATN");
3042        let transition = atn
3043            .state(0)
3044            .expect("start")
3045            .transitions()
3046            .first()
3047            .expect("transition");
3048        let ParserTransitionData::Set { set, .. } = transition.data() else {
3049            panic!("expected set transition");
3050        };
3051        assert_eq!(set.ranges().collect::<Vec<_>>(), vec![(2, 8), (10, 10)]);
3052        assert!(set.contains(7));
3053        assert!(!set.contains(9));
3054        assert_eq!(atn.stats().interval_ranges, 2);
3055    }
3056
3057    #[test]
3058    fn rejects_out_of_range_transition_target() {
3059        let atn = sample_atn();
3060        let mut words = atn.packed_words().to_vec();
3061        let target = atn.layout.transitions.offset + 1;
3062        words[target] = 99;
3063        assert!(matches!(
3064            ParserAtn::from_owned(words),
3065            Err(ParserAtnError::InvalidData(message))
3066                if message.contains("transition target")
3067        ));
3068    }
3069
3070    #[test]
3071    fn not_set_membership_preserves_vocabulary_bounds() {
3072        let mut builder = ParserAtnBuilder::new(5);
3073        builder
3074            .add_state(AtnStateKind::RuleStart, Some(0))
3075            .expect("start");
3076        builder
3077            .add_state(AtnStateKind::RuleStop, Some(0))
3078            .expect("stop");
3079        builder
3080            .set_rule_to_start_state(vec![0])
3081            .expect("rule starts");
3082        builder.set_rule_to_stop_state(vec![1]).expect("rule stops");
3083        let excluded = builder.add_interval_set([(2, 4)]).expect("excluded set");
3084        builder
3085            .add_transition(
3086                0,
3087                ParserTransitionSpec::NotSet {
3088                    target: 1,
3089                    set: excluded,
3090                },
3091            )
3092            .expect("not-set transition");
3093        let atn = builder.finish().expect("ATN");
3094        let transition = atn
3095            .state(0)
3096            .expect("start")
3097            .transitions()
3098            .first()
3099            .expect("transition");
3100
3101        assert!(transition.matches(1, 1, 5));
3102        assert!(!transition.matches(2, 1, 5));
3103        assert!(!transition.matches(4, 1, 5));
3104        assert!(transition.matches(5, 1, 5));
3105        assert!(!transition.matches(TOKEN_EOF, 1, 5));
3106        assert!(!transition.matches(0, 1, 5));
3107        assert!(!transition.matches(6, 1, 5));
3108    }
3109
3110    #[test]
3111    fn rejects_inconsistent_adaptive_token_set_bits() {
3112        let atn = token_set_atn(127, &[(1, 3), (63, 64), (127, 127)]);
3113        let mut words = atn.packed_words().to_vec();
3114        words[atn.layout.token_bits.offset] ^= 1 << 1;
3115        let error = ParserAtn::from_owned(words).expect_err("corrupted token bits must fail");
3116        assert!(error.to_string().contains("bit word"), "{error}");
3117
3118        let mut words = atn.packed_words().to_vec();
3119        words[atn.layout.sets.offset + 2] = 99;
3120        let error = ParserAtn::from_owned(words).expect_err("unknown token-set kind must fail");
3121        assert!(error.to_string().contains("token-set kind"), "{error}");
3122    }
3123
3124    #[cfg(feature = "perf-counters")]
3125    #[test]
3126    fn token_set_counters_report_selection_and_probes() {
3127        crate::perf::reset();
3128        let before = crate::perf::parser_token_set_snapshot();
3129        let inline_atn = token_set_atn(10, &[(1, 4)]);
3130        let dense_ranges = (1..=256)
3131            .step_by(2)
3132            .map(|token| (token, token))
3133            .collect::<Vec<_>>();
3134        let dense_atn = token_set_atn(256, &dense_ranges);
3135        let interval_atn = token_set_atn(i32::MAX, &[(1, 1), (i32::MAX, i32::MAX)]);
3136        let inline = inline_atn.token_set(0).expect("inline");
3137        let dense = dense_atn.token_set(0).expect("dense");
3138        let intervals = interval_atn.token_set(0).expect("intervals");
3139
3140        assert!(inline.contains(2));
3141        assert!(!inline.contains(9));
3142        assert!(dense.contains(255));
3143        assert!(!dense.contains(256));
3144        assert!(intervals.contains(i32::MAX));
3145        assert!(!intervals.contains(2));
3146
3147        let after = crate::perf::parser_token_set_snapshot();
3148        assert!(after[0] > before[0], "{before:?} -> {after:?}");
3149        assert!(after[1] > before[1], "{before:?} -> {after:?}");
3150        assert!(after[2] > before[2], "{before:?} -> {after:?}");
3151        assert_eq!(after[5] - before[5], 1);
3152        assert_eq!(after[6] - before[6], 1);
3153        assert_eq!(after[7] - before[7], 1);
3154        assert_eq!(after[8] - before[8], 1);
3155        assert_eq!(after[9] - before[9], 1);
3156        assert_eq!(after[10] - before[10], 1);
3157        assert_eq!(after[11] - before[11], 4);
3158        assert_eq!(after[12] - before[12], 2);
3159    }
3160
3161    #[test]
3162    fn eof_interval_is_preserved_as_signed_data() {
3163        let mut builder = ParserAtnBuilder::new(3);
3164        builder
3165            .add_state(AtnStateKind::RuleStart, Some(0))
3166            .expect("start");
3167        builder
3168            .add_state(AtnStateKind::RuleStop, Some(0))
3169            .expect("stop");
3170        builder
3171            .set_rule_to_start_state(vec![0])
3172            .expect("rule starts");
3173        builder.set_rule_to_stop_state(vec![1]).expect("rule stops");
3174        let set = builder
3175            .add_interval_set([(TOKEN_EOF, TOKEN_EOF)])
3176            .expect("set");
3177        builder
3178            .add_transition(0, ParserTransitionSpec::Set { target: 1, set })
3179            .expect("transition");
3180        let atn = builder.finish().expect("ATN");
3181        let transition = atn
3182            .state(0)
3183            .expect("start")
3184            .transitions()
3185            .first()
3186            .expect("transition");
3187        assert!(transition.matches(TOKEN_EOF, 1, 3));
3188    }
3189}