Skip to main content

antlr4_runtime/atn/
parser_atn.rs

1//! Packed, index-addressed parser ATN storage.
2//!
3//! Parser ATNs are immutable after generation/deserialization. Keeping their
4//! states and transitions in one validated word stream avoids the allocation
5//! and pointer-chasing costs of an owned object graph while still exposing
6//! borrowing semantic views to the simulator and diagnostics.
7
8// These accessors are scalar address calculations used throughout the parser's
9// innermost transition loops. Cross-crate generated parsers need them inlined.
10#![allow(clippy::inline_always)]
11
12use std::borrow::Cow;
13use std::fmt;
14use std::iter::FusedIterator;
15
16#[cfg(test)]
17use crate::token::TOKEN_EOF;
18
19use super::AtnStateKind;
20
21const PARSER_ATN_MAGIC: u32 = 0x5041_544e;
22const PARSER_ATN_FORMAT_VERSION: u32 = 1;
23const PARSER_ATN_MIN_FORMAT_VERSION: u32 = 1;
24const PARSER_ATN_MAX_FORMAT_VERSION: u32 = 1;
25const PARSER_ATN_BYTE_ORDER: u32 = 0x0102_0304;
26
27const HEADER_WORDS: usize = 26;
28const STATE_WORDS: usize = 7;
29const TRANSITION_WORDS: usize = 5;
30const SET_WORDS: usize = 2;
31
32const NO_INDEX: u32 = u32::MAX;
33
34const FLAG_NON_GREEDY: u32 = 1 << 0;
35const FLAG_PRECEDENCE_DECISION: u32 = 1 << 1;
36const FLAG_LEFT_RECURSIVE_RULE: u32 = 1 << 2;
37const FLAG_EPSILON_ONLY: u32 = 1 << 3;
38const FLAG_RULE_STOP: u32 = 1 << 4;
39const FLAG_HAS_CONSUMING: u32 = 1 << 5;
40const FLAG_HAS_SEMANTIC: u32 = 1 << 6;
41const STATE_FLAGS: u32 = FLAG_NON_GREEDY
42    | FLAG_PRECEDENCE_DECISION
43    | FLAG_LEFT_RECURSIVE_RULE
44    | FLAG_EPSILON_ONLY
45    | FLAG_RULE_STOP
46    | FLAG_HAS_CONSUMING
47    | FLAG_HAS_SEMANTIC;
48
49const HEADER_MAGIC: usize = 0;
50const HEADER_VERSION: usize = 1;
51const HEADER_BYTE_ORDER: usize = 2;
52const HEADER_SIZE: usize = 3;
53const HEADER_MAX_TOKEN_TYPE: usize = 4;
54const HEADER_STATE_COUNT: usize = 5;
55const HEADER_TRANSITION_COUNT: usize = 6;
56const HEADER_SET_COUNT: usize = 7;
57const HEADER_INTERVAL_COUNT: usize = 8;
58const HEADER_DECISION_COUNT: usize = 9;
59const HEADER_RULE_COUNT: usize = 10;
60const HEADER_STATES_OFFSET: usize = 11;
61const HEADER_TRANSITIONS_OFFSET: usize = 13;
62const HEADER_SETS_OFFSET: usize = 15;
63const HEADER_INTERVALS_OFFSET: usize = 17;
64const HEADER_DECISIONS_OFFSET: usize = 19;
65const HEADER_RULE_STARTS_OFFSET: usize = 21;
66const HEADER_RULE_STOPS_OFFSET: usize = 23;
67const HEADER_TOTAL_LEN: usize = 25;
68
69/// Checked compact identity for one parser ATN state.
70#[repr(transparent)]
71#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
72pub struct AtnStateId(u32);
73
74impl AtnStateId {
75    pub const fn index(self) -> usize {
76        self.0 as usize
77    }
78
79    const fn raw(self) -> u32 {
80        self.0
81    }
82}
83
84impl TryFrom<usize> for AtnStateId {
85    type Error = ParserAtnError;
86
87    fn try_from(value: usize) -> Result<Self, Self::Error> {
88        compact_id("parser ATN state", value).map(Self)
89    }
90}
91
92/// Checked compact identity for one parser ATN transition.
93#[repr(transparent)]
94#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
95pub struct TransitionId(u32);
96
97impl TransitionId {
98    pub const fn index(self) -> usize {
99        self.0 as usize
100    }
101}
102
103impl TryFrom<usize> for TransitionId {
104    type Error = ParserAtnError;
105
106    fn try_from(value: usize) -> Result<Self, Self::Error> {
107        compact_id("parser ATN transition", value).map(Self)
108    }
109}
110
111/// Checked compact identity for one shared interval set.
112#[repr(transparent)]
113#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
114pub struct ParserIntervalSetId(u32);
115
116impl ParserIntervalSetId {
117    pub const fn index(self) -> usize {
118        self.0 as usize
119    }
120
121    const fn raw(self) -> u32 {
122        self.0
123    }
124}
125
126impl TryFrom<usize> for ParserIntervalSetId {
127    type Error = ParserAtnError;
128
129    fn try_from(value: usize) -> Result<Self, Self::Error> {
130        compact_id("parser ATN interval set", value).map(Self)
131    }
132}
133
134/// Failure while reading, validating, or constructing packed parser ATN data.
135#[derive(Clone, Debug, Eq, PartialEq, thiserror::Error)]
136pub enum ParserAtnError {
137    #[error(
138        "generated parser ATN format version {found} is unsupported; \
139         this runtime requires generator/runtime format {minimum}..={maximum}"
140    )]
141    UnsupportedVersion {
142        found: u32,
143        minimum: u32,
144        maximum: u32,
145    },
146    #[error("invalid packed parser ATN: {0}")]
147    InvalidData(String),
148    #[error("{field} count/index {value} exceeds the compact u32 range")]
149    Overflow { field: &'static str, value: usize },
150}
151
152/// Storage and shape measurements for one packed parser ATN.
153#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
154pub struct ParserAtnStats {
155    pub states: usize,
156    pub transitions: usize,
157    pub interval_sets: usize,
158    pub interval_ranges: usize,
159    pub decisions: usize,
160    pub rules: usize,
161    pub packed_bytes: usize,
162}
163
164/// Immutable packed parser ATN.
165///
166/// Generated parsers borrow a static word stream directly. Deserialization of
167/// ordinary ANTLR v4 integer metadata produces the same layout in one owned
168/// allocation.
169pub struct ParserAtn {
170    words: Cow<'static, [u32]>,
171    words_address: usize,
172    layout: ParserAtnLayout,
173}
174
175impl Clone for ParserAtn {
176    fn clone(&self) -> Self {
177        let words = self.words.clone();
178        let words_address = words.as_ptr() as usize;
179        Self {
180            words,
181            words_address,
182            layout: self.layout,
183        }
184    }
185}
186
187impl PartialEq for ParserAtn {
188    fn eq(&self, other: &Self) -> bool {
189        self.words == other.words && self.layout == other.layout
190    }
191}
192
193impl Eq for ParserAtn {}
194
195impl fmt::Debug for ParserAtn {
196    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
197        formatter
198            .debug_struct("ParserAtn")
199            .field("max_token_type", &self.max_token_type())
200            .field("stats", &self.stats())
201            .finish_non_exhaustive()
202    }
203}
204
205impl ParserAtn {
206    /// Validates and borrows generator-emitted packed data without allocating.
207    pub fn from_static(words: &'static [u32]) -> Result<Self, ParserAtnError> {
208        let layout = validate_packed(words)?;
209        Ok(Self {
210            words: Cow::Borrowed(words),
211            words_address: words.as_ptr() as usize,
212            layout,
213        })
214    }
215
216    /// Validates one owned packed stream.
217    pub fn from_owned(words: Vec<u32>) -> Result<Self, ParserAtnError> {
218        let layout = validate_packed(&words)?;
219        let words: Cow<'static, [u32]> = Cow::Owned(words);
220        let words_address = words.as_ptr() as usize;
221        Ok(Self {
222            words,
223            words_address,
224            layout,
225        })
226    }
227
228    /// Canonical generator/runtime format version carried by this ATN.
229    pub fn format_version(&self) -> u32 {
230        self.words[HEADER_VERSION]
231    }
232
233    #[inline(always)]
234    pub const fn max_token_type(&self) -> i32 {
235        self.layout.max_token_type
236    }
237
238    pub const fn state_count(&self) -> usize {
239        self.layout.state_count
240    }
241
242    pub const fn transition_count(&self) -> usize {
243        self.layout.transition_count
244    }
245
246    pub const fn decision_count(&self) -> usize {
247        self.layout.decisions.len
248    }
249
250    pub const fn rule_count(&self) -> usize {
251        self.layout.rule_starts.len
252    }
253
254    #[inline(always)]
255    pub fn state(&self, state_number: usize) -> Option<ParserAtnState<'_>> {
256        (state_number < self.state_count())
257            .then(|| ParserAtnState::new(self, AtnStateId(state_number as u32)))
258    }
259
260    #[inline(always)]
261    pub fn state_by_id(&self, id: AtnStateId) -> Option<ParserAtnState<'_>> {
262        (id.index() < self.state_count()).then(|| ParserAtnState::new(self, id))
263    }
264
265    pub const fn states(&self) -> ParserAtnStates<'_> {
266        ParserAtnStates {
267            atn: self,
268            next: 0,
269            end: self.state_count(),
270        }
271    }
272
273    #[inline(always)]
274    pub fn transition(&self, id: TransitionId) -> Option<ParserTransition<'_>> {
275        (id.index() < self.transition_count()).then(|| ParserTransition::new(self, id))
276    }
277
278    pub const fn decision_to_state(&self) -> ParserStateIdTable<'_> {
279        ParserStateIdTable::new(self, self.layout.decisions)
280    }
281
282    pub const fn rule_to_start_state(&self) -> ParserStateIdTable<'_> {
283        ParserStateIdTable::new(self, self.layout.rule_starts)
284    }
285
286    pub const fn rule_to_stop_state(&self) -> ParserStateIdTable<'_> {
287        ParserStateIdTable::new(self, self.layout.rule_stops)
288    }
289
290    /// Returns the exact generator-emitted representation.
291    pub fn packed_words(&self) -> &[u32] {
292        &self.words
293    }
294
295    /// Stable backing-storage address used by thread-local grammar caches.
296    pub(crate) fn storage_identity(&self) -> (usize, usize) {
297        (self.words.as_ptr() as usize, self.words.len())
298    }
299
300    pub fn stats(&self) -> ParserAtnStats {
301        ParserAtnStats {
302            states: self.state_count(),
303            transitions: self.transition_count(),
304            interval_sets: self.layout.sets.len / SET_WORDS,
305            interval_ranges: self.layout.intervals.len / 2,
306            decisions: self.decision_count(),
307            rules: self.rule_count(),
308            packed_bytes: self.words.len() * size_of::<u32>(),
309        }
310    }
311
312    #[inline(always)]
313    fn word(&self, section: Section, record: usize, field: usize, width: usize) -> u32 {
314        self.packed_word(section.offset + record * width + field)
315    }
316
317    #[inline(always)]
318    fn interval_set(&self, id: ParserIntervalSetId) -> ParserIntervalSet<'_> {
319        let start = self.word(self.layout.sets, id.index(), 0, SET_WORDS) as usize;
320        let len = self.word(self.layout.sets, id.index(), 1, SET_WORDS) as usize;
321        ParserIntervalSet {
322            atn: self,
323            start,
324            len,
325        }
326    }
327
328    #[inline(always)]
329    fn packed_address(&self, index: usize) -> usize {
330        debug_assert!(index < self.words.len());
331        self.words_address + index * size_of::<u32>()
332    }
333
334    #[inline(always)]
335    #[allow(unsafe_code)]
336    fn packed_word(&self, index: usize) -> u32 {
337        debug_assert!(index < self.words.len());
338        // `words_address` is captured after the final backing allocation is in
339        // place. Parser ATNs are immutable, and every view index/range is
340        // validated before construction, so the allocation remains live and
341        // the read stays in bounds for the lifetime of `self`.
342        unsafe { *((self.words_address as *const u32).add(index)) }
343    }
344}
345
346/// Borrowing semantic view over one parser ATN state.
347#[derive(Clone, Copy)]
348pub struct ParserAtnState<'a> {
349    atn: &'a ParserAtn,
350    record_address: usize,
351}
352
353impl fmt::Debug for ParserAtnState<'_> {
354    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
355        formatter
356            .debug_struct("ParserAtnState")
357            .field("id", &self.id())
358            .field("kind", &self.kind())
359            .field("rule_index", &self.rule_index())
360            .field("transition_count", &self.transitions().len())
361            .finish()
362    }
363}
364
365impl<'a> ParserAtnState<'a> {
366    #[inline(always)]
367    fn new(atn: &'a ParserAtn, id: AtnStateId) -> Self {
368        Self {
369            atn,
370            record_address: atn.packed_address(atn.layout.states.offset + id.index() * STATE_WORDS),
371        }
372    }
373
374    pub const fn id(self) -> AtnStateId {
375        let word = (self.record_address - self.atn.words_address) / size_of::<u32>();
376        AtnStateId(((word - self.atn.layout.states.offset) / STATE_WORDS) as u32)
377    }
378
379    pub const fn state_number(self) -> usize {
380        self.id().index()
381    }
382
383    #[inline(always)]
384    pub fn kind(self) -> AtnStateKind {
385        decode_state_kind(self.word(0)).expect("packed parser ATN state kind was validated")
386    }
387
388    #[inline(always)]
389    pub fn rule_index(self) -> Option<usize> {
390        unpack_index(self.word(1))
391    }
392
393    #[inline(always)]
394    pub fn end_state(self) -> Option<usize> {
395        unpack_index(self.word(5))
396    }
397
398    #[inline(always)]
399    pub fn loop_back_state(self) -> Option<usize> {
400        unpack_index(self.word(6))
401    }
402
403    #[inline(always)]
404    pub fn non_greedy(self) -> bool {
405        self.flags() & FLAG_NON_GREEDY != 0
406    }
407
408    #[inline(always)]
409    pub fn precedence_rule_decision(self) -> bool {
410        self.flags() & FLAG_PRECEDENCE_DECISION != 0
411    }
412
413    #[inline(always)]
414    pub fn left_recursive_rule(self) -> bool {
415        self.flags() & FLAG_LEFT_RECURSIVE_RULE != 0
416    }
417
418    #[inline]
419    pub fn is_rule_stop(self) -> bool {
420        self.flags() & FLAG_RULE_STOP != 0
421    }
422
423    #[inline]
424    pub fn epsilon_only(self) -> bool {
425        self.flags() & FLAG_EPSILON_ONLY != 0
426    }
427
428    #[inline]
429    pub fn has_consuming_transition(self) -> bool {
430        self.flags() & FLAG_HAS_CONSUMING != 0
431    }
432
433    #[inline]
434    pub fn has_semantic_transition(self) -> bool {
435        self.flags() & FLAG_HAS_SEMANTIC != 0
436    }
437
438    #[inline(always)]
439    pub fn transitions(self) -> ParserTransitions<'a> {
440        let start = self.word(3) as usize;
441        ParserTransitions {
442            atn: self.atn,
443            record_address: self
444                .atn
445                .packed_address(self.atn.layout.transitions.offset + start * TRANSITION_WORDS),
446            len: self.word(4) as usize,
447        }
448    }
449
450    #[inline(always)]
451    fn flags(self) -> u32 {
452        self.word(2)
453    }
454
455    #[inline(always)]
456    #[allow(unsafe_code)]
457    fn word(self, field: usize) -> u32 {
458        debug_assert!(field < STATE_WORDS);
459        // The record address comes from the immutable validated state
460        // section, and `field` is constrained to the fixed record width.
461        unsafe { *((self.record_address as *const u32).add(field)) }
462    }
463}
464
465/// Borrowing range of transitions owned by the ATN's shared transition pool.
466#[derive(Clone, Copy, Debug)]
467pub struct ParserTransitions<'a> {
468    atn: &'a ParserAtn,
469    record_address: usize,
470    len: usize,
471}
472
473impl<'a> ParserTransitions<'a> {
474    pub const fn len(self) -> usize {
475        self.len
476    }
477
478    pub const fn is_empty(self) -> bool {
479        self.len == 0
480    }
481
482    #[inline(always)]
483    pub fn get(self, index: usize) -> Option<ParserTransition<'a>> {
484        (index < self.len).then(|| ParserTransition {
485            atn: self.atn,
486            record_address: self.record_address + index * TRANSITION_WORDS * size_of::<u32>(),
487        })
488    }
489
490    #[inline(always)]
491    pub fn first(self) -> Option<ParserTransition<'a>> {
492        self.get(0)
493    }
494
495    #[inline]
496    pub fn last(self) -> Option<ParserTransition<'a>> {
497        self.len.checked_sub(1).and_then(|index| self.get(index))
498    }
499
500    pub const fn iter(self) -> ParserTransitionIter<'a> {
501        ParserTransitionIter {
502            atn: self.atn,
503            next_record_address: self.record_address,
504            remaining: self.len,
505        }
506    }
507}
508
509impl<'a> IntoIterator for ParserTransitions<'a> {
510    type Item = ParserTransition<'a>;
511    type IntoIter = ParserTransitionIter<'a>;
512
513    fn into_iter(self) -> Self::IntoIter {
514        self.iter()
515    }
516}
517
518impl<'a> IntoIterator for &'a ParserTransitions<'a> {
519    type Item = ParserTransition<'a>;
520    type IntoIter = ParserTransitionIter<'a>;
521
522    fn into_iter(self) -> Self::IntoIter {
523        self.iter()
524    }
525}
526
527/// Iterator over one state's contiguous transition range.
528#[derive(Clone, Debug)]
529pub struct ParserTransitionIter<'a> {
530    atn: &'a ParserAtn,
531    next_record_address: usize,
532    remaining: usize,
533}
534
535impl<'a> Iterator for ParserTransitionIter<'a> {
536    type Item = ParserTransition<'a>;
537
538    #[inline(always)]
539    fn next(&mut self) -> Option<Self::Item> {
540        if self.remaining == 0 {
541            return None;
542        }
543        let transition = ParserTransition {
544            atn: self.atn,
545            record_address: self.next_record_address,
546        };
547        self.next_record_address += TRANSITION_WORDS * size_of::<u32>();
548        self.remaining -= 1;
549        Some(transition)
550    }
551
552    fn size_hint(&self) -> (usize, Option<usize>) {
553        (self.remaining, Some(self.remaining))
554    }
555}
556
557impl ExactSizeIterator for ParserTransitionIter<'_> {}
558impl FusedIterator for ParserTransitionIter<'_> {}
559
560/// Borrowing semantic view over one parser ATN transition.
561#[derive(Clone, Copy)]
562pub struct ParserTransition<'a> {
563    atn: &'a ParserAtn,
564    record_address: usize,
565}
566
567impl fmt::Debug for ParserTransition<'_> {
568    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
569        self.data().fmt(formatter)
570    }
571}
572
573impl<'a> ParserTransition<'a> {
574    #[inline(always)]
575    fn new(atn: &'a ParserAtn, id: TransitionId) -> Self {
576        Self {
577            atn,
578            record_address: atn
579                .packed_address(atn.layout.transitions.offset + id.index() * TRANSITION_WORDS),
580        }
581    }
582
583    #[inline(always)]
584    pub const fn id(self) -> TransitionId {
585        let word = (self.record_address - self.atn.words_address) / size_of::<u32>();
586        TransitionId(((word - self.atn.layout.transitions.offset) / TRANSITION_WORDS) as u32)
587    }
588
589    #[inline(always)]
590    pub fn target_id(self) -> AtnStateId {
591        AtnStateId(self.word(1))
592    }
593
594    #[inline(always)]
595    pub fn target(self) -> usize {
596        self.target_id().index()
597    }
598
599    #[inline(always)]
600    pub fn kind(self) -> ParserTransitionKind {
601        decode_transition_kind(self.word(0))
602            .expect("packed parser ATN transition kind was validated")
603    }
604
605    #[inline(always)]
606    pub fn is_epsilon(self) -> bool {
607        matches!(
608            self.kind(),
609            ParserTransitionKind::Epsilon
610                | ParserTransitionKind::Rule
611                | ParserTransitionKind::Predicate
612                | ParserTransitionKind::Action
613                | ParserTransitionKind::Precedence
614        )
615    }
616
617    #[inline(always)]
618    pub fn is_action(self) -> bool {
619        self.kind() == ParserTransitionKind::Action
620    }
621
622    #[inline(always)]
623    pub fn matches(self, symbol: i32, min_vocabulary: i32, max_vocabulary: i32) -> bool {
624        self.matches_kind(self.kind(), symbol, min_vocabulary, max_vocabulary)
625    }
626
627    #[inline(always)]
628    pub(crate) fn matches_kind(
629        self,
630        kind: ParserTransitionKind,
631        symbol: i32,
632        min_vocabulary: i32,
633        max_vocabulary: i32,
634    ) -> bool {
635        match kind {
636            ParserTransitionKind::Atom => unpack_i32(self.arg0()) == symbol,
637            ParserTransitionKind::Range => {
638                (unpack_i32(self.arg0())..=unpack_i32(self.arg1())).contains(&symbol)
639            }
640            ParserTransitionKind::Set => self
641                .atn
642                .interval_set(ParserIntervalSetId(self.arg0()))
643                .contains(symbol),
644            ParserTransitionKind::NotSet => {
645                (min_vocabulary..=max_vocabulary).contains(&symbol)
646                    && !self
647                        .atn
648                        .interval_set(ParserIntervalSetId(self.arg0()))
649                        .contains(symbol)
650            }
651            ParserTransitionKind::Wildcard => (min_vocabulary..=max_vocabulary).contains(&symbol),
652            ParserTransitionKind::Epsilon
653            | ParserTransitionKind::Rule
654            | ParserTransitionKind::Predicate
655            | ParserTransitionKind::Action
656            | ParserTransitionKind::Precedence => false,
657        }
658    }
659
660    #[inline(always)]
661    pub(crate) fn arg0(self) -> u32 {
662        self.word(2)
663    }
664
665    #[inline(always)]
666    pub(crate) fn arg1(self) -> u32 {
667        self.word(3)
668    }
669
670    #[inline(always)]
671    pub(crate) fn arg2(self) -> u32 {
672        self.word(4)
673    }
674
675    #[inline(always)]
676    pub fn data(self) -> ParserTransitionData<'a> {
677        match decode_transition_kind(self.word(0))
678            .expect("packed parser ATN transition kind was validated")
679        {
680            ParserTransitionKind::Epsilon => ParserTransitionData::Epsilon {
681                target: self.word(1) as usize,
682            },
683            ParserTransitionKind::Atom => ParserTransitionData::Atom {
684                target: self.word(1) as usize,
685                label: unpack_i32(self.word(2)),
686            },
687            ParserTransitionKind::Range => ParserTransitionData::Range {
688                target: self.word(1) as usize,
689                start: unpack_i32(self.word(2)),
690                stop: unpack_i32(self.word(3)),
691            },
692            ParserTransitionKind::Set => ParserTransitionData::Set {
693                target: self.word(1) as usize,
694                set: self.atn.interval_set(ParserIntervalSetId(self.word(2))),
695            },
696            ParserTransitionKind::NotSet => ParserTransitionData::NotSet {
697                target: self.word(1) as usize,
698                set: self.atn.interval_set(ParserIntervalSetId(self.word(2))),
699            },
700            ParserTransitionKind::Wildcard => ParserTransitionData::Wildcard {
701                target: self.word(1) as usize,
702            },
703            ParserTransitionKind::Rule => ParserTransitionData::Rule {
704                target: self.word(1) as usize,
705                rule_index: self.word(2) as usize,
706                follow_state: self.word(3) as usize,
707                precedence: unpack_i32(self.word(4)),
708            },
709            ParserTransitionKind::Predicate => ParserTransitionData::Predicate {
710                target: self.word(1) as usize,
711                rule_index: self.word(2) as usize,
712                pred_index: self.word(3) as usize,
713                context_dependent: self.word(4) != 0,
714            },
715            ParserTransitionKind::Action => ParserTransitionData::Action {
716                target: self.word(1) as usize,
717                rule_index: self.word(2) as usize,
718                action_index: unpack_index(self.word(3)),
719                context_dependent: self.word(4) != 0,
720            },
721            ParserTransitionKind::Precedence => ParserTransitionData::Precedence {
722                target: self.word(1) as usize,
723                precedence: unpack_i32(self.word(2)),
724            },
725        }
726    }
727
728    #[inline(always)]
729    #[allow(unsafe_code)]
730    fn word(self, field: usize) -> u32 {
731        debug_assert!(field < TRANSITION_WORDS);
732        // The record address comes from the immutable validated transition
733        // section, and `field` is constrained to the fixed record width.
734        unsafe { *((self.record_address as *const u32).add(field)) }
735    }
736}
737
738/// Fixed transition tag stored in the packed transition table.
739#[derive(Clone, Copy, Debug, Eq, PartialEq)]
740#[repr(u8)]
741pub enum ParserTransitionKind {
742    Epsilon = 1,
743    Range = 2,
744    Rule = 3,
745    Predicate = 4,
746    Atom = 5,
747    Action = 6,
748    Set = 7,
749    NotSet = 8,
750    Wildcard = 9,
751    Precedence = 10,
752}
753
754/// Borrowing semantic payload for a packed parser transition.
755#[derive(Clone, Copy, Debug, Eq, PartialEq)]
756pub enum ParserTransitionData<'a> {
757    Epsilon {
758        target: usize,
759    },
760    Atom {
761        target: usize,
762        label: i32,
763    },
764    Range {
765        target: usize,
766        start: i32,
767        stop: i32,
768    },
769    Set {
770        target: usize,
771        set: ParserIntervalSet<'a>,
772    },
773    NotSet {
774        target: usize,
775        set: ParserIntervalSet<'a>,
776    },
777    Wildcard {
778        target: usize,
779    },
780    Rule {
781        target: usize,
782        rule_index: usize,
783        follow_state: usize,
784        precedence: i32,
785    },
786    Predicate {
787        target: usize,
788        rule_index: usize,
789        pred_index: usize,
790        context_dependent: bool,
791    },
792    Action {
793        target: usize,
794        rule_index: usize,
795        action_index: Option<usize>,
796        context_dependent: bool,
797    },
798    Precedence {
799        target: usize,
800        precedence: i32,
801    },
802}
803
804impl ParserTransitionData<'_> {
805    pub const fn target(self) -> usize {
806        match self {
807            Self::Epsilon { target }
808            | Self::Atom { target, .. }
809            | Self::Range { target, .. }
810            | Self::Set { target, .. }
811            | Self::NotSet { target, .. }
812            | Self::Wildcard { target }
813            | Self::Rule { target, .. }
814            | Self::Predicate { target, .. }
815            | Self::Action { target, .. }
816            | Self::Precedence { target, .. } => target,
817        }
818    }
819
820    pub const fn is_epsilon(self) -> bool {
821        matches!(
822            self,
823            Self::Epsilon { .. }
824                | Self::Rule { .. }
825                | Self::Predicate { .. }
826                | Self::Action { .. }
827                | Self::Precedence { .. }
828        )
829    }
830
831    pub const fn is_action(self) -> bool {
832        matches!(self, Self::Action { .. })
833    }
834
835    pub fn matches(self, symbol: i32, min_vocabulary: i32, max_vocabulary: i32) -> bool {
836        match self {
837            Self::Atom { label, .. } => label == symbol,
838            Self::Range { start, stop, .. } => (start..=stop).contains(&symbol),
839            Self::Set { set, .. } => set.contains(symbol),
840            Self::NotSet { set, .. } => {
841                (min_vocabulary..=max_vocabulary).contains(&symbol) && !set.contains(symbol)
842            }
843            Self::Wildcard { .. } => (min_vocabulary..=max_vocabulary).contains(&symbol),
844            Self::Epsilon { .. }
845            | Self::Rule { .. }
846            | Self::Predicate { .. }
847            | Self::Action { .. }
848            | Self::Precedence { .. } => false,
849        }
850    }
851}
852
853/// Borrowing view over one interval set in the shared interval pool.
854#[derive(Clone, Copy, Eq, PartialEq)]
855pub struct ParserIntervalSet<'a> {
856    atn: &'a ParserAtn,
857    start: usize,
858    len: usize,
859}
860
861impl fmt::Debug for ParserIntervalSet<'_> {
862    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
863        formatter.debug_list().entries(self.ranges()).finish()
864    }
865}
866
867impl<'a> ParserIntervalSet<'a> {
868    pub const fn is_empty(self) -> bool {
869        self.len == 0
870    }
871
872    #[inline(always)]
873    pub fn contains(self, value: i32) -> bool {
874        let mut low = 0;
875        let mut high = self.len;
876        while low < high {
877            let middle = low + (high - low) / 2;
878            if self.range_start(middle) <= value {
879                low = middle + 1;
880            } else {
881                high = middle;
882            }
883        }
884        low > 0 && self.range_stop(low - 1) >= value
885    }
886
887    pub const fn ranges(self) -> ParserIntervalRanges<'a> {
888        ParserIntervalRanges { set: self, next: 0 }
889    }
890
891    #[inline(always)]
892    fn range(self, index: usize) -> (i32, i32) {
893        (self.range_start(index), self.range_stop(index))
894    }
895
896    #[inline(always)]
897    fn range_start(self, index: usize) -> i32 {
898        let word = self.atn.layout.intervals.offset + (self.start + index) * 2;
899        unpack_i32(self.atn.packed_word(word))
900    }
901
902    #[inline(always)]
903    fn range_stop(self, index: usize) -> i32 {
904        let word = self.atn.layout.intervals.offset + (self.start + index) * 2 + 1;
905        unpack_i32(self.atn.packed_word(word))
906    }
907}
908
909/// Iterator over inclusive ranges in one shared parser interval set.
910#[derive(Clone, Debug)]
911pub struct ParserIntervalRanges<'a> {
912    set: ParserIntervalSet<'a>,
913    next: usize,
914}
915
916impl Iterator for ParserIntervalRanges<'_> {
917    type Item = (i32, i32);
918
919    #[inline]
920    fn next(&mut self) -> Option<Self::Item> {
921        if self.next >= self.set.len {
922            return None;
923        }
924        let range = self.set.range(self.next);
925        self.next += 1;
926        Some(range)
927    }
928
929    fn size_hint(&self) -> (usize, Option<usize>) {
930        let remaining = self.set.len.saturating_sub(self.next);
931        (remaining, Some(remaining))
932    }
933}
934
935impl ExactSizeIterator for ParserIntervalRanges<'_> {}
936impl FusedIterator for ParserIntervalRanges<'_> {}
937
938/// Borrowing compact-ID side table with checked `usize` accessors.
939#[derive(Clone, Copy, Debug)]
940pub struct ParserStateIdTable<'a> {
941    atn: &'a ParserAtn,
942    section: Section,
943}
944
945impl<'a> ParserStateIdTable<'a> {
946    const fn new(atn: &'a ParserAtn, section: Section) -> Self {
947        Self { atn, section }
948    }
949
950    pub const fn len(self) -> usize {
951        self.section.len
952    }
953
954    pub const fn is_empty(self) -> bool {
955        self.section.len == 0
956    }
957
958    #[inline(always)]
959    pub fn get(self, index: usize) -> Option<usize> {
960        (index < self.len()).then(|| self.atn.packed_word(self.section.offset + index) as usize)
961    }
962
963    pub fn get_id(self, index: usize) -> Option<AtnStateId> {
964        self.get(index).map(|value| {
965            AtnStateId::try_from(value).expect("validated side-table state fits compact ID")
966        })
967    }
968
969    pub const fn iter(self) -> ParserStateIdIter<'a> {
970        ParserStateIdIter {
971            table: self,
972            next: 0,
973        }
974    }
975}
976
977impl<'a> IntoIterator for ParserStateIdTable<'a> {
978    type Item = usize;
979    type IntoIter = ParserStateIdIter<'a>;
980
981    fn into_iter(self) -> Self::IntoIter {
982        self.iter()
983    }
984}
985
986/// Iterator over checked state indices in a parser ATN side table.
987#[derive(Clone, Debug)]
988pub struct ParserStateIdIter<'a> {
989    table: ParserStateIdTable<'a>,
990    next: usize,
991}
992
993impl Iterator for ParserStateIdIter<'_> {
994    type Item = usize;
995
996    #[inline]
997    fn next(&mut self) -> Option<Self::Item> {
998        let value = self.table.get(self.next)?;
999        self.next += 1;
1000        Some(value)
1001    }
1002
1003    fn size_hint(&self) -> (usize, Option<usize>) {
1004        let remaining = self.table.len().saturating_sub(self.next);
1005        (remaining, Some(remaining))
1006    }
1007}
1008
1009impl ExactSizeIterator for ParserStateIdIter<'_> {}
1010impl FusedIterator for ParserStateIdIter<'_> {}
1011
1012/// Iterator over every state in deterministic state-number order.
1013#[derive(Clone, Debug)]
1014pub struct ParserAtnStates<'a> {
1015    atn: &'a ParserAtn,
1016    next: usize,
1017    end: usize,
1018}
1019
1020impl<'a> Iterator for ParserAtnStates<'a> {
1021    type Item = ParserAtnState<'a>;
1022
1023    #[inline]
1024    fn next(&mut self) -> Option<Self::Item> {
1025        if self.next >= self.end {
1026            return None;
1027        }
1028        let state = self.atn.state(self.next);
1029        self.next += 1;
1030        state
1031    }
1032
1033    fn size_hint(&self) -> (usize, Option<usize>) {
1034        let remaining = self.end.saturating_sub(self.next);
1035        (remaining, Some(remaining))
1036    }
1037}
1038
1039impl ExactSizeIterator for ParserAtnStates<'_> {}
1040impl FusedIterator for ParserAtnStates<'_> {}
1041
1042/// Centralized construction API for packed parser ATNs.
1043///
1044/// States never own transition collections; edges are grouped into contiguous
1045/// ranges only when the final packed stream is emitted.
1046#[derive(Debug)]
1047pub struct ParserAtnBuilder {
1048    max_token_type: i32,
1049    states: Vec<StateBuild>,
1050    transitions: Vec<TransitionBuild>,
1051    interval_sets: Vec<(u32, u32)>,
1052    interval_ranges: Vec<(i32, i32)>,
1053    decisions: Vec<AtnStateId>,
1054    rule_starts: Vec<AtnStateId>,
1055    rule_stops: Vec<AtnStateId>,
1056}
1057
1058impl ParserAtnBuilder {
1059    pub const fn new(max_token_type: i32) -> Self {
1060        Self {
1061            max_token_type,
1062            states: Vec::new(),
1063            transitions: Vec::new(),
1064            interval_sets: Vec::new(),
1065            interval_ranges: Vec::new(),
1066            decisions: Vec::new(),
1067            rule_starts: Vec::new(),
1068            rule_stops: Vec::new(),
1069        }
1070    }
1071
1072    pub fn add_state(
1073        &mut self,
1074        kind: AtnStateKind,
1075        rule_index: Option<usize>,
1076    ) -> Result<AtnStateId, ParserAtnError> {
1077        let id = AtnStateId::try_from(self.states.len())?;
1078        let rule_index = pack_optional_index("parser ATN rule", rule_index)?;
1079        self.states.push(StateBuild {
1080            kind,
1081            rule_index,
1082            flags: u32::from(kind == AtnStateKind::RuleStop) * FLAG_RULE_STOP,
1083            end_state: NO_INDEX,
1084            loop_back_state: NO_INDEX,
1085        });
1086        Ok(id)
1087    }
1088
1089    pub fn set_end_state(&mut self, state: usize, end_state: usize) -> Result<(), ParserAtnError> {
1090        let end_state = self.checked_state(end_state, "block end state")?;
1091        self.state_mut(state, "block start state")?.end_state = end_state.raw();
1092        Ok(())
1093    }
1094
1095    pub fn set_loop_back_state(
1096        &mut self,
1097        state: usize,
1098        loop_back_state: usize,
1099    ) -> Result<(), ParserAtnError> {
1100        let loop_back_state = self.checked_state(loop_back_state, "loop back state")?;
1101        self.state_mut(state, "loop end state")?.loop_back_state = loop_back_state.raw();
1102        Ok(())
1103    }
1104
1105    pub fn set_non_greedy(&mut self, state: usize) -> Result<(), ParserAtnError> {
1106        self.state_mut(state, "non-greedy state")?.flags |= FLAG_NON_GREEDY;
1107        Ok(())
1108    }
1109
1110    pub fn set_left_recursive_rule(&mut self, state: usize) -> Result<(), ParserAtnError> {
1111        self.state_mut(state, "precedence rule state")?.flags |= FLAG_LEFT_RECURSIVE_RULE;
1112        Ok(())
1113    }
1114
1115    pub fn set_precedence_rule_decision(&mut self, state: usize) -> Result<(), ParserAtnError> {
1116        self.state_mut(state, "precedence decision state")?.flags |= FLAG_PRECEDENCE_DECISION;
1117        Ok(())
1118    }
1119
1120    pub fn add_interval_set(
1121        &mut self,
1122        ranges: impl IntoIterator<Item = (i32, i32)>,
1123    ) -> Result<ParserIntervalSetId, ParserAtnError> {
1124        let id = ParserIntervalSetId::try_from(self.interval_sets.len())?;
1125        let start = compact_id("parser ATN interval start", self.interval_ranges.len())?;
1126        let normalized = normalize_ranges(ranges);
1127        let len = compact_id("parser ATN interval count", normalized.len())?;
1128        self.interval_ranges.extend(normalized);
1129        self.interval_sets.push((start, len));
1130        Ok(id)
1131    }
1132
1133    pub fn add_transition(
1134        &mut self,
1135        source: usize,
1136        transition: ParserTransitionSpec,
1137    ) -> Result<TransitionId, ParserAtnError> {
1138        let source = self.checked_state(source, "transition source")?;
1139        let record = self.transition_record(source, transition)?;
1140        let id = TransitionId::try_from(self.transitions.len())?;
1141        self.transitions.push(record);
1142        Ok(id)
1143    }
1144
1145    pub fn set_rule_to_start_state(&mut self, states: Vec<usize>) -> Result<(), ParserAtnError> {
1146        self.rule_starts = self.checked_states(states, "rule start state")?;
1147        Ok(())
1148    }
1149
1150    pub fn set_rule_to_stop_state(&mut self, states: Vec<usize>) -> Result<(), ParserAtnError> {
1151        self.rule_stops = self.checked_states(states, "rule stop state")?;
1152        Ok(())
1153    }
1154
1155    pub fn add_decision_state(&mut self, state: usize) -> Result<(), ParserAtnError> {
1156        let state = self.checked_state(state, "decision state")?;
1157        self.decisions.push(state);
1158        Ok(())
1159    }
1160
1161    pub fn state_kind(&self, state: usize) -> Option<AtnStateKind> {
1162        self.states.get(state).map(|record| record.kind)
1163    }
1164
1165    pub const fn state_count(&self) -> usize {
1166        self.states.len()
1167    }
1168
1169    pub fn state_rule_index(&self, state: usize) -> Option<usize> {
1170        self.states
1171            .get(state)
1172            .and_then(|record| unpack_index(record.rule_index))
1173    }
1174
1175    pub fn rule_stop_state(&self, rule: usize) -> Option<usize> {
1176        self.rule_stops.get(rule).copied().map(AtnStateId::index)
1177    }
1178
1179    pub fn transitions_from(
1180        &self,
1181        source: usize,
1182    ) -> impl DoubleEndedIterator<Item = ParserTransitionSpec> + '_ {
1183        self.transitions
1184            .iter()
1185            .filter(move |transition| transition.source.index() == source)
1186            .map(TransitionBuild::spec)
1187    }
1188
1189    pub fn finish(mut self) -> Result<ParserAtn, ParserAtnError> {
1190        self.mark_precedence_decisions();
1191        self.transitions.sort_by_key(|transition| transition.source);
1192        let transition_ranges = self.transition_ranges()?;
1193        self.precompute_state_flags(&transition_ranges);
1194        let words = self.encode(&transition_ranges)?;
1195        ParserAtn::from_owned(words)
1196    }
1197
1198    fn state_mut(&mut self, state: usize, label: &str) -> Result<&mut StateBuild, ParserAtnError> {
1199        self.states.get_mut(state).ok_or_else(|| {
1200            ParserAtnError::InvalidData(format!("{label} {state} outside state list"))
1201        })
1202    }
1203
1204    fn checked_state(&self, state: usize, label: &str) -> Result<AtnStateId, ParserAtnError> {
1205        let id = AtnStateId::try_from(state)?;
1206        if state >= self.states.len() {
1207            return Err(ParserAtnError::InvalidData(format!(
1208                "{label} {state} outside state list"
1209            )));
1210        }
1211        Ok(id)
1212    }
1213
1214    fn checked_states(
1215        &self,
1216        states: Vec<usize>,
1217        label: &str,
1218    ) -> Result<Vec<AtnStateId>, ParserAtnError> {
1219        states
1220            .into_iter()
1221            .map(|state| self.checked_state(state, label))
1222            .collect()
1223    }
1224
1225    fn transition_record(
1226        &self,
1227        source: AtnStateId,
1228        spec: ParserTransitionSpec,
1229    ) -> Result<TransitionBuild, ParserAtnError> {
1230        let target = self.checked_state(spec.target(), "transition target")?;
1231        let (kind, arg0, arg1, arg2) = match spec {
1232            ParserTransitionSpec::Epsilon { .. } => (ParserTransitionKind::Epsilon, 0, 0, 0),
1233            ParserTransitionSpec::Atom { label, .. } => {
1234                (ParserTransitionKind::Atom, pack_i32(label), 0, 0)
1235            }
1236            ParserTransitionSpec::Range { start, stop, .. } => (
1237                ParserTransitionKind::Range,
1238                pack_i32(start),
1239                pack_i32(stop),
1240                0,
1241            ),
1242            ParserTransitionSpec::Set { set, .. } => {
1243                self.checked_set(set)?;
1244                (ParserTransitionKind::Set, set.raw(), 0, 0)
1245            }
1246            ParserTransitionSpec::NotSet { set, .. } => {
1247                self.checked_set(set)?;
1248                (ParserTransitionKind::NotSet, set.raw(), 0, 0)
1249            }
1250            ParserTransitionSpec::Wildcard { .. } => (ParserTransitionKind::Wildcard, 0, 0, 0),
1251            ParserTransitionSpec::Rule {
1252                rule_index,
1253                follow_state,
1254                precedence,
1255                ..
1256            } => (
1257                ParserTransitionKind::Rule,
1258                compact_id("rule transition rule", rule_index)?,
1259                self.checked_state(follow_state, "rule follow state")?.raw(),
1260                pack_i32(precedence),
1261            ),
1262            ParserTransitionSpec::Predicate {
1263                rule_index,
1264                pred_index,
1265                context_dependent,
1266                ..
1267            } => (
1268                ParserTransitionKind::Predicate,
1269                compact_id("predicate rule", rule_index)?,
1270                compact_id("predicate index", pred_index)?,
1271                u32::from(context_dependent),
1272            ),
1273            ParserTransitionSpec::Action {
1274                rule_index,
1275                action_index,
1276                context_dependent,
1277                ..
1278            } => (
1279                ParserTransitionKind::Action,
1280                compact_id("action rule", rule_index)?,
1281                pack_optional_index("action", action_index)?,
1282                u32::from(context_dependent),
1283            ),
1284            ParserTransitionSpec::Precedence { precedence, .. } => {
1285                (ParserTransitionKind::Precedence, pack_i32(precedence), 0, 0)
1286            }
1287        };
1288        Ok(TransitionBuild {
1289            source,
1290            kind,
1291            target,
1292            arg0,
1293            arg1,
1294            arg2,
1295        })
1296    }
1297
1298    fn checked_set(&self, set: ParserIntervalSetId) -> Result<(), ParserAtnError> {
1299        if set.index() >= self.interval_sets.len() {
1300            return Err(ParserAtnError::InvalidData(format!(
1301                "interval set {} outside set list",
1302                set.index()
1303            )));
1304        }
1305        Ok(())
1306    }
1307
1308    fn transition_ranges(&self) -> Result<Vec<(u32, u32)>, ParserAtnError> {
1309        let mut ranges = vec![(0, 0); self.states.len()];
1310        let mut cursor = 0;
1311        for (state, range) in ranges.iter_mut().enumerate() {
1312            let start = cursor;
1313            while cursor < self.transitions.len()
1314                && self.transitions[cursor].source.index() == state
1315            {
1316                cursor += 1;
1317            }
1318            *range = (
1319                compact_id("state transition start", start)?,
1320                compact_id("state transition count", cursor - start)?,
1321            );
1322        }
1323        Ok(ranges)
1324    }
1325
1326    fn precompute_state_flags(&mut self, ranges: &[(u32, u32)]) {
1327        for (state, &(start, len)) in self.states.iter_mut().zip(ranges) {
1328            let transitions = &self.transitions[start as usize..start as usize + len as usize];
1329            if !transitions.is_empty()
1330                && transitions
1331                    .iter()
1332                    .all(|transition| transition.kind.is_epsilon())
1333            {
1334                state.flags |= FLAG_EPSILON_ONLY;
1335            }
1336            if transitions
1337                .iter()
1338                .any(|transition| transition.kind.is_consuming())
1339            {
1340                state.flags |= FLAG_HAS_CONSUMING;
1341            }
1342            if transitions
1343                .iter()
1344                .any(|transition| transition.kind.is_semantic())
1345            {
1346                state.flags |= FLAG_HAS_SEMANTIC;
1347            }
1348        }
1349    }
1350
1351    fn mark_precedence_decisions(&mut self) {
1352        let candidates = (0..self.states.len())
1353            .filter(|&state| self.is_precedence_decision(state))
1354            .collect::<Vec<_>>();
1355        for state in candidates {
1356            self.states[state].flags |= FLAG_PRECEDENCE_DECISION;
1357        }
1358    }
1359
1360    fn is_precedence_decision(&self, state: usize) -> bool {
1361        let record = &self.states[state];
1362        if record.kind != AtnStateKind::StarLoopEntry {
1363            return false;
1364        }
1365        let Some(rule_index) = unpack_index(record.rule_index) else {
1366            return false;
1367        };
1368        let Some(rule_start) = self.rule_starts.get(rule_index) else {
1369            return false;
1370        };
1371        if self.states[rule_start.index()].flags & FLAG_LEFT_RECURSIVE_RULE == 0 {
1372            return false;
1373        }
1374        let Some(loop_end) = self.transitions_from(state).next_back() else {
1375            return false;
1376        };
1377        let loop_end = loop_end.target();
1378        if self.state_kind(loop_end) != Some(AtnStateKind::LoopEnd) {
1379            return false;
1380        }
1381        self.transitions_from(loop_end)
1382            .next()
1383            .and_then(|transition| self.state_kind(transition.target()))
1384            == Some(AtnStateKind::RuleStop)
1385    }
1386
1387    fn encode(&self, transition_ranges: &[(u32, u32)]) -> Result<Vec<u32>, ParserAtnError> {
1388        let layout = EncodedLayout::new(self)?;
1389        let mut words = vec![0; layout.total_len];
1390        self.encode_header(&mut words, layout)?;
1391        self.encode_states(&mut words, layout.states, transition_ranges);
1392        self.encode_transitions(&mut words, layout.transitions);
1393        self.encode_sets(&mut words, layout.sets);
1394        self.encode_intervals(&mut words, layout.intervals);
1395        encode_ids(&mut words, layout.decisions, &self.decisions);
1396        encode_ids(&mut words, layout.rule_starts, &self.rule_starts);
1397        encode_ids(&mut words, layout.rule_stops, &self.rule_stops);
1398        Ok(words)
1399    }
1400
1401    fn encode_header(
1402        &self,
1403        words: &mut [u32],
1404        layout: EncodedLayout,
1405    ) -> Result<(), ParserAtnError> {
1406        words[HEADER_MAGIC] = PARSER_ATN_MAGIC;
1407        words[HEADER_VERSION] = PARSER_ATN_FORMAT_VERSION;
1408        words[HEADER_BYTE_ORDER] = PARSER_ATN_BYTE_ORDER;
1409        words[HEADER_SIZE] = compact_id("parser ATN header size", HEADER_WORDS)?;
1410        words[HEADER_MAX_TOKEN_TYPE] = pack_i32(self.max_token_type);
1411        words[HEADER_STATE_COUNT] = compact_id("parser ATN state count", self.states.len())?;
1412        words[HEADER_TRANSITION_COUNT] =
1413            compact_id("parser ATN transition count", self.transitions.len())?;
1414        words[HEADER_SET_COUNT] =
1415            compact_id("parser ATN interval-set count", self.interval_sets.len())?;
1416        words[HEADER_INTERVAL_COUNT] =
1417            compact_id("parser ATN interval count", self.interval_ranges.len())?;
1418        words[HEADER_DECISION_COUNT] =
1419            compact_id("parser ATN decision count", self.decisions.len())?;
1420        words[HEADER_RULE_COUNT] = compact_id("parser ATN rule count", self.rule_starts.len())?;
1421        write_section(words, HEADER_STATES_OFFSET, layout.states)?;
1422        write_section(words, HEADER_TRANSITIONS_OFFSET, layout.transitions)?;
1423        write_section(words, HEADER_SETS_OFFSET, layout.sets)?;
1424        write_section(words, HEADER_INTERVALS_OFFSET, layout.intervals)?;
1425        write_section(words, HEADER_DECISIONS_OFFSET, layout.decisions)?;
1426        write_section(words, HEADER_RULE_STARTS_OFFSET, layout.rule_starts)?;
1427        write_section(words, HEADER_RULE_STOPS_OFFSET, layout.rule_stops)?;
1428        words[HEADER_TOTAL_LEN] = compact_id("packed parser ATN word", layout.total_len)?;
1429        Ok(())
1430    }
1431
1432    fn encode_states(&self, words: &mut [u32], section: Section, transition_ranges: &[(u32, u32)]) {
1433        for (index, (state, &(start, len))) in self.states.iter().zip(transition_ranges).enumerate()
1434        {
1435            let base = section.offset + index * STATE_WORDS;
1436            words[base] = state_kind_word(state.kind);
1437            words[base + 1] = state.rule_index;
1438            words[base + 2] = state.flags;
1439            words[base + 3] = start;
1440            words[base + 4] = len;
1441            words[base + 5] = state.end_state;
1442            words[base + 6] = state.loop_back_state;
1443        }
1444    }
1445
1446    fn encode_transitions(&self, words: &mut [u32], section: Section) {
1447        for (index, transition) in self.transitions.iter().enumerate() {
1448            let base = section.offset + index * TRANSITION_WORDS;
1449            words[base] = transition.kind as u32;
1450            words[base + 1] = transition.target.raw();
1451            words[base + 2] = transition.arg0;
1452            words[base + 3] = transition.arg1;
1453            words[base + 4] = transition.arg2;
1454        }
1455    }
1456
1457    fn encode_sets(&self, words: &mut [u32], section: Section) {
1458        for (index, &(start, len)) in self.interval_sets.iter().enumerate() {
1459            let base = section.offset + index * SET_WORDS;
1460            words[base] = start;
1461            words[base + 1] = len;
1462        }
1463    }
1464
1465    fn encode_intervals(&self, words: &mut [u32], section: Section) {
1466        for (index, &(start, stop)) in self.interval_ranges.iter().enumerate() {
1467            let base = section.offset + index * 2;
1468            words[base] = pack_i32(start);
1469            words[base + 1] = pack_i32(stop);
1470        }
1471    }
1472}
1473
1474/// Transient semantic transition accepted by [`ParserAtnBuilder`].
1475#[derive(Clone, Copy, Debug, Eq, PartialEq)]
1476pub enum ParserTransitionSpec {
1477    Epsilon {
1478        target: usize,
1479    },
1480    Atom {
1481        target: usize,
1482        label: i32,
1483    },
1484    Range {
1485        target: usize,
1486        start: i32,
1487        stop: i32,
1488    },
1489    Set {
1490        target: usize,
1491        set: ParserIntervalSetId,
1492    },
1493    NotSet {
1494        target: usize,
1495        set: ParserIntervalSetId,
1496    },
1497    Wildcard {
1498        target: usize,
1499    },
1500    Rule {
1501        target: usize,
1502        rule_index: usize,
1503        follow_state: usize,
1504        precedence: i32,
1505    },
1506    Predicate {
1507        target: usize,
1508        rule_index: usize,
1509        pred_index: usize,
1510        context_dependent: bool,
1511    },
1512    Action {
1513        target: usize,
1514        rule_index: usize,
1515        action_index: Option<usize>,
1516        context_dependent: bool,
1517    },
1518    Precedence {
1519        target: usize,
1520        precedence: i32,
1521    },
1522}
1523
1524impl ParserTransitionSpec {
1525    pub const fn target(self) -> usize {
1526        match self {
1527            Self::Epsilon { target }
1528            | Self::Atom { target, .. }
1529            | Self::Range { target, .. }
1530            | Self::Set { target, .. }
1531            | Self::NotSet { target, .. }
1532            | Self::Wildcard { target }
1533            | Self::Rule { target, .. }
1534            | Self::Predicate { target, .. }
1535            | Self::Action { target, .. }
1536            | Self::Precedence { target, .. } => target,
1537        }
1538    }
1539}
1540
1541#[derive(Clone, Copy, Debug, Eq, PartialEq)]
1542struct ParserAtnLayout {
1543    max_token_type: i32,
1544    state_count: usize,
1545    transition_count: usize,
1546    states: Section,
1547    transitions: Section,
1548    sets: Section,
1549    intervals: Section,
1550    decisions: Section,
1551    rule_starts: Section,
1552    rule_stops: Section,
1553}
1554
1555#[derive(Clone, Copy, Debug, Eq, PartialEq)]
1556struct Section {
1557    offset: usize,
1558    len: usize,
1559}
1560
1561#[derive(Clone, Copy, Debug)]
1562struct EncodedLayout {
1563    states: Section,
1564    transitions: Section,
1565    sets: Section,
1566    intervals: Section,
1567    decisions: Section,
1568    rule_starts: Section,
1569    rule_stops: Section,
1570    total_len: usize,
1571}
1572
1573impl EncodedLayout {
1574    fn new(builder: &ParserAtnBuilder) -> Result<Self, ParserAtnError> {
1575        let mut cursor = HEADER_WORDS;
1576        let states = next_section(&mut cursor, builder.states.len(), STATE_WORDS, "states")?;
1577        let transitions = next_section(
1578            &mut cursor,
1579            builder.transitions.len(),
1580            TRANSITION_WORDS,
1581            "transitions",
1582        )?;
1583        let sets = next_section(
1584            &mut cursor,
1585            builder.interval_sets.len(),
1586            SET_WORDS,
1587            "interval sets",
1588        )?;
1589        let intervals = next_section(
1590            &mut cursor,
1591            builder.interval_ranges.len(),
1592            2,
1593            "interval ranges",
1594        )?;
1595        let decisions = next_section(&mut cursor, builder.decisions.len(), 1, "decisions")?;
1596        let rule_starts = next_section(&mut cursor, builder.rule_starts.len(), 1, "rule starts")?;
1597        let rule_stops = next_section(&mut cursor, builder.rule_stops.len(), 1, "rule stops")?;
1598        compact_id("packed parser ATN word", cursor)?;
1599        Ok(Self {
1600            states,
1601            transitions,
1602            sets,
1603            intervals,
1604            decisions,
1605            rule_starts,
1606            rule_stops,
1607            total_len: cursor,
1608        })
1609    }
1610}
1611
1612#[derive(Clone, Debug)]
1613struct StateBuild {
1614    kind: AtnStateKind,
1615    rule_index: u32,
1616    flags: u32,
1617    end_state: u32,
1618    loop_back_state: u32,
1619}
1620
1621#[derive(Clone, Debug)]
1622struct TransitionBuild {
1623    source: AtnStateId,
1624    kind: ParserTransitionKind,
1625    target: AtnStateId,
1626    arg0: u32,
1627    arg1: u32,
1628    arg2: u32,
1629}
1630
1631impl TransitionBuild {
1632    const fn spec(&self) -> ParserTransitionSpec {
1633        let target = self.target.index();
1634        match self.kind {
1635            ParserTransitionKind::Epsilon => ParserTransitionSpec::Epsilon { target },
1636            ParserTransitionKind::Atom => ParserTransitionSpec::Atom {
1637                target,
1638                label: unpack_i32(self.arg0),
1639            },
1640            ParserTransitionKind::Range => ParserTransitionSpec::Range {
1641                target,
1642                start: unpack_i32(self.arg0),
1643                stop: unpack_i32(self.arg1),
1644            },
1645            ParserTransitionKind::Set => ParserTransitionSpec::Set {
1646                target,
1647                set: ParserIntervalSetId(self.arg0),
1648            },
1649            ParserTransitionKind::NotSet => ParserTransitionSpec::NotSet {
1650                target,
1651                set: ParserIntervalSetId(self.arg0),
1652            },
1653            ParserTransitionKind::Wildcard => ParserTransitionSpec::Wildcard { target },
1654            ParserTransitionKind::Rule => ParserTransitionSpec::Rule {
1655                target,
1656                rule_index: self.arg0 as usize,
1657                follow_state: self.arg1 as usize,
1658                precedence: unpack_i32(self.arg2),
1659            },
1660            ParserTransitionKind::Predicate => ParserTransitionSpec::Predicate {
1661                target,
1662                rule_index: self.arg0 as usize,
1663                pred_index: self.arg1 as usize,
1664                context_dependent: self.arg2 != 0,
1665            },
1666            ParserTransitionKind::Action => ParserTransitionSpec::Action {
1667                target,
1668                rule_index: self.arg0 as usize,
1669                action_index: unpack_index(self.arg1),
1670                context_dependent: self.arg2 != 0,
1671            },
1672            ParserTransitionKind::Precedence => ParserTransitionSpec::Precedence {
1673                target,
1674                precedence: unpack_i32(self.arg0),
1675            },
1676        }
1677    }
1678}
1679
1680impl ParserTransitionKind {
1681    const fn is_epsilon(self) -> bool {
1682        matches!(
1683            self,
1684            Self::Epsilon | Self::Rule | Self::Predicate | Self::Action | Self::Precedence
1685        )
1686    }
1687
1688    const fn is_consuming(self) -> bool {
1689        matches!(
1690            self,
1691            Self::Atom | Self::Range | Self::Set | Self::NotSet | Self::Wildcard
1692        )
1693    }
1694
1695    const fn is_semantic(self) -> bool {
1696        matches!(self, Self::Predicate | Self::Action | Self::Precedence)
1697    }
1698}
1699
1700fn validate_packed(words: &[u32]) -> Result<ParserAtnLayout, ParserAtnError> {
1701    validate_header(words)?;
1702    let layout = read_layout(words)?;
1703    validate_sections(words, layout)?;
1704    validate_states(words, layout)?;
1705    validate_transitions(words, layout)?;
1706    validate_state_flags(words, layout)?;
1707    validate_sets(words, layout)?;
1708    validate_side_tables(words, layout)?;
1709    Ok(layout)
1710}
1711
1712fn validate_header(words: &[u32]) -> Result<(), ParserAtnError> {
1713    if words.len() < HEADER_WORDS {
1714        return Err(ParserAtnError::InvalidData(format!(
1715            "header has {} words; expected at least {HEADER_WORDS}",
1716            words.len()
1717        )));
1718    }
1719    if words[HEADER_MAGIC] != PARSER_ATN_MAGIC {
1720        return Err(ParserAtnError::InvalidData(format!(
1721            "magic 0x{:08x}; expected 0x{PARSER_ATN_MAGIC:08x}",
1722            words[HEADER_MAGIC]
1723        )));
1724    }
1725    let version = words[HEADER_VERSION];
1726    if !(PARSER_ATN_MIN_FORMAT_VERSION..=PARSER_ATN_MAX_FORMAT_VERSION).contains(&version) {
1727        return Err(ParserAtnError::UnsupportedVersion {
1728            found: version,
1729            minimum: PARSER_ATN_MIN_FORMAT_VERSION,
1730            maximum: PARSER_ATN_MAX_FORMAT_VERSION,
1731        });
1732    }
1733    if words[HEADER_BYTE_ORDER] != PARSER_ATN_BYTE_ORDER {
1734        return Err(ParserAtnError::InvalidData(format!(
1735            "byte-order marker 0x{:08x}; expected 0x{PARSER_ATN_BYTE_ORDER:08x}",
1736            words[HEADER_BYTE_ORDER]
1737        )));
1738    }
1739    if words[HEADER_SIZE] as usize != HEADER_WORDS {
1740        return Err(ParserAtnError::InvalidData(format!(
1741            "header length {}; expected {HEADER_WORDS}",
1742            words[HEADER_SIZE]
1743        )));
1744    }
1745    if words[HEADER_TOTAL_LEN] as usize != words.len() {
1746        return Err(ParserAtnError::InvalidData(format!(
1747            "declared total length {} does not match {} words",
1748            words[HEADER_TOTAL_LEN],
1749            words.len()
1750        )));
1751    }
1752    Ok(())
1753}
1754
1755fn read_layout(words: &[u32]) -> Result<ParserAtnLayout, ParserAtnError> {
1756    let states = read_section(words, HEADER_STATES_OFFSET)?;
1757    let transitions = read_section(words, HEADER_TRANSITIONS_OFFSET)?;
1758    let sets = read_section(words, HEADER_SETS_OFFSET)?;
1759    let intervals = read_section(words, HEADER_INTERVALS_OFFSET)?;
1760    let decisions = read_section(words, HEADER_DECISIONS_OFFSET)?;
1761    let rule_starts = read_section(words, HEADER_RULE_STARTS_OFFSET)?;
1762    let rule_stops = read_section(words, HEADER_RULE_STOPS_OFFSET)?;
1763    let state_count = words[HEADER_STATE_COUNT] as usize;
1764    let transition_count = words[HEADER_TRANSITION_COUNT] as usize;
1765    expect_section_len("states", states, state_count, STATE_WORDS)?;
1766    expect_section_len(
1767        "transitions",
1768        transitions,
1769        transition_count,
1770        TRANSITION_WORDS,
1771    )?;
1772    expect_section_len(
1773        "interval sets",
1774        sets,
1775        words[HEADER_SET_COUNT] as usize,
1776        SET_WORDS,
1777    )?;
1778    expect_section_len(
1779        "intervals",
1780        intervals,
1781        words[HEADER_INTERVAL_COUNT] as usize,
1782        2,
1783    )?;
1784    expect_section_len(
1785        "decisions",
1786        decisions,
1787        words[HEADER_DECISION_COUNT] as usize,
1788        1,
1789    )?;
1790    expect_section_len(
1791        "rule starts",
1792        rule_starts,
1793        words[HEADER_RULE_COUNT] as usize,
1794        1,
1795    )?;
1796    expect_section_len(
1797        "rule stops",
1798        rule_stops,
1799        words[HEADER_RULE_COUNT] as usize,
1800        1,
1801    )?;
1802    Ok(ParserAtnLayout {
1803        max_token_type: unpack_i32(words[HEADER_MAX_TOKEN_TYPE]),
1804        state_count,
1805        transition_count,
1806        states,
1807        transitions,
1808        sets,
1809        intervals,
1810        decisions,
1811        rule_starts,
1812        rule_stops,
1813    })
1814}
1815
1816fn validate_sections(words: &[u32], layout: ParserAtnLayout) -> Result<(), ParserAtnError> {
1817    let sections = [
1818        ("states", layout.states),
1819        ("transitions", layout.transitions),
1820        ("sets", layout.sets),
1821        ("intervals", layout.intervals),
1822        ("decisions", layout.decisions),
1823        ("rule starts", layout.rule_starts),
1824        ("rule stops", layout.rule_stops),
1825    ];
1826    let mut expected_offset = HEADER_WORDS;
1827    for (name, section) in sections {
1828        if section.offset != expected_offset {
1829            return Err(ParserAtnError::InvalidData(format!(
1830                "{name} section starts at {}, expected {expected_offset}",
1831                section.offset
1832            )));
1833        }
1834        expected_offset = section_end(section, words.len(), name)?;
1835    }
1836    if expected_offset != words.len() {
1837        return Err(ParserAtnError::InvalidData(format!(
1838            "sections end at {expected_offset}, stream ends at {}",
1839            words.len()
1840        )));
1841    }
1842    Ok(())
1843}
1844
1845fn validate_states(words: &[u32], layout: ParserAtnLayout) -> Result<(), ParserAtnError> {
1846    let mut transition_cursor = 0;
1847    for state in 0..layout.state_count {
1848        let base = layout.states.offset + state * STATE_WORDS;
1849        decode_state_kind(words[base])?;
1850        let flags = words[base + 2];
1851        if flags & !STATE_FLAGS != 0 {
1852            return Err(ParserAtnError::InvalidData(format!(
1853                "state {state} has unknown flags 0x{:x}",
1854                flags & !STATE_FLAGS
1855            )));
1856        }
1857        validate_optional_index(words[base + 1], layout.rule_starts.len, "state rule index")?;
1858        let transition_start = words[base + 3] as usize;
1859        if transition_start != transition_cursor {
1860            return Err(ParserAtnError::InvalidData(format!(
1861                "state {state} transition range starts at {transition_start}, expected {transition_cursor}"
1862            )));
1863        }
1864        validate_range(
1865            words[base + 3],
1866            words[base + 4],
1867            layout.transition_count,
1868            "state transition",
1869        )?;
1870        transition_cursor += words[base + 4] as usize;
1871        validate_optional_index(words[base + 5], layout.state_count, "block end state")?;
1872        validate_optional_index(words[base + 6], layout.state_count, "loop back state")?;
1873    }
1874    if transition_cursor != layout.transition_count {
1875        return Err(ParserAtnError::InvalidData(format!(
1876            "state transition ranges cover {transition_cursor} transitions; expected {}",
1877            layout.transition_count
1878        )));
1879    }
1880    Ok(())
1881}
1882
1883fn validate_transitions(words: &[u32], layout: ParserAtnLayout) -> Result<(), ParserAtnError> {
1884    for transition in 0..layout.transition_count {
1885        let base = layout.transitions.offset + transition * TRANSITION_WORDS;
1886        let kind = decode_transition_kind(words[base])?;
1887        validate_index(words[base + 1], layout.state_count, "transition target")?;
1888        match kind {
1889            ParserTransitionKind::Range => {
1890                let start = unpack_i32(words[base + 2]);
1891                let stop = unpack_i32(words[base + 3]);
1892                if start > stop {
1893                    return Err(ParserAtnError::InvalidData(format!(
1894                        "transition {transition} range starts at {start} after stop {stop}"
1895                    )));
1896                }
1897            }
1898            ParserTransitionKind::Set | ParserTransitionKind::NotSet => {
1899                validate_index(words[base + 2], layout.sets.len / SET_WORDS, "interval set")?;
1900            }
1901            ParserTransitionKind::Rule => {
1902                validate_index(words[base + 2], layout.rule_starts.len, "rule index")?;
1903                validate_index(words[base + 3], layout.state_count, "rule follow state")?;
1904            }
1905            ParserTransitionKind::Predicate => {
1906                validate_index(words[base + 2], layout.rule_starts.len, "predicate rule")?;
1907                validate_bool(words[base + 4], "predicate context-dependent flag")?;
1908            }
1909            ParserTransitionKind::Action => {
1910                validate_index(words[base + 2], layout.rule_starts.len, "action rule")?;
1911                validate_bool(words[base + 4], "action context-dependent flag")?;
1912            }
1913            ParserTransitionKind::Epsilon
1914            | ParserTransitionKind::Atom
1915            | ParserTransitionKind::Wildcard
1916            | ParserTransitionKind::Precedence => {}
1917        }
1918    }
1919    Ok(())
1920}
1921
1922fn validate_state_flags(words: &[u32], layout: ParserAtnLayout) -> Result<(), ParserAtnError> {
1923    for state in 0..layout.state_count {
1924        let base = layout.states.offset + state * STATE_WORDS;
1925        let kind = decode_state_kind(words[base])?;
1926        let start = words[base + 3] as usize;
1927        let len = words[base + 4] as usize;
1928        let mut all_epsilon = len != 0;
1929        let mut has_consuming = false;
1930        let mut has_semantic = false;
1931        for transition in start..start + len {
1932            let base = layout.transitions.offset + transition * TRANSITION_WORDS;
1933            let kind = decode_transition_kind(words[base])
1934                .expect("packed parser transition kind was already validated");
1935            all_epsilon &= kind.is_epsilon();
1936            has_consuming |= kind.is_consuming();
1937            has_semantic |= kind.is_semantic();
1938        }
1939        let mut expected = u32::from(kind == AtnStateKind::RuleStop) * FLAG_RULE_STOP;
1940        expected |= u32::from(all_epsilon) * FLAG_EPSILON_ONLY;
1941        expected |= u32::from(has_consuming) * FLAG_HAS_CONSUMING;
1942        expected |= u32::from(has_semantic) * FLAG_HAS_SEMANTIC;
1943        let derived = words[base + 2]
1944            & (FLAG_EPSILON_ONLY | FLAG_RULE_STOP | FLAG_HAS_CONSUMING | FLAG_HAS_SEMANTIC);
1945        if derived != expected {
1946            return Err(ParserAtnError::InvalidData(format!(
1947                "state {state} has inconsistent precomputed flags 0x{derived:x}; expected 0x{expected:x}"
1948            )));
1949        }
1950    }
1951    Ok(())
1952}
1953
1954fn validate_sets(words: &[u32], layout: ParserAtnLayout) -> Result<(), ParserAtnError> {
1955    for set in 0..layout.sets.len / SET_WORDS {
1956        let base = layout.sets.offset + set * SET_WORDS;
1957        validate_range(
1958            words[base],
1959            words[base + 1],
1960            layout.intervals.len / 2,
1961            "interval set",
1962        )?;
1963        let start = words[base] as usize;
1964        let len = words[base + 1] as usize;
1965        let mut previous_stop: Option<i32> = None;
1966        for interval in start..start + len {
1967            let interval_base = layout.intervals.offset + interval * 2;
1968            let range_start = unpack_i32(words[interval_base]);
1969            let range_stop = unpack_i32(words[interval_base + 1]);
1970            if range_start > range_stop {
1971                return Err(ParserAtnError::InvalidData(format!(
1972                    "interval {interval} starts at {range_start} after stop {range_stop}"
1973                )));
1974            }
1975            if previous_stop.is_some_and(|stop| range_start <= stop.saturating_add(1)) {
1976                return Err(ParserAtnError::InvalidData(format!(
1977                    "interval set {set} is not sorted and coalesced"
1978                )));
1979            }
1980            previous_stop = Some(range_stop);
1981        }
1982    }
1983    Ok(())
1984}
1985
1986fn validate_side_tables(words: &[u32], layout: ParserAtnLayout) -> Result<(), ParserAtnError> {
1987    for (name, section) in [
1988        ("decision state", layout.decisions),
1989        ("rule start state", layout.rule_starts),
1990        ("rule stop state", layout.rule_stops),
1991    ] {
1992        for &state in &words[section.offset..section.offset + section.len] {
1993            validate_index(state, layout.state_count, name)?;
1994        }
1995    }
1996    Ok(())
1997}
1998
1999#[inline(always)]
2000fn decode_state_kind(value: u32) -> Result<AtnStateKind, ParserAtnError> {
2001    let kind = match value {
2002        0 => AtnStateKind::Invalid,
2003        1 => AtnStateKind::Basic,
2004        2 => AtnStateKind::RuleStart,
2005        3 => AtnStateKind::BlockStart,
2006        4 => AtnStateKind::PlusBlockStart,
2007        5 => AtnStateKind::StarBlockStart,
2008        6 => AtnStateKind::TokenStart,
2009        7 => AtnStateKind::RuleStop,
2010        8 => AtnStateKind::BlockEnd,
2011        9 => AtnStateKind::StarLoopBack,
2012        10 => AtnStateKind::StarLoopEntry,
2013        11 => AtnStateKind::PlusLoopBack,
2014        12 => AtnStateKind::LoopEnd,
2015        other => {
2016            return Err(ParserAtnError::InvalidData(format!(
2017                "parser ATN state kind {other}"
2018            )));
2019        }
2020    };
2021    Ok(kind)
2022}
2023
2024#[inline(always)]
2025fn decode_transition_kind(value: u32) -> Result<ParserTransitionKind, ParserAtnError> {
2026    let kind = match value {
2027        1 => ParserTransitionKind::Epsilon,
2028        2 => ParserTransitionKind::Range,
2029        3 => ParserTransitionKind::Rule,
2030        4 => ParserTransitionKind::Predicate,
2031        5 => ParserTransitionKind::Atom,
2032        6 => ParserTransitionKind::Action,
2033        7 => ParserTransitionKind::Set,
2034        8 => ParserTransitionKind::NotSet,
2035        9 => ParserTransitionKind::Wildcard,
2036        10 => ParserTransitionKind::Precedence,
2037        other => {
2038            return Err(ParserAtnError::InvalidData(format!(
2039                "parser ATN transition kind {other}"
2040            )));
2041        }
2042    };
2043    Ok(kind)
2044}
2045
2046const fn state_kind_word(kind: AtnStateKind) -> u32 {
2047    match kind {
2048        AtnStateKind::Invalid => 0,
2049        AtnStateKind::Basic => 1,
2050        AtnStateKind::RuleStart => 2,
2051        AtnStateKind::BlockStart => 3,
2052        AtnStateKind::PlusBlockStart => 4,
2053        AtnStateKind::StarBlockStart => 5,
2054        AtnStateKind::TokenStart => 6,
2055        AtnStateKind::RuleStop => 7,
2056        AtnStateKind::BlockEnd => 8,
2057        AtnStateKind::StarLoopBack => 9,
2058        AtnStateKind::StarLoopEntry => 10,
2059        AtnStateKind::PlusLoopBack => 11,
2060        AtnStateKind::LoopEnd => 12,
2061    }
2062}
2063
2064fn compact_id(field: &'static str, value: usize) -> Result<u32, ParserAtnError> {
2065    u32::try_from(value).map_err(|_| ParserAtnError::Overflow { field, value })
2066}
2067
2068fn pack_optional_index(field: &'static str, value: Option<usize>) -> Result<u32, ParserAtnError> {
2069    match value {
2070        Some(value) => {
2071            let compact = compact_id(field, value)?;
2072            if compact == NO_INDEX {
2073                return Err(ParserAtnError::Overflow { field, value });
2074            }
2075            Ok(compact)
2076        }
2077        None => Ok(NO_INDEX),
2078    }
2079}
2080
2081const fn unpack_index(value: u32) -> Option<usize> {
2082    if value == NO_INDEX {
2083        None
2084    } else {
2085        Some(value as usize)
2086    }
2087}
2088
2089const fn pack_i32(value: i32) -> u32 {
2090    u32::from_le_bytes(value.to_le_bytes())
2091}
2092
2093const fn unpack_i32(value: u32) -> i32 {
2094    i32::from_le_bytes(value.to_le_bytes())
2095}
2096
2097fn normalize_ranges(ranges: impl IntoIterator<Item = (i32, i32)>) -> Vec<(i32, i32)> {
2098    let mut ranges = ranges
2099        .into_iter()
2100        .map(|(start, stop)| {
2101            if start <= stop {
2102                (start, stop)
2103            } else {
2104                (stop, start)
2105            }
2106        })
2107        .collect::<Vec<_>>();
2108    ranges.sort_unstable();
2109    let mut normalized: Vec<(i32, i32)> = Vec::with_capacity(ranges.len());
2110    for (start, stop) in ranges {
2111        if let Some((_, previous_stop)) = normalized.last_mut()
2112            && start <= previous_stop.saturating_add(1)
2113        {
2114            *previous_stop = (*previous_stop).max(stop);
2115            continue;
2116        }
2117        normalized.push((start, stop));
2118    }
2119    normalized
2120}
2121
2122fn next_section(
2123    cursor: &mut usize,
2124    count: usize,
2125    width: usize,
2126    name: &str,
2127) -> Result<Section, ParserAtnError> {
2128    let len = count.checked_mul(width).ok_or_else(|| {
2129        ParserAtnError::InvalidData(format!("{name} section length overflows usize"))
2130    })?;
2131    let section = Section {
2132        offset: *cursor,
2133        len,
2134    };
2135    *cursor = cursor.checked_add(len).ok_or_else(|| {
2136        ParserAtnError::InvalidData(format!("{name} section end overflows usize"))
2137    })?;
2138    Ok(section)
2139}
2140
2141fn write_section(
2142    words: &mut [u32],
2143    header_offset: usize,
2144    section: Section,
2145) -> Result<(), ParserAtnError> {
2146    words[header_offset] = compact_id("parser ATN section offset", section.offset)?;
2147    words[header_offset + 1] = compact_id("parser ATN section length", section.len)?;
2148    Ok(())
2149}
2150
2151fn encode_ids(words: &mut [u32], section: Section, ids: &[AtnStateId]) {
2152    for (target, id) in words[section.offset..section.offset + section.len]
2153        .iter_mut()
2154        .zip(ids)
2155    {
2156        *target = id.raw();
2157    }
2158}
2159
2160fn read_section(words: &[u32], header_offset: usize) -> Result<Section, ParserAtnError> {
2161    let offset = words[header_offset] as usize;
2162    let len = words[header_offset + 1] as usize;
2163    section_end(Section { offset, len }, words.len(), "declared")?;
2164    Ok(Section { offset, len })
2165}
2166
2167fn section_end(section: Section, total: usize, name: &str) -> Result<usize, ParserAtnError> {
2168    let end = section.offset.checked_add(section.len).ok_or_else(|| {
2169        ParserAtnError::InvalidData(format!("{name} section offset arithmetic overflow"))
2170    })?;
2171    if end > total {
2172        return Err(ParserAtnError::InvalidData(format!(
2173            "{name} section {0}..{end} exceeds stream length {total}",
2174            section.offset
2175        )));
2176    }
2177    Ok(end)
2178}
2179
2180fn expect_section_len(
2181    name: &str,
2182    section: Section,
2183    count: usize,
2184    width: usize,
2185) -> Result<(), ParserAtnError> {
2186    let expected = count.checked_mul(width).ok_or_else(|| {
2187        ParserAtnError::InvalidData(format!("{name} count/width multiplication overflow"))
2188    })?;
2189    if section.len != expected {
2190        return Err(ParserAtnError::InvalidData(format!(
2191            "{name} section has {} words; expected {expected}",
2192            section.len
2193        )));
2194    }
2195    Ok(())
2196}
2197
2198fn validate_index(value: u32, count: usize, name: &str) -> Result<(), ParserAtnError> {
2199    if value as usize >= count {
2200        return Err(ParserAtnError::InvalidData(format!(
2201            "{name} {value} outside 0..{count}"
2202        )));
2203    }
2204    Ok(())
2205}
2206
2207fn validate_optional_index(value: u32, count: usize, name: &str) -> Result<(), ParserAtnError> {
2208    if value == NO_INDEX {
2209        return Ok(());
2210    }
2211    validate_index(value, count, name)
2212}
2213
2214fn validate_bool(value: u32, name: &str) -> Result<(), ParserAtnError> {
2215    if value > 1 {
2216        return Err(ParserAtnError::InvalidData(format!(
2217            "{name} is {value}; expected 0 or 1"
2218        )));
2219    }
2220    Ok(())
2221}
2222
2223fn validate_range(start: u32, len: u32, count: usize, name: &str) -> Result<(), ParserAtnError> {
2224    let start = start as usize;
2225    let len = len as usize;
2226    let end = start
2227        .checked_add(len)
2228        .ok_or_else(|| ParserAtnError::InvalidData(format!("{name} range arithmetic overflow")))?;
2229    if end > count {
2230        return Err(ParserAtnError::InvalidData(format!(
2231            "{name} range {start}..{end} exceeds count {count}"
2232        )));
2233    }
2234    Ok(())
2235}
2236
2237#[cfg(test)]
2238mod tests {
2239    use super::*;
2240
2241    fn sample_atn() -> ParserAtn {
2242        let mut builder = ParserAtnBuilder::new(9);
2243        builder
2244            .add_state(AtnStateKind::RuleStart, Some(0))
2245            .expect("rule start");
2246        builder
2247            .add_state(AtnStateKind::RuleStop, Some(0))
2248            .expect("rule stop");
2249        builder
2250            .set_rule_to_start_state(vec![0])
2251            .expect("rule starts");
2252        builder.set_rule_to_stop_state(vec![1]).expect("rule stops");
2253        builder.add_decision_state(0).expect("decision");
2254        builder
2255            .add_transition(
2256                0,
2257                ParserTransitionSpec::Atom {
2258                    target: 1,
2259                    label: 7,
2260                },
2261            )
2262            .expect("transition");
2263        builder.finish().expect("packed parser ATN")
2264    }
2265
2266    #[test]
2267    fn packed_views_preserve_state_and_transition_semantics() {
2268        let atn = sample_atn();
2269        let start = atn.state(0).expect("start");
2270        assert_eq!(start.kind(), AtnStateKind::RuleStart);
2271        assert_eq!(start.rule_index(), Some(0));
2272        assert!(start.has_consuming_transition());
2273        let transition = start.transitions().first().expect("transition");
2274        assert_eq!(
2275            transition.data(),
2276            ParserTransitionData::Atom {
2277                target: 1,
2278                label: 7
2279            }
2280        );
2281        assert!(transition.matches(7, 1, 9));
2282        assert!(!transition.matches(8, 1, 9));
2283        assert_eq!(atn.rule_to_stop_state().get(0), Some(1));
2284    }
2285
2286    #[test]
2287    fn static_format_is_allocation_free_and_version_checked() {
2288        let atn = sample_atn();
2289        let words = Box::leak(atn.packed_words().to_vec().into_boxed_slice());
2290        let borrowed = ParserAtn::from_static(words).expect("static packed ATN");
2291        assert!(matches!(borrowed.words, Cow::Borrowed(_)));
2292
2293        let mut wrong_version = words.to_vec();
2294        wrong_version[HEADER_VERSION] = PARSER_ATN_FORMAT_VERSION + 1;
2295        assert_eq!(
2296            ParserAtn::from_owned(wrong_version),
2297            Err(ParserAtnError::UnsupportedVersion {
2298                found: 2,
2299                minimum: 1,
2300                maximum: 1,
2301            })
2302        );
2303    }
2304
2305    #[cfg(target_pointer_width = "64")]
2306    #[test]
2307    fn header_encoding_rejects_values_outside_u32() {
2308        let builder = ParserAtnBuilder::new(0);
2309        let section = Section {
2310            offset: HEADER_WORDS,
2311            len: 0,
2312        };
2313        let mut layout = EncodedLayout {
2314            states: section,
2315            transitions: section,
2316            sets: section,
2317            intervals: section,
2318            decisions: section,
2319            rule_starts: section,
2320            rule_stops: section,
2321            total_len: usize::MAX,
2322        };
2323        let mut words = [0; HEADER_WORDS];
2324
2325        assert_eq!(
2326            builder.encode_header(&mut words, layout),
2327            Err(ParserAtnError::Overflow {
2328                field: "packed parser ATN word",
2329                value: usize::MAX,
2330            })
2331        );
2332
2333        layout.states.offset = usize::MAX;
2334        layout.total_len = HEADER_WORDS;
2335        assert_eq!(
2336            builder.encode_header(&mut words, layout),
2337            Err(ParserAtnError::Overflow {
2338                field: "parser ATN section offset",
2339                value: usize::MAX,
2340            })
2341        );
2342    }
2343
2344    #[test]
2345    fn rejects_invalid_header_and_section_layout() {
2346        let atn = sample_atn();
2347        let cases = [
2348            (HEADER_MAGIC, 0, "magic"),
2349            (HEADER_BYTE_ORDER, 0x0403_0201, "byte-order marker"),
2350            (HEADER_SIZE, 0, "header length"),
2351            (HEADER_STATES_OFFSET, 0, "states section starts"),
2352            (HEADER_STATES_OFFSET + 1, 0, "states section has 0 words"),
2353            (HEADER_TOTAL_LEN, 0, "declared total length"),
2354        ];
2355        for (word, value, expected) in cases {
2356            let mut words = atn.packed_words().to_vec();
2357            words[word] = value;
2358            let error = ParserAtn::from_owned(words).expect_err("invalid format must fail");
2359            assert!(
2360                error.to_string().contains(expected),
2361                "{error} did not contain {expected:?}"
2362            );
2363        }
2364    }
2365
2366    #[test]
2367    fn rejects_non_contiguous_state_transition_ranges() {
2368        let atn = sample_atn();
2369        let mut words = atn.packed_words().to_vec();
2370        let second_state = atn.layout.states.offset + STATE_WORDS;
2371        words[second_state + 3] = 0;
2372        let error = ParserAtn::from_owned(words).expect_err("overlapping ranges must fail");
2373        assert!(error.to_string().contains("transition range starts"));
2374    }
2375
2376    #[test]
2377    fn interval_sets_share_one_range_pool() {
2378        let mut builder = ParserAtnBuilder::new(20);
2379        builder
2380            .add_state(AtnStateKind::RuleStart, Some(0))
2381            .expect("start");
2382        builder
2383            .add_state(AtnStateKind::RuleStop, Some(0))
2384            .expect("stop");
2385        builder
2386            .set_rule_to_start_state(vec![0])
2387            .expect("rule starts");
2388        builder.set_rule_to_stop_state(vec![1]).expect("rule stops");
2389        let set = builder
2390            .add_interval_set([(2, 4), (4, 8), (10, 10)])
2391            .expect("set");
2392        builder
2393            .add_transition(0, ParserTransitionSpec::Set { target: 1, set })
2394            .expect("set transition");
2395        let atn = builder.finish().expect("ATN");
2396        let transition = atn
2397            .state(0)
2398            .expect("start")
2399            .transitions()
2400            .first()
2401            .expect("transition");
2402        let ParserTransitionData::Set { set, .. } = transition.data() else {
2403            panic!("expected set transition");
2404        };
2405        assert_eq!(set.ranges().collect::<Vec<_>>(), vec![(2, 8), (10, 10)]);
2406        assert!(set.contains(7));
2407        assert!(!set.contains(9));
2408        assert_eq!(atn.stats().interval_ranges, 2);
2409    }
2410
2411    #[test]
2412    fn rejects_out_of_range_transition_target() {
2413        let atn = sample_atn();
2414        let mut words = atn.packed_words().to_vec();
2415        let target = atn.layout.transitions.offset + 1;
2416        words[target] = 99;
2417        assert!(matches!(
2418            ParserAtn::from_owned(words),
2419            Err(ParserAtnError::InvalidData(message))
2420                if message.contains("transition target")
2421        ));
2422    }
2423
2424    #[test]
2425    fn eof_interval_is_preserved_as_signed_data() {
2426        let mut builder = ParserAtnBuilder::new(3);
2427        builder
2428            .add_state(AtnStateKind::RuleStart, Some(0))
2429            .expect("start");
2430        builder
2431            .add_state(AtnStateKind::RuleStop, Some(0))
2432            .expect("stop");
2433        builder
2434            .set_rule_to_start_state(vec![0])
2435            .expect("rule starts");
2436        builder.set_rule_to_stop_state(vec![1]).expect("rule stops");
2437        let set = builder
2438            .add_interval_set([(TOKEN_EOF, TOKEN_EOF)])
2439            .expect("set");
2440        builder
2441            .add_transition(0, ParserTransitionSpec::Set { target: 1, set })
2442            .expect("transition");
2443        let atn = builder.finish().expect("ATN");
2444        let transition = atn
2445            .state(0)
2446            .expect("start")
2447            .transitions()
2448            .first()
2449            .expect("transition");
2450        assert!(transition.matches(TOKEN_EOF, 1, 3));
2451    }
2452}