1#![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#[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#[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#[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#[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#[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
164pub 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 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 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 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 pub fn packed_words(&self) -> &[u32] {
292 &self.words
293 }
294
295 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 unsafe { *((self.words_address as *const u32).add(index)) }
343 }
344}
345
346#[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 unsafe { *((self.record_address as *const u32).add(field)) }
462 }
463}
464
465#[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#[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#[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 unsafe { *((self.record_address as *const u32).add(field)) }
735 }
736}
737
738#[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#[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#[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#[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#[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#[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#[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#[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#[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}