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