Skip to main content

antlr4_runtime/atn/
serialized.rs

1// SPDX-License-Identifier: BSD-3-Clause
2// Copyright (c) 2026 Konstantin Vyatkin
3use std::borrow::Cow;
4
5use crate::atn::parser_atn::{
6    ParserAtn, ParserAtnBuilder, ParserAtnError, ParserIntervalSetId, ParserTransitionSpec,
7};
8use crate::atn::{
9    AtnStateKind, IntervalSet, LexerAction, LexerAtn, LexerAtnState, LexerTransition,
10};
11use crate::errors::AntlrError;
12use crate::token::TOKEN_EOF;
13
14pub const SERIALIZED_VERSION: i32 = 4;
15
16/// Raw integer form of an ANTLR v4 serialized ATN.
17///
18/// ANTLR targets commonly embed this data as strings or integer arrays. The
19/// Rust generator emits integer arrays from its compiled lexer artifact, while
20/// `from_chars` supports targets that encode ATN values in string literals.
21#[derive(Clone, Debug)]
22pub struct SerializedAtn<'a> {
23    values: Cow<'a, [i32]>,
24}
25
26impl<'a> SerializedAtn<'a> {
27    /// Creates serialized ATN data from an already-decoded integer array.
28    pub const fn from_i32(values: &'a [i32]) -> Self {
29        Self {
30            values: Cow::Borrowed(values),
31        }
32    }
33
34    /// Creates serialized ATN data by widening each character to its scalar
35    /// value.
36    ///
37    /// This is useful for ANTLR targets that store serialized ATN data in
38    /// string fragments. Java-style 16-bit word decoding is not applied here;
39    /// callers should pass already-decoded characters for now.
40    pub fn from_chars(chars: impl IntoIterator<Item = char>) -> SerializedAtn<'static> {
41        SerializedAtn {
42            values: Cow::Owned(chars.into_iter().map(|ch| ch as i32).collect()),
43        }
44    }
45
46    pub fn values(&self) -> &[i32] {
47        &self.values
48    }
49}
50
51/// Cursor-based decoder for ANTLR v4 serialized ATN data.
52#[derive(Debug)]
53pub struct AtnDeserializer<'a> {
54    values: &'a [i32],
55    cursor: usize,
56}
57
58impl<'a> AtnDeserializer<'a> {
59    /// Creates a deserializer over immutable serialized ATN storage.
60    pub fn new(serialized: &'a SerializedAtn<'_>) -> Self {
61        Self {
62            values: serialized.values(),
63            cursor: 0,
64        }
65    }
66
67    /// Decodes an ANTLR v4 serialized lexer ATN into the lexer graph.
68    ///
69    /// The layout is order-sensitive: states come first, followed by non-greedy
70    /// and precedence markers, rule tables, mode starts, interval sets, edges,
71    /// decisions, and lexer actions. This method keeps ANTLR's side tables as
72    /// explicit vectors because lexer simulation needs them without depending
73    /// on generated per-rule code. Parser input is rejected; use
74    /// [`Self::deserialize_parser`] for the packed parser representation.
75    pub fn deserialize(mut self) -> Result<LexerAtn, AntlrError> {
76        let version = self.read("version")?;
77        if version != SERIALIZED_VERSION {
78            return Err(AntlrError::Unsupported(format!(
79                "serialized ATN version {version}; expected {SERIALIZED_VERSION}"
80            )));
81        }
82
83        match self.read("grammar type")? {
84            0 => {}
85            1 => {
86                return Err(AntlrError::Unsupported(
87                    "parser ATNs require AtnDeserializer::deserialize_parser()".to_owned(),
88                ));
89            }
90            other => {
91                return Err(AntlrError::Unsupported(format!(
92                    "serialized ATN grammar type {other}"
93                )));
94            }
95        }
96        let max_token_type = self.read("max token type")?;
97        let mut atn = LexerAtn::new(max_token_type);
98
99        self.deserialize_states(&mut atn)?;
100        self.deserialize_non_greedy_states(&mut atn)?;
101        self.deserialize_precedence_states(&mut atn)?;
102        self.deserialize_rules(&mut atn)?;
103        self.deserialize_modes(&mut atn)?;
104        let sets = self.deserialize_sets()?;
105        self.deserialize_edges(&mut atn, &sets)?;
106        self.deserialize_decisions(&mut atn)?;
107        self.deserialize_lexer_actions(&mut atn)?;
108        mark_precedence_decisions(&mut atn);
109
110        Ok(atn)
111    }
112
113    /// Decodes parser metadata directly into the packed parser-only runtime
114    /// representation.
115    ///
116    /// No lexer object graph is constructed. Temporary state and edge records
117    /// live in centralized builder vectors, then become one validated
118    /// index-addressed word stream.
119    pub fn deserialize_parser(mut self) -> Result<ParserAtn, AntlrError> {
120        self.deserialize_parser_header()?;
121        let max_token_type = self.read("max token type")?;
122        let mut builder = ParserAtnBuilder::new(max_token_type);
123        self.deserialize_parser_states(&mut builder)?;
124        self.deserialize_parser_flags(&mut builder)?;
125        self.deserialize_parser_rules(&mut builder)?;
126        self.deserialize_parser_modes(&builder)?;
127        let sets = self.deserialize_parser_sets(&mut builder)?;
128        self.deserialize_parser_edges(&mut builder, &sets)?;
129        self.deserialize_parser_decisions(&mut builder)?;
130        if self.cursor != self.values.len() {
131            return Err(AntlrError::Unsupported(format!(
132                "serialized parser ATN has {} trailing values",
133                self.values.len() - self.cursor
134            )));
135        }
136        builder.finish().map_err(|error| parser_atn_error(&error))
137    }
138
139    fn deserialize_parser_header(&mut self) -> Result<(), AntlrError> {
140        let version = self.read("version")?;
141        if version != SERIALIZED_VERSION {
142            return Err(AntlrError::Unsupported(format!(
143                "serialized ATN version {version}; expected {SERIALIZED_VERSION}"
144            )));
145        }
146        let grammar_type = self.read("grammar type")?;
147        if grammar_type != 1 {
148            return Err(AntlrError::Unsupported(format!(
149                "serialized parser ATN has grammar type {grammar_type}; expected 1"
150            )));
151        }
152        Ok(())
153    }
154
155    fn deserialize_parser_states(
156        &mut self,
157        builder: &mut ParserAtnBuilder,
158    ) -> Result<(), AntlrError> {
159        let state_count = self.read_usize("state count")?;
160        let mut end_states = Vec::new();
161        let mut loop_back_states = Vec::new();
162        for _ in 0..state_count {
163            let kind = decode_state_kind(self.read("state type")?)?;
164            if kind == AtnStateKind::Invalid {
165                builder
166                    .add_state(kind, None)
167                    .map_err(|error| parser_atn_error(&error))?;
168                continue;
169            }
170            let raw_rule_index = self.read("rule index")?;
171            let rule_index = (raw_rule_index >= 0)
172                .then(|| read_index(raw_rule_index, "state rule index"))
173                .transpose()?;
174            let state = builder
175                .add_state(kind, rule_index)
176                .map_err(|error| parser_atn_error(&error))?
177                .index();
178            match kind {
179                AtnStateKind::LoopEnd => {
180                    let target = self.read_usize("loop back state")?;
181                    loop_back_states.push((state, target));
182                }
183                AtnStateKind::BlockStart
184                | AtnStateKind::PlusBlockStart
185                | AtnStateKind::StarBlockStart => {
186                    let target = self.read_usize("block end state")?;
187                    end_states.push((state, target));
188                }
189                _ => {}
190            }
191        }
192        for (state, target) in end_states {
193            builder
194                .set_end_state(state, target)
195                .map_err(|error| parser_atn_error(&error))?;
196        }
197        for (state, target) in loop_back_states {
198            builder
199                .set_loop_back_state(state, target)
200                .map_err(|error| parser_atn_error(&error))?;
201        }
202        Ok(())
203    }
204
205    fn deserialize_parser_flags(
206        &mut self,
207        builder: &mut ParserAtnBuilder,
208    ) -> Result<(), AntlrError> {
209        let non_greedy_count = self.read_usize("non-greedy state count")?;
210        for _ in 0..non_greedy_count {
211            let state = self.read_usize("non-greedy state")?;
212            builder
213                .set_non_greedy(state)
214                .map_err(|error| parser_atn_error(&error))?;
215        }
216        let precedence_count = self.read_usize("precedence state count")?;
217        for _ in 0..precedence_count {
218            let state = self.read_usize("precedence state")?;
219            builder
220                .set_left_recursive_rule(state)
221                .map_err(|error| parser_atn_error(&error))?;
222        }
223        Ok(())
224    }
225
226    fn deserialize_parser_rules(
227        &mut self,
228        builder: &mut ParserAtnBuilder,
229    ) -> Result<(), AntlrError> {
230        let rule_count = self.read_usize("rule count")?;
231        let mut starts = Vec::with_capacity(rule_count);
232        for _ in 0..rule_count {
233            starts.push(self.read_usize("rule start state")?);
234        }
235        let mut stops = vec![None; rule_count];
236        for state in 0..builder.state_count() {
237            let kind = builder
238                .state_kind(state)
239                .expect("state count bounds builder state lookup");
240            if kind != AtnStateKind::RuleStop {
241                continue;
242            }
243            let Some(rule_index) = builder.state_rule_index(state) else {
244                continue;
245            };
246            if let Some(stop) = stops.get_mut(rule_index) {
247                *stop = Some(state);
248            }
249        }
250        let stops = stops
251            .into_iter()
252            .enumerate()
253            .map(|(rule, stop)| {
254                stop.ok_or_else(|| {
255                    AntlrError::Unsupported(format!(
256                        "serialized parser ATN has no stop state for rule {rule}"
257                    ))
258                })
259            })
260            .collect::<Result<Vec<_>, _>>()?;
261        builder
262            .set_rule_to_start_state(starts)
263            .map_err(|error| parser_atn_error(&error))?;
264        builder
265            .set_rule_to_stop_state(stops)
266            .map_err(|error| parser_atn_error(&error))?;
267        Ok(())
268    }
269
270    fn deserialize_parser_modes(&mut self, builder: &ParserAtnBuilder) -> Result<(), AntlrError> {
271        let mode_count = self.read_usize("mode count")?;
272        for _ in 0..mode_count {
273            let state = self.read_usize("mode start state")?;
274            if builder.state_kind(state).is_none() {
275                return Err(AntlrError::Unsupported(format!(
276                    "mode start state {state} outside state list"
277                )));
278            }
279        }
280        Ok(())
281    }
282
283    fn deserialize_parser_sets(
284        &mut self,
285        builder: &mut ParserAtnBuilder,
286    ) -> Result<Vec<ParserIntervalSetId>, AntlrError> {
287        let set_count = self.read_usize("set count")?;
288        let mut sets = Vec::with_capacity(set_count);
289        for _ in 0..set_count {
290            let interval_count = self.read_usize("interval count")?;
291            let contains_eof = self.read("set contains EOF")? != 0;
292            let mut ranges = Vec::with_capacity(interval_count + usize::from(contains_eof));
293            if contains_eof {
294                ranges.push((TOKEN_EOF, TOKEN_EOF));
295            }
296            for _ in 0..interval_count {
297                ranges.push((self.read("interval start")?, self.read("interval stop")?));
298            }
299            sets.push(
300                builder
301                    .add_interval_set(ranges)
302                    .map_err(|error| parser_atn_error(&error))?,
303            );
304        }
305        Ok(sets)
306    }
307
308    fn deserialize_parser_edges(
309        &mut self,
310        builder: &mut ParserAtnBuilder,
311        sets: &[ParserIntervalSetId],
312    ) -> Result<(), AntlrError> {
313        let transition_count = self.read_usize("transition count")?;
314        for _ in 0..transition_count {
315            let source = self.read_usize("transition source")?;
316            let target = self.read_usize("transition target")?;
317            let kind = self.read("transition type")?;
318            let a = self.read("transition arg 1")?;
319            let b = self.read("transition arg 2")?;
320            let c = self.read("transition arg 3")?;
321            let transition = decode_parser_transition(target, kind, a, b, c, sets)?;
322            builder
323                .add_transition(source, transition)
324                .map_err(|error| parser_atn_error(&error))?;
325        }
326        add_parser_rule_return_edges(builder)
327    }
328
329    fn deserialize_parser_decisions(
330        &mut self,
331        builder: &mut ParserAtnBuilder,
332    ) -> Result<(), AntlrError> {
333        let decision_count = self.read_usize("decision count")?;
334        for _ in 0..decision_count {
335            let state = self.read_usize("decision state")?;
336            builder
337                .add_decision_state(state)
338                .map_err(|error| parser_atn_error(&error))?;
339        }
340        Ok(())
341    }
342
343    /// Reads all serialized ATN states and preserves state-specific paired
344    /// links such as block end states and loop-back states.
345    fn deserialize_states(&mut self, atn: &mut LexerAtn) -> Result<(), AntlrError> {
346        let state_count = self.read_usize("state count")?;
347        for state_number in 0..state_count {
348            let kind = decode_state_kind(self.read("state type")?)?;
349            if kind == AtnStateKind::Invalid {
350                atn.add_state(LexerAtnState::new(state_number, kind));
351                continue;
352            }
353
354            let rule_index = self.read("rule index")?;
355            let mut state = LexerAtnState::new(state_number, kind);
356            if rule_index >= 0 {
357                let rule_index = usize::try_from(rule_index).map_err(|_| {
358                    AntlrError::Unsupported(format!("rule index cannot be negative: {rule_index}"))
359                })?;
360                state = state.with_rule_index(rule_index);
361            }
362
363            match kind {
364                AtnStateKind::LoopEnd => {
365                    state.loop_back_state = Some(self.read_usize("loop back state")?);
366                }
367                AtnStateKind::BlockStart
368                | AtnStateKind::PlusBlockStart
369                | AtnStateKind::StarBlockStart => {
370                    state.end_state = Some(self.read_usize("block end state")?);
371                }
372                _ => {}
373            }
374
375            atn.add_state(state);
376        }
377        Ok(())
378    }
379
380    /// Marks lexer and parser decision states that ANTLR encoded as
381    /// non-greedy.
382    fn deserialize_non_greedy_states(&mut self, atn: &mut LexerAtn) -> Result<(), AntlrError> {
383        let count = self.read_usize("non-greedy state count")?;
384        for _ in 0..count {
385            let state_number = self.read_usize("non-greedy state")?;
386            let Some(state) = atn.state_mut(state_number) else {
387                return Err(AntlrError::Unsupported(format!(
388                    "non-greedy state {state_number} outside state list"
389                )));
390            };
391            state.non_greedy = true;
392        }
393        Ok(())
394    }
395
396    /// Marks rule-start states that ANTLR generated for left-recursive
397    /// precedence rules.
398    fn deserialize_precedence_states(&mut self, atn: &mut LexerAtn) -> Result<(), AntlrError> {
399        let count = self.read_usize("precedence state count")?;
400        for _ in 0..count {
401            let state_number = self.read_usize("precedence state")?;
402            let Some(state) = atn.state_mut(state_number) else {
403                return Err(AntlrError::Unsupported(format!(
404                    "precedence state {state_number} outside state list"
405                )));
406            };
407            state.left_recursive_rule = true;
408        }
409        Ok(())
410    }
411
412    /// Decodes rule start states, lexer token types, and derived rule stop
413    /// states.
414    fn deserialize_rules(&mut self, atn: &mut LexerAtn) -> Result<(), AntlrError> {
415        let rule_count = self.read_usize("rule count")?;
416        let mut starts = Vec::with_capacity(rule_count);
417        let mut token_types = Vec::new();
418        for _ in 0..rule_count {
419            starts.push(self.read_usize("rule start state")?);
420            token_types.push(self.read("rule token type")?);
421        }
422
423        let mut stops = vec![usize::MAX; rule_count];
424        for state in atn.states() {
425            if state.kind == AtnStateKind::RuleStop {
426                let Some(rule_index) = state.rule_index else {
427                    continue;
428                };
429                if let Some(stop) = stops.get_mut(rule_index) {
430                    *stop = state.state_number;
431                }
432            }
433        }
434
435        atn.set_rule_to_start_state(starts);
436        atn.set_rule_to_stop_state(stops);
437        atn.set_rule_to_token_type(token_types);
438        Ok(())
439    }
440
441    /// Decodes lexer mode entry states.
442    fn deserialize_modes(&mut self, atn: &mut LexerAtn) -> Result<(), AntlrError> {
443        let mode_count = self.read_usize("mode count")?;
444        for _ in 0..mode_count {
445            atn.add_mode_start_state(self.read_usize("mode start state")?);
446        }
447        Ok(())
448    }
449
450    /// Decodes all interval sets referenced by `SET` and `NOT_SET`
451    /// transitions.
452    fn deserialize_sets(&mut self) -> Result<Vec<IntervalSet>, AntlrError> {
453        let set_count = self.read_usize("set count")?;
454        let mut sets = Vec::with_capacity(set_count);
455        for _ in 0..set_count {
456            let interval_count = self.read_usize("interval count")?;
457            let mut set = IntervalSet::new();
458            let contains_eof = self.read("set contains EOF")? != 0;
459            if contains_eof {
460                set.add(TOKEN_EOF);
461            }
462            for _ in 0..interval_count {
463                let start = self.read("interval start")?;
464                let stop = self.read("interval stop")?;
465                set.add_range(start, stop);
466            }
467            sets.push(set);
468        }
469        Ok(sets)
470    }
471
472    /// Decodes serialized edges and appends derived rule-return epsilon edges.
473    fn deserialize_edges(
474        &mut self,
475        atn: &mut LexerAtn,
476        sets: &[IntervalSet],
477    ) -> Result<(), AntlrError> {
478        let transition_count = self.read_usize("transition count")?;
479        for _ in 0..transition_count {
480            let src = self.read_usize("transition source")?;
481            let target = self.read_usize("transition target")?;
482            let kind = self.read("transition type")?;
483            let a = self.read("transition arg 1")?;
484            let b = self.read("transition arg 2")?;
485            let c = self.read("transition arg 3")?;
486            let transition = decode_transition(target, kind, a, b, c, sets)?;
487            let Some(state) = atn.state_mut(src) else {
488                return Err(AntlrError::Unsupported(format!(
489                    "transition source {src} outside state list"
490                )));
491            };
492            state.add_transition(transition);
493        }
494
495        let mut return_edges = Vec::new();
496        for state in atn.states() {
497            for transition in &state.transitions {
498                let LexerTransition::Rule {
499                    target,
500                    follow_state,
501                    ..
502                } = transition
503                else {
504                    continue;
505                };
506                let Some(rule_index) = atn.state(*target).and_then(|state| state.rule_index) else {
507                    continue;
508                };
509                let Some(stop_state) = atn.rule_to_stop_state().get(rule_index).copied() else {
510                    continue;
511                };
512                if stop_state != usize::MAX {
513                    return_edges.push((stop_state, *follow_state));
514                }
515            }
516        }
517        for (stop_state, follow_state) in return_edges {
518            if let Some(state) = atn.state_mut(stop_state) {
519                state.add_transition(LexerTransition::Epsilon {
520                    target: follow_state,
521                });
522            }
523        }
524
525        Ok(())
526    }
527
528    /// Decodes parser/lexer decision entry states in decision-number order.
529    fn deserialize_decisions(&mut self, atn: &mut LexerAtn) -> Result<(), AntlrError> {
530        let decision_count = self.read_usize("decision count")?;
531        for _ in 0..decision_count {
532            atn.add_decision_state(self.read_usize("decision state")?);
533        }
534        Ok(())
535    }
536
537    /// Decodes grammar-independent lexer actions referenced by action
538    /// transitions.
539    fn deserialize_lexer_actions(&mut self, atn: &mut LexerAtn) -> Result<(), AntlrError> {
540        let action_count = self.read_usize("lexer action count")?;
541        let mut actions = Vec::with_capacity(action_count);
542        for _ in 0..action_count {
543            let action_type = self.read("lexer action type")?;
544            let data1 = self.read("lexer action data 1")?;
545            let data2 = self.read("lexer action data 2")?;
546            actions.push(decode_lexer_action(action_type, data1, data2)?);
547        }
548        atn.set_lexer_actions(actions);
549        Ok(())
550    }
551
552    /// Reads the next integer and reports which logical field was expected if
553    /// the data ends early.
554    fn read(&mut self, label: &str) -> Result<i32, AntlrError> {
555        let value = self.values.get(self.cursor).copied().ok_or_else(|| {
556            AntlrError::Unsupported(format!("serialized ATN ended while reading {label}"))
557        })?;
558        self.cursor += 1;
559        Ok(value)
560    }
561
562    /// Reads the next integer as a non-negative state/table count or index.
563    fn read_usize(&mut self, label: &str) -> Result<usize, AntlrError> {
564        let value = self.read(label)?;
565        usize::try_from(value)
566            .map_err(|_| AntlrError::Unsupported(format!("{label} cannot be negative: {value}")))
567    }
568}
569
570/// Converts ANTLR's serialized state integer into the runtime state enum.
571fn decode_state_kind(value: i32) -> Result<AtnStateKind, AntlrError> {
572    let kind = match value {
573        0 => AtnStateKind::Invalid,
574        1 => AtnStateKind::Basic,
575        2 => AtnStateKind::RuleStart,
576        3 => AtnStateKind::BlockStart,
577        4 => AtnStateKind::PlusBlockStart,
578        5 => AtnStateKind::StarBlockStart,
579        6 => AtnStateKind::TokenStart,
580        7 => AtnStateKind::RuleStop,
581        8 => AtnStateKind::BlockEnd,
582        9 => AtnStateKind::StarLoopBack,
583        10 => AtnStateKind::StarLoopEntry,
584        11 => AtnStateKind::PlusLoopBack,
585        12 => AtnStateKind::LoopEnd,
586        other => return Err(AntlrError::Unsupported(format!("ATN state type {other}"))),
587    };
588    Ok(kind)
589}
590
591/// Converts one serialized edge record into a typed transition.
592fn decode_transition(
593    target: usize,
594    kind: i32,
595    a: i32,
596    b: i32,
597    c: i32,
598    sets: &[IntervalSet],
599) -> Result<LexerTransition, AntlrError> {
600    let transition = match kind {
601        1 => LexerTransition::Epsilon { target },
602        2 => LexerTransition::Range {
603            target,
604            start: if c != 0 { TOKEN_EOF } else { a },
605            stop: b,
606        },
607        3 => LexerTransition::Rule {
608            target: read_index(a, "rule transition target")?,
609            rule_index: read_index(b, "rule transition rule index")?,
610            follow_state: target,
611            precedence: c,
612        },
613        4 => LexerTransition::Predicate {
614            target,
615            rule_index: read_index(a, "predicate rule index")?,
616            pred_index: read_index(b, "predicate index")?,
617            context_dependent: c != 0,
618        },
619        5 => LexerTransition::Atom {
620            target,
621            label: if c != 0 { TOKEN_EOF } else { a },
622        },
623        6 => LexerTransition::Action {
624            target,
625            rule_index: read_index(a, "action rule index")?,
626            action_index: usize::try_from(b).ok(),
627            context_dependent: c != 0,
628        },
629        7 => LexerTransition::Set {
630            target,
631            set: sets
632                .get(read_index(a, "set transition set index")?)
633                .cloned()
634                .ok_or_else(|| {
635                    AntlrError::Unsupported(format!("set index {a} outside set list"))
636                })?,
637        },
638        8 => LexerTransition::NotSet {
639            target,
640            set: sets
641                .get(read_index(a, "not-set transition set index")?)
642                .cloned()
643                .ok_or_else(|| {
644                    AntlrError::Unsupported(format!("set index {a} outside set list"))
645                })?,
646        },
647        9 => LexerTransition::Wildcard { target },
648        10 => LexerTransition::Precedence {
649            target,
650            precedence: a,
651        },
652        other => {
653            return Err(AntlrError::Unsupported(format!(
654                "ATN transition type {other}"
655            )));
656        }
657    };
658    Ok(transition)
659}
660
661/// Converts one serialized parser edge directly into a packed-builder record.
662fn decode_parser_transition(
663    target: usize,
664    kind: i32,
665    a: i32,
666    b: i32,
667    c: i32,
668    sets: &[ParserIntervalSetId],
669) -> Result<ParserTransitionSpec, AntlrError> {
670    let transition = match kind {
671        1 => ParserTransitionSpec::Epsilon { target },
672        2 => ParserTransitionSpec::Range {
673            target,
674            start: if c != 0 { TOKEN_EOF } else { a },
675            stop: b,
676        },
677        3 => ParserTransitionSpec::Rule {
678            target: read_index(a, "rule transition target")?,
679            rule_index: read_index(b, "rule transition rule index")?,
680            follow_state: target,
681            precedence: c,
682        },
683        4 => ParserTransitionSpec::Predicate {
684            target,
685            rule_index: read_index(a, "predicate rule index")?,
686            pred_index: read_index(b, "predicate index")?,
687            context_dependent: c != 0,
688        },
689        5 => ParserTransitionSpec::Atom {
690            target,
691            label: if c != 0 { TOKEN_EOF } else { a },
692        },
693        6 => ParserTransitionSpec::Action {
694            target,
695            rule_index: read_index(a, "action rule index")?,
696            action_index: usize::try_from(b).ok(),
697            context_dependent: c != 0,
698        },
699        7 => ParserTransitionSpec::Set {
700            target,
701            set: parser_set_id(sets, a, "set transition")?,
702        },
703        8 => ParserTransitionSpec::NotSet {
704            target,
705            set: parser_set_id(sets, a, "not-set transition")?,
706        },
707        9 => ParserTransitionSpec::Wildcard { target },
708        10 => ParserTransitionSpec::Precedence {
709            target,
710            precedence: a,
711        },
712        other => {
713            return Err(AntlrError::Unsupported(format!(
714                "ATN transition type {other}"
715            )));
716        }
717    };
718    Ok(transition)
719}
720
721fn parser_set_id(
722    sets: &[ParserIntervalSetId],
723    value: i32,
724    label: &str,
725) -> Result<ParserIntervalSetId, AntlrError> {
726    let index = read_index(value, label)?;
727    sets.get(index).copied().ok_or_else(|| {
728        AntlrError::Unsupported(format!("{label} set index {value} outside set list"))
729    })
730}
731
732/// Adds ANTLR's derived epsilon returns without constructing per-state edge
733/// vectors. The builder keeps the original edge order for each stop state and
734/// appends these derived returns after serialized edges.
735fn add_parser_rule_return_edges(builder: &mut ParserAtnBuilder) -> Result<(), AntlrError> {
736    let mut return_edges = Vec::new();
737    for source in 0..builder.state_count() {
738        for transition in builder.transitions_from(source) {
739            let ParserTransitionSpec::Rule {
740                target,
741                follow_state,
742                ..
743            } = transition
744            else {
745                continue;
746            };
747            let Some(rule_index) = builder.state_rule_index(target) else {
748                continue;
749            };
750            let Some(stop_state) = builder.rule_stop_state(rule_index) else {
751                continue;
752            };
753            return_edges.push((stop_state, follow_state));
754        }
755    }
756    for (stop_state, follow_state) in return_edges {
757        builder
758            .add_transition(
759                stop_state,
760                ParserTransitionSpec::Epsilon {
761                    target: follow_state,
762                },
763            )
764            .map_err(|error| parser_atn_error(&error))?;
765    }
766    Ok(())
767}
768
769fn parser_atn_error(error: &ParserAtnError) -> AntlrError {
770    AntlrError::Unsupported(error.to_string())
771}
772
773/// Converts ANTLR's serialized lexer action ordinal and data operands into a
774/// runtime action.
775fn decode_lexer_action(
776    action_type: i32,
777    data1: i32,
778    data2: i32,
779) -> Result<LexerAction, AntlrError> {
780    let action = match action_type {
781        0 => LexerAction::Channel(data1),
782        1 => LexerAction::Custom {
783            rule_index: data1,
784            action_index: data2,
785        },
786        2 => LexerAction::Mode(data1),
787        3 => LexerAction::More,
788        4 => LexerAction::PopMode,
789        5 => LexerAction::PushMode(data1),
790        6 => LexerAction::Skip,
791        7 => LexerAction::Type(data1),
792        other => {
793            return Err(AntlrError::Unsupported(format!(
794                "lexer action type {other}"
795            )));
796        }
797    };
798    Ok(action)
799}
800
801/// Marks star-loop entry states that are parser precedence decisions.
802fn mark_precedence_decisions(atn: &mut LexerAtn) {
803    let mut decisions = Vec::new();
804    for state in atn.states() {
805        if state.kind != AtnStateKind::StarLoopEntry {
806            continue;
807        }
808        let Some(rule_index) = state.rule_index else {
809            continue;
810        };
811        let Some(rule_start) = atn
812            .rule_to_start_state()
813            .get(rule_index)
814            .and_then(|state_number| atn.state(*state_number))
815        else {
816            continue;
817        };
818        if !rule_start.left_recursive_rule {
819            continue;
820        }
821        let Some(loop_end_state) = state
822            .transitions
823            .last()
824            .and_then(|transition| atn.state(transition.target()))
825        else {
826            continue;
827        };
828        if loop_end_state.kind != AtnStateKind::LoopEnd {
829            continue;
830        }
831        let Some(target) = loop_end_state
832            .transitions
833            .first()
834            .and_then(|transition| atn.state(transition.target()))
835        else {
836            continue;
837        };
838        if target.kind == AtnStateKind::RuleStop {
839            decisions.push(state.state_number);
840        }
841    }
842
843    for state_number in decisions {
844        if let Some(state) = atn.state_mut(state_number) {
845            state.precedence_rule_decision = true;
846        }
847    }
848}
849
850/// Converts a serialized integer operand to an index with a field-specific
851/// error.
852fn read_index(value: i32, label: &str) -> Result<usize, AntlrError> {
853    usize::try_from(value)
854        .map_err(|_| AntlrError::Unsupported(format!("{label} cannot be negative: {value}")))
855}
856
857#[cfg(test)]
858#[allow(clippy::disallowed_methods)] // `insta` assertion macros unwrap internal I/O.
859mod tests {
860    use super::*;
861
862    #[test]
863    fn reads_small_parser_atn() {
864        let serialized = SerializedAtn::from_i32(&[
865            4, 1, 9, // header: version, parser, max token type
866            2, // states
867            2, 0, // rule start
868            7, 0, // rule stop
869            0, // non-greedy states
870            0, // precedence states
871            1, // rules
872            0, // rule 0 start
873            0, // modes
874            0, // sets
875            1, // transitions
876            0, 1, 5, 42, 0, 0, // atom to state 1 with label 42
877            1, // decisions
878            0,
879        ]);
880        let atn = AtnDeserializer::new(&serialized)
881            .deserialize_parser()
882            .expect("artificial parser ATN should deserialize");
883        // One summary snapshot of the deserialized shape supersedes the six per-accessor pokes and
884        // additionally locks the full ParserAtnStats layout (states count included).
885        insta::assert_debug_snapshot!(
886            "reads_small_parser_atn",
887            (
888                atn.max_token_type(),
889                atn.rule_to_start_state().iter().collect::<Vec<_>>(),
890                atn.rule_to_stop_state().iter().collect::<Vec<_>>(),
891                atn.decision_to_state().iter().collect::<Vec<_>>(),
892                atn.stats(),
893            )
894        );
895    }
896
897    #[test]
898    fn graph_deserializer_rejects_parser_input() {
899        let serialized = SerializedAtn::from_i32(&[4, 1, 0]);
900        let error = AtnDeserializer::new(&serialized)
901            .deserialize()
902            .expect_err("parser input must not create a lexer graph");
903        insta::assert_snapshot!(error.to_string(), @"unsupported runtime feature: parser ATNs require AtnDeserializer::deserialize_parser()");
904    }
905}