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