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