Skip to main content

antlr4_runtime/atn/
parser_atn.rs

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