Skip to main content

antlr4_runtime/
tree.rs

1// SPDX-License-Identifier: BSD-3-Clause
2// Copyright (c) 2026 Konstantin Vyatkin
3use crate::errors::AntlrError;
4use crate::recognizer::Recognizer;
5use crate::token::{Token, TokenId, TokenStore, TokenView};
6use std::any::Any;
7use std::collections::BTreeMap;
8use std::fmt;
9use std::mem::size_of;
10
11const NONE: u32 = u32::MAX;
12const FLAG_MATCHED_CHILD: u8 = 1 << 0;
13const FLAG_START_PRESENT: u8 = 1 << 1;
14const FLAG_STOP_PRESENT: u8 = 1 << 2;
15const VISITOR_STACK_RED_ZONE: usize = 1024 * 1024;
16const VISITOR_STACK_SIZE: usize = 4 * 1024 * 1024;
17
18#[repr(transparent)]
19#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
20pub struct NodeId(u32);
21
22impl NodeId {
23    pub(crate) const fn placeholder() -> Self {
24        Self(NONE)
25    }
26
27    #[must_use]
28    pub const fn index(self) -> usize {
29        self.0 as usize
30    }
31}
32
33/// Compact parser result. The tree data lives in [`ParseTreeStorage`].
34pub type ParseTree = NodeId;
35
36#[repr(u8)]
37#[derive(Clone, Copy, Debug, Eq, PartialEq)]
38pub enum NodeKind {
39    Rule,
40    Terminal,
41    Error,
42}
43
44#[derive(Debug)]
45struct ChildLink {
46    node: NodeId,
47    next: u32,
48}
49
50#[derive(Debug)]
51struct RuleExtra {
52    int_returns: BTreeMap<String, i64>,
53    exception: Option<AntlrError>,
54    attrs: Option<GeneratedAttrs>,
55}
56
57#[derive(Debug)]
58enum ParseTreeExtra {
59    Rule(RuleExtra),
60}
61
62/// Flat, structure-of-arrays concrete syntax tree storage.
63///
64/// Every node is addressed by [`NodeId`]. Rule children occupy one range in
65/// `children`; `child_links` is parser scratch used only while rule contexts
66/// are open and is never exposed as part of the completed tree.
67#[derive(Debug, Default)]
68pub struct ParseTreeStorage {
69    kinds: Vec<NodeKind>,
70    child_starts: Vec<u32>,
71    child_lens: Vec<u32>,
72    payload_a: Vec<u32>,
73    payload_b: Vec<u32>,
74    starts: Vec<u32>,
75    stops: Vec<u32>,
76    alt_numbers: Vec<u32>,
77    context_alt_numbers: Vec<u32>,
78    extra_ids: Vec<u32>,
79    parents: Vec<u32>,
80    flags: Vec<u8>,
81    children: Vec<NodeId>,
82    extras: Vec<ParseTreeExtra>,
83    child_links: Vec<ChildLink>,
84}
85
86#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
87pub struct ParseTreeStats {
88    pub nodes: usize,
89    pub edges: usize,
90    pub extras: usize,
91    pub scratch_links: usize,
92    pub allocated_bytes: usize,
93}
94
95#[derive(Clone, Copy, Debug, Eq, PartialEq)]
96pub(crate) struct ParseTreeCheckpoint {
97    nodes: usize,
98    children: usize,
99    extras: usize,
100    child_links: usize,
101}
102
103impl ParseTreeStorage {
104    #[must_use]
105    pub const fn new() -> Self {
106        Self {
107            kinds: Vec::new(),
108            child_starts: Vec::new(),
109            child_lens: Vec::new(),
110            payload_a: Vec::new(),
111            payload_b: Vec::new(),
112            starts: Vec::new(),
113            stops: Vec::new(),
114            alt_numbers: Vec::new(),
115            context_alt_numbers: Vec::new(),
116            extra_ids: Vec::new(),
117            parents: Vec::new(),
118            flags: Vec::new(),
119            children: Vec::new(),
120            extras: Vec::new(),
121            child_links: Vec::new(),
122        }
123    }
124
125    #[must_use]
126    pub const fn node_count(&self) -> usize {
127        self.kinds.len()
128    }
129
130    #[must_use]
131    pub const fn edge_count(&self) -> usize {
132        self.children.len()
133    }
134
135    #[must_use]
136    pub const fn extra_count(&self) -> usize {
137        self.extras.len()
138    }
139
140    #[must_use]
141    pub const fn stats(&self) -> ParseTreeStats {
142        ParseTreeStats {
143            nodes: self.node_count(),
144            edges: self.edge_count(),
145            extras: self.extra_count(),
146            scratch_links: self.child_links.len(),
147            allocated_bytes: self.kinds.capacity() * size_of::<NodeKind>()
148                + self.child_starts.capacity() * size_of::<u32>()
149                + self.child_lens.capacity() * size_of::<u32>()
150                + self.payload_a.capacity() * size_of::<u32>()
151                + self.payload_b.capacity() * size_of::<u32>()
152                + self.starts.capacity() * size_of::<u32>()
153                + self.stops.capacity() * size_of::<u32>()
154                + self.alt_numbers.capacity() * size_of::<u32>()
155                + self.context_alt_numbers.capacity() * size_of::<u32>()
156                + self.extra_ids.capacity() * size_of::<u32>()
157                + self.parents.capacity() * size_of::<u32>()
158                + self.flags.capacity() * size_of::<u8>()
159                + self.children.capacity() * size_of::<NodeId>()
160                + self.extras.capacity() * size_of::<ParseTreeExtra>()
161                + self.child_links.capacity() * size_of::<ChildLink>(),
162        }
163    }
164
165    pub(crate) fn reset(&mut self) {
166        self.kinds.clear();
167        self.child_starts.clear();
168        self.child_lens.clear();
169        self.payload_a.clear();
170        self.payload_b.clear();
171        self.starts.clear();
172        self.stops.clear();
173        self.alt_numbers.clear();
174        self.context_alt_numbers.clear();
175        self.extra_ids.clear();
176        self.parents.clear();
177        self.flags.clear();
178        self.children.clear();
179        self.extras.clear();
180        self.child_links.clear();
181    }
182
183    pub(crate) fn release_scratch(&mut self) {
184        self.child_links.clear();
185    }
186
187    pub(crate) fn discard_scratch(&mut self) {
188        self.child_links = Vec::new();
189    }
190
191    pub(crate) const fn checkpoint(&self) -> ParseTreeCheckpoint {
192        ParseTreeCheckpoint {
193            nodes: self.kinds.len(),
194            children: self.children.len(),
195            extras: self.extras.len(),
196            child_links: self.child_links.len(),
197        }
198    }
199
200    pub(crate) fn rollback(&mut self, checkpoint: ParseTreeCheckpoint) {
201        self.kinds.truncate(checkpoint.nodes);
202        self.child_starts.truncate(checkpoint.nodes);
203        self.child_lens.truncate(checkpoint.nodes);
204        self.payload_a.truncate(checkpoint.nodes);
205        self.payload_b.truncate(checkpoint.nodes);
206        self.starts.truncate(checkpoint.nodes);
207        self.stops.truncate(checkpoint.nodes);
208        self.alt_numbers.truncate(checkpoint.nodes);
209        self.context_alt_numbers.truncate(checkpoint.nodes);
210        self.extra_ids.truncate(checkpoint.nodes);
211        self.parents.truncate(checkpoint.nodes);
212        self.flags.truncate(checkpoint.nodes);
213        self.children.truncate(checkpoint.children);
214        self.extras.truncate(checkpoint.extras);
215        self.child_links.truncate(checkpoint.child_links);
216    }
217
218    pub(crate) fn terminal(&mut self, token: TokenId) -> NodeId {
219        self.push_node(NodeRecord {
220            kind: NodeKind::Terminal,
221            payload_a: token.index() as u32,
222            ..NodeRecord::default()
223        })
224    }
225
226    pub(crate) fn error(&mut self, token: TokenId) -> NodeId {
227        self.push_node(NodeRecord {
228            kind: NodeKind::Error,
229            payload_a: token.index() as u32,
230            ..NodeRecord::default()
231        })
232    }
233
234    pub(crate) fn add_child(&mut self, context: &mut ParserRuleContext, child: NodeId) {
235        context.matched_child = true;
236        let link = self.child_links.len_u32("parse-tree scratch child links");
237        self.child_links.push(ChildLink {
238            node: child,
239            next: NONE,
240        });
241        if context.first_child == NONE {
242            context.first_child = link;
243        } else {
244            self.child_links[context.last_child as usize].next = link;
245        }
246        context.last_child = link;
247        context.child_count = context
248            .child_count
249            .checked_add(1)
250            .expect("rule child count exceeds u32");
251    }
252
253    pub(crate) fn finish_rule(&mut self, context: ParserRuleContext) -> NodeId {
254        let parent = NodeId(self.kinds.len_u32("parse-tree node pool"));
255        let child_start = self.children.len_u32("parse-tree child pool");
256        let mut link = context.first_child;
257        while link != NONE {
258            let child = &self.child_links[link as usize];
259            self.children.push(child.node);
260            self.parents[child.node.index()] = parent.0;
261            link = child.next;
262        }
263
264        let extra_id = if context.int_returns.is_empty()
265            && context.exception.is_none()
266            && context.attrs.is_none()
267        {
268            NONE
269        } else {
270            let id = self.extras.len_u32("parse-tree extra pool");
271            self.extras.push(ParseTreeExtra::Rule(RuleExtra {
272                int_returns: context.int_returns,
273                exception: context.exception,
274                attrs: context.attrs,
275            }));
276            id
277        };
278
279        self.push_node(NodeRecord {
280            kind: NodeKind::Rule,
281            child_start,
282            child_len: context.child_count,
283            payload_a: u32::try_from(context.rule_index).expect("rule index exceeds u32"),
284            payload_b: i32::try_from(context.invoking_state)
285                .expect("invoking state exceeds i32")
286                .cast_unsigned(),
287            start: context.start.map_or(NONE, |token| token.index() as u32),
288            stop: context.stop.map_or(NONE, |token| token.index() as u32),
289            alt_number: u32::try_from(context.alt_number).expect("alternative number exceeds u32"),
290            context_alt_number: u32::try_from(context.context_alt_number)
291                .expect("context alternative number exceeds u32"),
292            extra_id,
293            flags: (u8::from(context.matched_child) * FLAG_MATCHED_CHILD)
294                | (u8::from(context.start.is_some()) * FLAG_START_PRESENT)
295                | (u8::from(context.stop.is_some()) * FLAG_STOP_PRESENT),
296        })
297    }
298
299    fn push_node(&mut self, record: NodeRecord) -> NodeId {
300        let id = NodeId(self.kinds.len_u32("parse-tree node pool"));
301        self.kinds.push(record.kind);
302        self.child_starts.push(record.child_start);
303        self.child_lens.push(record.child_len);
304        self.payload_a.push(record.payload_a);
305        self.payload_b.push(record.payload_b);
306        self.starts.push(record.start);
307        self.stops.push(record.stop);
308        self.alt_numbers.push(record.alt_number);
309        if record.context_alt_number == 0 {
310            if !self.context_alt_numbers.is_empty() {
311                self.context_alt_numbers.push(0);
312            }
313        } else {
314            if self.context_alt_numbers.is_empty() {
315                self.context_alt_numbers.resize(id.index(), 0);
316            }
317            self.context_alt_numbers.push(record.context_alt_number);
318        }
319        self.extra_ids.push(record.extra_id);
320        self.parents.push(NONE);
321        self.flags.push(record.flags);
322        id
323    }
324
325    #[must_use]
326    pub fn node<'tree>(&'tree self, tokens: &'tree TokenStore, id: NodeId) -> Option<Node<'tree>> {
327        (id.index() < self.node_count()).then_some(Node {
328            storage: self,
329            tokens,
330            id,
331        })
332    }
333
334    fn kind(&self, id: NodeId) -> NodeKind {
335        self.kinds[id.index()]
336    }
337
338    fn child_ids(&self, id: NodeId) -> &[NodeId] {
339        let index = id.index();
340        let start = self.child_starts[index] as usize;
341        let len = self.child_lens[index] as usize;
342        &self.children[start..start + len]
343    }
344
345    const fn context_child_ids<'a>(
346        &'a self,
347        context: &'a ParserRuleContext,
348    ) -> ContextChildIds<'a> {
349        ContextChildIds {
350            storage: self,
351            next: context.first_child,
352            remaining: context.child_count as usize,
353        }
354    }
355
356    fn token_id(&self, id: NodeId) -> Option<TokenId> {
357        match self.kind(id) {
358            NodeKind::Terminal | NodeKind::Error => {
359                Some(stored_token_id(self.payload_a[id.index()]))
360            }
361            NodeKind::Rule => None,
362        }
363    }
364
365    fn rule_extra(&self, id: NodeId) -> Option<&RuleExtra> {
366        let extra = *self.extra_ids.get(id.index())?;
367        if extra == NONE {
368            return None;
369        }
370        match &self.extras[extra as usize] {
371            ParseTreeExtra::Rule(extra) => Some(extra),
372        }
373    }
374}
375
376#[derive(Clone, Copy)]
377struct NodeRecord {
378    kind: NodeKind,
379    child_start: u32,
380    child_len: u32,
381    payload_a: u32,
382    payload_b: u32,
383    start: u32,
384    stop: u32,
385    alt_number: u32,
386    context_alt_number: u32,
387    extra_id: u32,
388    flags: u8,
389}
390
391impl Default for NodeRecord {
392    fn default() -> Self {
393        Self {
394            kind: NodeKind::Rule,
395            child_start: 0,
396            child_len: 0,
397            payload_a: 0,
398            payload_b: 0,
399            start: NONE,
400            stop: NONE,
401            alt_number: 0,
402            context_alt_number: 0,
403            extra_id: NONE,
404            flags: 0,
405        }
406    }
407}
408
409trait LenU32 {
410    fn len_u32(&self, name: &str) -> u32;
411}
412
413impl<T> LenU32 for Vec<T> {
414    fn len_u32(&self, name: &str) -> u32 {
415        u32::try_from(self.len()).unwrap_or_else(|_| panic!("{name} exceeds u32"))
416    }
417}
418
419#[derive(Clone, Copy, Debug)]
420pub struct Node<'tree> {
421    storage: &'tree ParseTreeStorage,
422    tokens: &'tree TokenStore,
423    id: NodeId,
424}
425
426impl<'tree> Node<'tree> {
427    #[must_use]
428    pub const fn id(self) -> NodeId {
429        self.id
430    }
431
432    #[must_use]
433    pub fn kind(self) -> NodeKind {
434        self.storage.kind(self.id)
435    }
436
437    #[must_use]
438    pub fn as_rule(self) -> Option<RuleNodeView<'tree>> {
439        (self.kind() == NodeKind::Rule).then_some(RuleNodeView { node: self })
440    }
441
442    #[must_use]
443    pub fn as_terminal(self) -> Option<TerminalNodeView<'tree>> {
444        (self.kind() == NodeKind::Terminal).then_some(TerminalNodeView { node: self })
445    }
446
447    #[must_use]
448    pub fn as_error(self) -> Option<ErrorNodeView<'tree>> {
449        (self.kind() == NodeKind::Error).then_some(ErrorNodeView { node: self })
450    }
451
452    /// Child-token triage shared by every terminal-children iterator: real
453    /// terminals and recovered error-node terminals view as terminals, rule
454    /// nodes do not.
455    #[must_use]
456    pub(crate) fn terminal_view(self) -> Option<TerminalNodeView<'tree>> {
457        match self.kind() {
458            NodeKind::Terminal => self.as_terminal(),
459            NodeKind::Error => self.as_error().map(ErrorNodeView::terminal),
460            NodeKind::Rule => None,
461        }
462    }
463
464    /// Grammar-positional labeled-token triage: deleted input tokens are
465    /// skipped while inserted (synthetic) tokens are kept. See
466    /// [`ParserRuleContext::labeled_terminal_children`] for the rationale.
467    #[must_use]
468    pub(crate) fn labeled_terminal_view(self) -> Option<TerminalNodeView<'tree>> {
469        match self.kind() {
470            NodeKind::Terminal => self.as_terminal(),
471            NodeKind::Error => {
472                let terminal = self.as_error().map(ErrorNodeView::terminal)?;
473                terminal.symbol().is_synthetic().then_some(terminal)
474            }
475            NodeKind::Rule => None,
476        }
477    }
478
479    #[must_use]
480    pub fn children(self) -> NodeChildren<'tree> {
481        NodeChildren {
482            storage: self.storage,
483            tokens: self.tokens,
484            ids: self.storage.child_ids(self.id).iter(),
485        }
486    }
487
488    #[must_use]
489    pub fn parent(self) -> Option<Self> {
490        let parent = self.storage.parents[self.id.index()];
491        (parent != NONE)
492            .then(|| self.storage.node(self.tokens, NodeId(parent)))
493            .flatten()
494    }
495
496    #[must_use]
497    pub fn descendants(self) -> ParseTreeDescendants<'tree> {
498        ParseTreeDescendants {
499            storage: self.storage,
500            tokens: self.tokens,
501            stack: vec![self.id],
502        }
503    }
504
505    #[must_use]
506    pub fn pre_order(self) -> ParseTreeDescendants<'tree> {
507        self.descendants()
508    }
509
510    #[must_use]
511    pub fn text(self) -> String {
512        match self.kind() {
513            NodeKind::Terminal | NodeKind::Error => self
514                .storage
515                .token_id(self.id)
516                .and_then(|id| self.tokens.text(id))
517                .unwrap_or("")
518                .to_owned(),
519            NodeKind::Rule => {
520                let mut text = String::new();
521                let mut stack = self
522                    .storage
523                    .child_ids(self.id)
524                    .iter()
525                    .rev()
526                    .copied()
527                    .collect::<Vec<_>>();
528                while let Some(id) = stack.pop() {
529                    match self.storage.kind(id) {
530                        NodeKind::Rule => {
531                            stack.extend(self.storage.child_ids(id).iter().rev().copied());
532                        }
533                        NodeKind::Terminal | NodeKind::Error => text.push_str(
534                            self.storage
535                                .token_id(id)
536                                .and_then(|token| self.tokens.text(token))
537                                .unwrap_or(""),
538                        ),
539                    }
540                }
541                text
542            }
543        }
544    }
545
546    #[must_use]
547    pub fn to_string_tree_with_names<S: AsRef<str>>(self, rule_names: &[S]) -> String {
548        match self.kind() {
549            NodeKind::Rule => self
550                .as_rule()
551                .expect("rule node kind checked")
552                .to_string_tree_with_names(rule_names),
553            NodeKind::Terminal | NodeKind::Error => escape_tree_text(
554                self.storage
555                    .token_id(self.id)
556                    .and_then(|id| self.tokens.text(id))
557                    .unwrap_or(""),
558            ),
559        }
560    }
561
562    #[must_use]
563    pub fn to_string_tree<R: Recognizer>(
564        self,
565        recognizer: Option<&R>,
566        _tokens: &TokenStore,
567    ) -> String {
568        recognizer.map_or_else(
569            || self.to_string_tree_with_names::<&str>(&[]),
570            |recognizer| self.to_string_tree_with_names(recognizer.data().rule_names()),
571        )
572    }
573
574    #[must_use]
575    pub fn first_rule(self, rule_index: usize) -> Option<Self> {
576        self.descendants().find(|node| {
577            node.as_rule()
578                .is_some_and(|rule| rule.rule_index() == rule_index)
579        })
580    }
581
582    #[must_use]
583    pub fn first_rule_stop(self, rule_index: usize) -> Option<TokenView<'tree>> {
584        self.first_rule(rule_index)?.as_rule()?.stop()
585    }
586
587    #[must_use]
588    pub fn first_rule_int_return(self, rule_index: usize, name: &str) -> Option<i64> {
589        self.first_rule(rule_index)?.as_rule()?.int_return(name)
590    }
591
592    #[must_use]
593    pub fn rule_attrs<T: Any>(self) -> Option<&'tree T> {
594        self.as_rule()?.generated_attrs::<T>()
595    }
596
597    #[must_use]
598    pub fn first_error_token(self) -> Option<TokenView<'tree>> {
599        self.descendants()
600            .find_map(Node::as_error)
601            .map(ErrorNodeView::symbol)
602    }
603
604    #[must_use]
605    pub fn rule_invocation_stack<S: AsRef<str>>(
606        self,
607        rule_index: usize,
608        rule_names: &[S],
609    ) -> Option<Vec<String>> {
610        let mut stack = vec![(self.id, 0_usize)];
611        let mut names = Vec::new();
612        while let Some((id, child_index)) = stack.last_mut() {
613            if *child_index == 0 {
614                let Some(rule) = self.storage.node(self.tokens, *id).and_then(Node::as_rule) else {
615                    stack.pop();
616                    continue;
617                };
618                names.push(
619                    rule_names
620                        .get(rule.rule_index())
621                        .map_or("<unknown>", |name| name.as_ref())
622                        .to_owned(),
623                );
624                if rule.rule_index() == rule_index {
625                    names.reverse();
626                    return Some(names);
627                }
628            }
629            let children = self.storage.child_ids(*id);
630            let next = children.get(*child_index).copied();
631            *child_index += 1;
632            if let Some(child) = next {
633                if self.storage.kind(child) == NodeKind::Rule {
634                    stack.push((child, 0));
635                }
636            } else {
637                stack.pop();
638                names.pop();
639            }
640        }
641        None
642    }
643}
644
645#[derive(Clone, Debug)]
646pub struct NodeChildren<'tree> {
647    storage: &'tree ParseTreeStorage,
648    tokens: &'tree TokenStore,
649    ids: std::slice::Iter<'tree, NodeId>,
650}
651
652impl<'tree> Iterator for NodeChildren<'tree> {
653    type Item = Node<'tree>;
654
655    fn next(&mut self) -> Option<Self::Item> {
656        self.ids
657            .next()
658            .and_then(|id| self.storage.node(self.tokens, *id))
659    }
660
661    fn size_hint(&self) -> (usize, Option<usize>) {
662        self.ids.size_hint()
663    }
664}
665
666impl DoubleEndedIterator for NodeChildren<'_> {
667    fn next_back(&mut self) -> Option<Self::Item> {
668        self.ids
669            .next_back()
670            .and_then(|id| self.storage.node(self.tokens, *id))
671    }
672}
673
674impl ExactSizeIterator for NodeChildren<'_> {}
675
676#[derive(Clone, Debug)]
677pub struct ParseTreeDescendants<'tree> {
678    storage: &'tree ParseTreeStorage,
679    tokens: &'tree TokenStore,
680    stack: Vec<NodeId>,
681}
682
683impl<'tree> Iterator for ParseTreeDescendants<'tree> {
684    type Item = Node<'tree>;
685
686    fn next(&mut self) -> Option<Self::Item> {
687        let id = self.stack.pop()?;
688        self.stack
689            .extend(self.storage.child_ids(id).iter().rev().copied());
690        Some(Node {
691            storage: self.storage,
692            tokens: self.tokens,
693            id,
694        })
695    }
696}
697
698#[derive(Clone, Copy, Debug)]
699pub struct RuleNodeView<'tree> {
700    node: Node<'tree>,
701}
702
703impl<'tree> RuleNodeView<'tree> {
704    #[must_use]
705    pub const fn node(self) -> Node<'tree> {
706        self.node
707    }
708
709    #[must_use]
710    pub fn rule_index(self) -> usize {
711        self.node.storage.payload_a[self.node.id.index()] as usize
712    }
713
714    #[must_use]
715    pub fn invoking_state(self) -> isize {
716        self.node.storage.payload_b[self.node.id.index()].cast_signed() as isize
717    }
718
719    #[must_use]
720    pub fn alt_number(self) -> usize {
721        self.node.storage.alt_numbers[self.node.id.index()] as usize
722    }
723
724    #[doc(hidden)]
725    #[must_use]
726    pub fn context_alt_number(self) -> usize {
727        self.node
728            .storage
729            .context_alt_numbers
730            .get(self.node.id.index())
731            .copied()
732            .unwrap_or_default() as usize
733    }
734
735    #[must_use]
736    pub fn start(self) -> Option<TokenView<'tree>> {
737        self.start_id().and_then(|id| self.node.tokens.view(id))
738    }
739
740    #[must_use]
741    pub fn start_id(self) -> Option<TokenId> {
742        let index = self.node.id.index();
743        (self.node.storage.flags[index] & FLAG_START_PRESENT != 0)
744            .then(|| stored_token_id(self.node.storage.starts[index]))
745    }
746
747    #[must_use]
748    pub fn stop(self) -> Option<TokenView<'tree>> {
749        self.stop_id().and_then(|id| self.node.tokens.view(id))
750    }
751
752    #[must_use]
753    pub fn stop_id(self) -> Option<TokenId> {
754        let index = self.node.id.index();
755        (self.node.storage.flags[index] & FLAG_STOP_PRESENT != 0)
756            .then(|| stored_token_id(self.node.storage.stops[index]))
757    }
758
759    #[must_use]
760    pub fn children(self) -> NodeChildren<'tree> {
761        self.node.children()
762    }
763
764    #[must_use]
765    pub fn child_count(self) -> usize {
766        self.node.storage.child_lens[self.node.id.index()] as usize
767    }
768
769    #[must_use]
770    pub fn child_rule(self, rule_index: usize) -> Option<Self> {
771        self.child_rules(rule_index).next()
772    }
773
774    pub fn child_rules(self, rule_index: usize) -> impl DoubleEndedIterator<Item = Self> + 'tree {
775        self.children().filter_map(move |child| {
776            let rule = child.as_rule()?;
777            (rule.rule_index() == rule_index).then_some(rule)
778        })
779    }
780
781    pub fn child_rule_trees(
782        self,
783        rule_index: usize,
784    ) -> impl DoubleEndedIterator<Item = Node<'tree>> + 'tree {
785        self.child_rules(rule_index).map(Self::node)
786    }
787
788    #[must_use]
789    pub fn child_token(self, token_type: i32) -> Option<TerminalNodeView<'tree>> {
790        self.child_tokens(token_type).next()
791    }
792
793    pub fn child_tokens(
794        self,
795        token_type: i32,
796    ) -> impl DoubleEndedIterator<Item = TerminalNodeView<'tree>> + 'tree {
797        self.children().filter_map(move |child| {
798            let terminal = child.terminal_view()?;
799            (terminal.symbol().token_type() == token_type).then_some(terminal)
800        })
801    }
802
803    pub fn terminal_children(
804        self,
805    ) -> impl DoubleEndedIterator<Item = TerminalNodeView<'tree>> + 'tree {
806        self.children().filter_map(Node::terminal_view)
807    }
808
809    #[must_use]
810    pub fn has_token(self, token_type: i32) -> bool {
811        self.child_token(token_type).is_some()
812    }
813
814    #[must_use]
815    pub fn text(self) -> String {
816        self.node.text()
817    }
818
819    #[must_use]
820    pub fn int_return(self, name: &str) -> Option<i64> {
821        self.node
822            .storage
823            .rule_extra(self.node.id)?
824            .int_returns
825            .get(name)
826            .copied()
827    }
828
829    #[must_use]
830    pub fn generated_attrs<T: Any>(self) -> Option<&'tree T> {
831        self.node
832            .storage
833            .rule_extra(self.node.id)?
834            .attrs
835            .as_ref()?
836            .downcast_ref::<T>()
837    }
838
839    #[must_use]
840    pub fn exception(self) -> Option<&'tree AntlrError> {
841        self.node
842            .storage
843            .rule_extra(self.node.id)?
844            .exception
845            .as_ref()
846    }
847
848    #[must_use]
849    pub fn downcast_ref<T: FromRuleNode<'tree>>(self) -> Option<T> {
850        T::from_rule_node(self)
851    }
852
853    pub fn invocation_states(self) -> impl Iterator<Item = isize> + 'tree {
854        std::iter::successors(Some(self), |rule| rule.node.parent()?.as_rule())
855            .take_while(|rule| rule.node.parent().is_some() && rule.invoking_state() >= 0)
856            .map(Self::invoking_state)
857    }
858
859    #[must_use]
860    pub fn to_string_tree_with_names<S: AsRef<str>>(self, rule_names: &[S]) -> String {
861        let name = rule_names
862            .get(self.rule_index())
863            .map_or("<unknown>", |name| name.as_ref());
864        let display_name = if self.alt_number() == 0 {
865            name.to_owned()
866        } else {
867            format!("{name}:{}", self.alt_number())
868        };
869        if self.child_count() == 0 {
870            return display_name;
871        }
872        let children = self
873            .children()
874            .map(|child| child.to_string_tree_with_names(rule_names))
875            .collect::<Vec<_>>()
876            .join(" ");
877        format!("({display_name} {children})")
878    }
879
880    #[must_use]
881    pub fn to_string_tree<R: Recognizer>(self, recognizer: Option<&R>) -> String {
882        recognizer.map_or_else(
883            || self.to_string_tree_with_names::<&str>(&[]),
884            |recognizer| self.to_string_tree_with_names(recognizer.data().rule_names()),
885        )
886    }
887}
888
889#[derive(Clone, Copy, Debug)]
890pub struct TerminalNodeView<'tree> {
891    node: Node<'tree>,
892}
893
894impl<'tree> TerminalNodeView<'tree> {
895    #[must_use]
896    pub const fn node(self) -> Node<'tree> {
897        self.node
898    }
899
900    #[must_use]
901    pub fn token_id(self) -> TokenId {
902        self.node
903            .storage
904            .token_id(self.node.id)
905            .expect("terminal node should contain a token ID")
906    }
907
908    #[must_use]
909    pub fn symbol(self) -> TokenView<'tree> {
910        self.node
911            .tokens
912            .view(self.token_id())
913            .expect("terminal node token ID should remain valid")
914    }
915
916    #[must_use]
917    pub fn text(self) -> &'tree str {
918        self.node.tokens.text(self.token_id()).unwrap_or("")
919    }
920}
921
922#[derive(Clone, Copy, Debug)]
923pub struct ErrorNodeView<'tree> {
924    node: Node<'tree>,
925}
926
927impl<'tree> ErrorNodeView<'tree> {
928    #[must_use]
929    pub const fn node(self) -> Node<'tree> {
930        self.node
931    }
932
933    #[must_use]
934    pub const fn terminal(self) -> TerminalNodeView<'tree> {
935        TerminalNodeView { node: self.node }
936    }
937
938    #[must_use]
939    pub fn token_id(self) -> TokenId {
940        self.terminal().token_id()
941    }
942
943    #[must_use]
944    pub fn symbol(self) -> TokenView<'tree> {
945        self.terminal().symbol()
946    }
947
948    #[must_use]
949    pub fn text(self) -> &'tree str {
950        self.terminal().text()
951    }
952}
953
954#[derive(Debug)]
955struct ContextChildIds<'a> {
956    storage: &'a ParseTreeStorage,
957    next: u32,
958    remaining: usize,
959}
960
961impl Iterator for ContextChildIds<'_> {
962    type Item = NodeId;
963
964    fn next(&mut self) -> Option<Self::Item> {
965        if self.next == NONE {
966            return None;
967        }
968        let link = &self.storage.child_links[self.next as usize];
969        self.next = link.next;
970        self.remaining -= 1;
971        Some(link.node)
972    }
973
974    fn size_hint(&self) -> (usize, Option<usize>) {
975        (self.remaining, Some(self.remaining))
976    }
977}
978
979impl ExactSizeIterator for ContextChildIds<'_> {}
980
981/// Transient builder for one open rule.
982///
983/// This value owns no tree nodes or child vector. Child IDs are appended to
984/// parser-owned scratch links and are copied once into the global child pool
985/// when the rule completes.
986#[derive(Debug)]
987pub struct ParserRuleContext {
988    rule_index: usize,
989    invoking_state: isize,
990    alt_number: usize,
991    context_alt_number: usize,
992    start: Option<TokenId>,
993    stop: Option<TokenId>,
994    int_returns: BTreeMap<String, i64>,
995    first_child: u32,
996    last_child: u32,
997    child_count: u32,
998    matched_child: bool,
999    exception: Option<AntlrError>,
1000    attrs: Option<GeneratedAttrs>,
1001}
1002
1003impl ParserRuleContext {
1004    #[must_use]
1005    pub const fn new(rule_index: usize, invoking_state: isize) -> Self {
1006        Self {
1007            rule_index,
1008            invoking_state,
1009            alt_number: 0,
1010            context_alt_number: 0,
1011            start: None,
1012            stop: None,
1013            int_returns: BTreeMap::new(),
1014            first_child: NONE,
1015            last_child: NONE,
1016            child_count: 0,
1017            matched_child: false,
1018            exception: None,
1019            attrs: None,
1020        }
1021    }
1022
1023    pub(crate) const fn with_child_capacity(
1024        rule_index: usize,
1025        invoking_state: isize,
1026        _capacity: usize,
1027    ) -> Self {
1028        Self::new(rule_index, invoking_state)
1029    }
1030
1031    #[must_use]
1032    pub const fn rule_index(&self) -> usize {
1033        self.rule_index
1034    }
1035
1036    #[must_use]
1037    pub const fn invoking_state(&self) -> isize {
1038        self.invoking_state
1039    }
1040
1041    #[must_use]
1042    pub const fn alt_number(&self) -> usize {
1043        self.alt_number
1044    }
1045
1046    pub const fn set_alt_number(&mut self, alt_number: usize) {
1047        self.alt_number = alt_number;
1048    }
1049
1050    #[doc(hidden)]
1051    #[must_use]
1052    pub const fn context_alt_number(&self) -> usize {
1053        self.context_alt_number
1054    }
1055
1056    #[doc(hidden)]
1057    pub const fn set_context_alt_number(&mut self, alt_number: usize) {
1058        self.context_alt_number = alt_number;
1059    }
1060
1061    pub fn start<'a>(&self, tokens: &'a TokenStore) -> Option<TokenView<'a>> {
1062        self.start.and_then(|id| tokens.view(id))
1063    }
1064
1065    pub(crate) const fn start_id(&self) -> Option<TokenId> {
1066        self.start
1067    }
1068
1069    pub fn stop<'a>(&self, tokens: &'a TokenStore) -> Option<TokenView<'a>> {
1070        self.stop.and_then(|id| tokens.view(id))
1071    }
1072
1073    pub(crate) const fn set_start_id(&mut self, token: TokenId) {
1074        self.start = Some(token);
1075    }
1076
1077    pub(crate) const fn set_stop_id(&mut self, token: TokenId) {
1078        self.stop = Some(token);
1079    }
1080
1081    pub(crate) const fn set_start_from_context(&mut self, other: &Self) {
1082        self.start = other.start;
1083    }
1084
1085    pub fn set_int_return(&mut self, name: impl Into<String>, value: i64) {
1086        self.int_returns.insert(name.into(), value);
1087    }
1088
1089    #[must_use]
1090    pub fn int_return(&self, name: &str) -> Option<i64> {
1091        self.int_returns.get(name).copied()
1092    }
1093
1094    pub fn set_generated_attrs(&mut self, attrs: GeneratedAttrs) {
1095        self.attrs = Some(attrs);
1096    }
1097
1098    #[must_use]
1099    pub fn generated_attrs<T: Any>(&self) -> Option<&T> {
1100        self.attrs.as_ref().and_then(GeneratedAttrs::downcast_ref)
1101    }
1102
1103    #[must_use]
1104    pub const fn exception(&self) -> Option<&AntlrError> {
1105        self.exception.as_ref()
1106    }
1107
1108    pub fn set_exception(&mut self, error: AntlrError) {
1109        self.exception = Some(error);
1110    }
1111
1112    #[must_use]
1113    pub const fn child_count(&self) -> usize {
1114        self.child_count as usize
1115    }
1116
1117    #[must_use]
1118    pub const fn has_matched_child(&self) -> bool {
1119        self.matched_child
1120    }
1121
1122    pub const fn note_matched_child(&mut self) {
1123        self.matched_child = true;
1124    }
1125
1126    pub fn child_nodes<'a>(
1127        &'a self,
1128        storage: &'a ParseTreeStorage,
1129        tokens: &'a TokenStore,
1130    ) -> impl Iterator<Item = Node<'a>> + 'a {
1131        storage
1132            .context_child_ids(self)
1133            .filter_map(move |id| storage.node(tokens, id))
1134    }
1135
1136    pub fn child_rules<'a>(
1137        &'a self,
1138        storage: &'a ParseTreeStorage,
1139        tokens: &'a TokenStore,
1140        rule_index: usize,
1141    ) -> impl Iterator<Item = RuleNodeView<'a>> + 'a {
1142        self.child_nodes(storage, tokens).filter_map(move |child| {
1143            let rule = child.as_rule()?;
1144            (rule.rule_index() == rule_index).then_some(rule)
1145        })
1146    }
1147
1148    pub fn child_rule_trees<'a>(
1149        &'a self,
1150        storage: &'a ParseTreeStorage,
1151        tokens: &'a TokenStore,
1152        rule_index: usize,
1153    ) -> impl Iterator<Item = Node<'a>> + 'a {
1154        self.child_rules(storage, tokens, rule_index)
1155            .map(RuleNodeView::node)
1156    }
1157
1158    pub fn child_tokens<'a>(
1159        &'a self,
1160        storage: &'a ParseTreeStorage,
1161        tokens: &'a TokenStore,
1162        token_type: i32,
1163    ) -> impl Iterator<Item = TerminalNodeView<'a>> + 'a {
1164        self.child_nodes(storage, tokens).filter_map(move |child| {
1165            let terminal = child.terminal_view()?;
1166            (terminal.symbol().token_type() == token_type).then_some(terminal)
1167        })
1168    }
1169
1170    pub fn terminal_children<'a>(
1171        &'a self,
1172        storage: &'a ParseTreeStorage,
1173        tokens: &'a TokenStore,
1174    ) -> impl Iterator<Item = TerminalNodeView<'a>> + 'a {
1175        self.child_nodes(storage, tokens)
1176            .filter_map(Node::terminal_view)
1177    }
1178
1179    /// Terminal children as a *grammar-positional* sequence: deleted input tokens
1180    /// are skipped while inserted missing tokens are kept.
1181    ///
1182    /// A generated label read derives its index from the grammar, which knows
1183    /// nothing about error recovery. A deleted token still occupies a child slot, so
1184    /// indexing [`Self::terminal_children`] would shift every later position on
1185    /// recovered input; an *inserted* token, by contrast, is the value ANTLR assigns
1186    /// to the label and must stay. This matches the labeled-token accessors the
1187    /// generator emits.
1188    pub fn labeled_terminal_children<'a>(
1189        &'a self,
1190        storage: &'a ParseTreeStorage,
1191        tokens: &'a TokenStore,
1192    ) -> impl Iterator<Item = TerminalNodeView<'a>> + 'a {
1193        self.child_nodes(storage, tokens)
1194            .filter_map(Node::labeled_terminal_view)
1195    }
1196
1197    #[must_use]
1198    pub fn text(&self, storage: &ParseTreeStorage, tokens: &TokenStore) -> String {
1199        self.child_nodes(storage, tokens).map(Node::text).collect()
1200    }
1201
1202    #[must_use]
1203    pub fn to_string_tree_with_names<S: AsRef<str>>(
1204        &self,
1205        storage: &ParseTreeStorage,
1206        tokens: &TokenStore,
1207        rule_names: &[S],
1208    ) -> String {
1209        let name = rule_names
1210            .get(self.rule_index)
1211            .map_or("<unknown>", |name| name.as_ref());
1212        let display_name = if self.alt_number == 0 {
1213            name.to_owned()
1214        } else {
1215            format!("{name}:{}", self.alt_number)
1216        };
1217        if self.child_count == 0 {
1218            return display_name;
1219        }
1220        let children = self
1221            .child_nodes(storage, tokens)
1222            .map(|child| child.to_string_tree_with_names(rule_names))
1223            .collect::<Vec<_>>()
1224            .join(" ");
1225        format!("({display_name} {children})")
1226    }
1227
1228    #[must_use]
1229    pub fn to_string_tree<R: Recognizer>(
1230        &self,
1231        recognizer: Option<&R>,
1232        storage: &ParseTreeStorage,
1233        tokens: &TokenStore,
1234    ) -> String {
1235        recognizer.map_or_else(
1236            || self.to_string_tree_with_names::<&str>(storage, tokens, &[]),
1237            |recognizer| {
1238                self.to_string_tree_with_names(storage, tokens, recognizer.data().rule_names())
1239            },
1240        )
1241    }
1242}
1243
1244/// Type-erased generated-rule attributes stored only for rules that use them.
1245pub struct GeneratedAttrs(Box<dyn Any>);
1246
1247impl GeneratedAttrs {
1248    #[must_use]
1249    pub fn new<T: Any>(attrs: T) -> Self {
1250        Self(Box::new(attrs))
1251    }
1252
1253    #[must_use]
1254    pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
1255        self.0.downcast_ref::<T>()
1256    }
1257}
1258
1259impl fmt::Debug for GeneratedAttrs {
1260    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1261        f.write_str("GeneratedAttrs(..)")
1262    }
1263}
1264
1265pub trait FromRuleNode<'tree>: Sized {
1266    fn from_rule_node(node: RuleNodeView<'tree>) -> Option<Self>;
1267}
1268
1269/// Exposes the stored rule node behind a completed generated context.
1270pub trait AsRuleNode<'tree> {
1271    fn as_rule_node(&self) -> RuleNodeView<'tree>;
1272}
1273
1274impl<'tree> AsRuleNode<'tree> for RuleNodeView<'tree> {
1275    fn as_rule_node(&self) -> Self {
1276        *self
1277    }
1278}
1279
1280/// A required grammar child was absent from a recovered parse tree.
1281#[derive(Clone, Copy, Debug, Eq, PartialEq)]
1282pub struct MissingChildError {
1283    context: &'static str,
1284    child: &'static str,
1285}
1286
1287impl MissingChildError {
1288    #[must_use]
1289    pub const fn new(context: &'static str, child: &'static str) -> Self {
1290        Self { context, child }
1291    }
1292
1293    #[must_use]
1294    pub const fn context(self) -> &'static str {
1295        self.context
1296    }
1297
1298    #[must_use]
1299    pub const fn child(self) -> &'static str {
1300        self.child
1301    }
1302}
1303
1304impl fmt::Display for MissingChildError {
1305    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1306        write!(
1307            f,
1308            "required child {} is missing from {}",
1309            self.child, self.context
1310        )
1311    }
1312}
1313
1314impl std::error::Error for MissingChildError {}
1315
1316pub trait ParseTreeListener {
1317    fn enter_every_rule(&mut self, _ctx: RuleNodeView<'_>) -> Result<(), AntlrError> {
1318        Ok(())
1319    }
1320
1321    fn exit_every_rule(&mut self, _ctx: RuleNodeView<'_>) -> Result<(), AntlrError> {
1322        Ok(())
1323    }
1324
1325    fn visit_terminal(&mut self, _node: TerminalNodeView<'_>) -> Result<(), AntlrError> {
1326        Ok(())
1327    }
1328
1329    fn visit_error_node(&mut self, _node: ErrorNodeView<'_>) -> Result<(), AntlrError> {
1330        Ok(())
1331    }
1332}
1333
1334/// Value-returning, caller-directed traversal over a completed parse tree.
1335///
1336/// Generated grammar visitors adapt typed rule and alternative callbacks to
1337/// this runtime contract. The default traversal returns the latest child's
1338/// result, matching ANTLR's base visitor behavior.
1339pub trait ParseTreeVisitor {
1340    type Result;
1341
1342    fn default_result(&mut self) -> Self::Result;
1343
1344    fn visit(&mut self, tree: Node<'_>) -> Self::Result {
1345        match tree.kind() {
1346            NodeKind::Rule => self.visit_rule(tree.as_rule().expect("rule node kind checked")),
1347            NodeKind::Terminal => {
1348                self.visit_terminal(tree.as_terminal().expect("terminal node kind checked"))
1349            }
1350            NodeKind::Error => {
1351                self.visit_error_node(tree.as_error().expect("error node kind checked"))
1352            }
1353        }
1354    }
1355
1356    fn visit_rule(&mut self, node: RuleNodeView<'_>) -> Self::Result {
1357        self.visit_children(node)
1358    }
1359
1360    fn visit_children(&mut self, node: RuleNodeView<'_>) -> Self::Result {
1361        stacker::maybe_grow(VISITOR_STACK_RED_ZONE, VISITOR_STACK_SIZE, || {
1362            let mut result = self.default_result();
1363            for child in node.children() {
1364                if !self.should_visit_next_child(node, &result) {
1365                    break;
1366                }
1367                let child_result = self.visit(child);
1368                result = self.aggregate_result(result, child_result);
1369            }
1370            result
1371        })
1372    }
1373
1374    fn visit_terminal(&mut self, _node: TerminalNodeView<'_>) -> Self::Result {
1375        self.default_result()
1376    }
1377
1378    fn visit_error_node(&mut self, _node: ErrorNodeView<'_>) -> Self::Result {
1379        self.default_result()
1380    }
1381
1382    fn aggregate_result(
1383        &mut self,
1384        _aggregate: Self::Result,
1385        next_result: Self::Result,
1386    ) -> Self::Result {
1387        next_result
1388    }
1389
1390    fn should_visit_next_child(
1391        &mut self,
1392        _node: RuleNodeView<'_>,
1393        _current_result: &Self::Result,
1394    ) -> bool {
1395        true
1396    }
1397}
1398
1399#[derive(Debug, Default)]
1400pub struct ParseTreeWalker;
1401
1402impl ParseTreeWalker {
1403    pub fn walk<L: ParseTreeListener>(listener: &mut L, tree: Node<'_>) -> Result<(), AntlrError> {
1404        enum Event {
1405            Enter(NodeId),
1406            Exit(NodeId),
1407        }
1408
1409        let storage = tree.storage;
1410        let tokens = tree.tokens;
1411        let mut stack = vec![Event::Enter(tree.id)];
1412        while let Some(event) = stack.pop() {
1413            match event {
1414                Event::Enter(id) => {
1415                    let node = storage
1416                        .node(tokens, id)
1417                        .expect("walker node ID should remain valid");
1418                    match node.kind() {
1419                        NodeKind::Rule => {
1420                            let rule = node.as_rule().expect("rule node kind checked");
1421                            listener.enter_every_rule(rule)?;
1422                            stack.push(Event::Exit(id));
1423                            stack.extend(
1424                                storage
1425                                    .child_ids(id)
1426                                    .iter()
1427                                    .rev()
1428                                    .copied()
1429                                    .map(Event::Enter),
1430                            );
1431                        }
1432                        NodeKind::Terminal => listener.visit_terminal(
1433                            node.as_terminal().expect("terminal node kind checked"),
1434                        )?,
1435                        NodeKind::Error => {
1436                            listener.visit_error_node(
1437                                node.as_error().expect("error node kind checked"),
1438                            )?;
1439                        }
1440                    }
1441                }
1442                Event::Exit(id) => {
1443                    let rule = storage
1444                        .node(tokens, id)
1445                        .and_then(Node::as_rule)
1446                        .expect("walker exit node should remain a rule");
1447                    listener.exit_every_rule(rule)?;
1448                }
1449            }
1450        }
1451        Ok(())
1452    }
1453}
1454
1455#[derive(Debug)]
1456pub struct ParsedFile {
1457    tokens: TokenStore,
1458    tree: ParseTreeStorage,
1459    root: NodeId,
1460}
1461
1462impl ParsedFile {
1463    #[must_use]
1464    pub fn new(tokens: TokenStore, mut tree: ParseTreeStorage, root: NodeId) -> Self {
1465        tree.discard_scratch();
1466        Self { tokens, tree, root }
1467    }
1468
1469    #[must_use]
1470    pub const fn tokens(&self) -> &TokenStore {
1471        &self.tokens
1472    }
1473
1474    #[must_use]
1475    pub const fn storage(&self) -> &ParseTreeStorage {
1476        &self.tree
1477    }
1478
1479    #[must_use]
1480    pub const fn root_id(&self) -> NodeId {
1481        self.root
1482    }
1483
1484    #[must_use]
1485    pub fn tree(&self) -> Node<'_> {
1486        self.tree
1487            .node(&self.tokens, self.root)
1488            .expect("parsed file root ID should remain valid")
1489    }
1490
1491    #[must_use]
1492    pub fn node(&self, id: NodeId) -> Option<Node<'_>> {
1493        self.tree.node(&self.tokens, id)
1494    }
1495
1496    #[must_use]
1497    pub fn into_parts(self) -> (TokenStore, ParseTreeStorage, NodeId) {
1498        (self.tokens, self.tree, self.root)
1499    }
1500}
1501
1502fn escape_tree_text(text: &str) -> String {
1503    let mut escaped = String::with_capacity(text.len());
1504    for ch in text.chars() {
1505        match ch {
1506            '\n' => escaped.push_str("\\n"),
1507            '\r' => escaped.push_str("\\r"),
1508            '\t' => escaped.push_str("\\t"),
1509            _ => escaped.push(ch),
1510        }
1511    }
1512    escaped
1513}
1514
1515fn stored_token_id(raw: u32) -> TokenId {
1516    TokenId::try_from(raw as usize).expect("stored token ID should fit in u32")
1517}
1518
1519#[cfg(test)]
1520#[allow(clippy::disallowed_methods)] // insta assertion macros unwrap internal I/O.
1521mod tests {
1522    use super::*;
1523    use crate::token::TokenSpec;
1524
1525    fn token(store: &mut TokenStore, token_type: i32, text: &str) -> TokenId {
1526        store
1527            .push(TokenSpec::explicit(token_type, text))
1528            .expect("test token should fit")
1529    }
1530
1531    #[test]
1532    fn stores_rule_children_in_one_pooled_range() {
1533        let mut tokens = TokenStore::new(None, "");
1534        let first = token(&mut tokens, 1, "a");
1535        let second = token(&mut tokens, 2, "b");
1536        let mut storage = ParseTreeStorage::new();
1537        let first = storage.terminal(first);
1538        let second = storage.error(second);
1539        let mut context = ParserRuleContext::new(0, -1);
1540        storage.add_child(&mut context, first);
1541        storage.add_child(&mut context, second);
1542        let root = storage.finish_rule(context);
1543        let parsed = ParsedFile::new(tokens, storage, root);
1544
1545        assert_eq!(parsed.tree().text(), "ab");
1546        assert_eq!(parsed.tree().children().count(), 2);
1547        assert_eq!(parsed.storage().stats().edges, 2);
1548        assert_eq!(parsed.storage().stats().scratch_links, 0);
1549        assert_eq!(
1550            parsed.tree().to_string_tree_with_names(&["root"]),
1551            "(root a b)"
1552        );
1553    }
1554
1555    #[test]
1556    fn labeled_terminal_children_keep_inserted_tokens_and_skip_deleted_ones() {
1557        let mut tokens = TokenStore::new(None, "");
1558        let deleted = token(&mut tokens, 1, "x");
1559        let inserted = tokens
1560            .push(TokenSpec::explicit(2, "<missing B>").with_span(usize::MAX, usize::MAX))
1561            .expect("test token should fit");
1562        let kept = token(&mut tokens, 3, "c");
1563        let mut storage = ParseTreeStorage::new();
1564        let deleted = storage.error(deleted);
1565        let inserted = storage.error(inserted);
1566        let kept = storage.terminal(kept);
1567        let mut context = ParserRuleContext::new(0, -1);
1568        storage.add_child(&mut context, deleted);
1569        storage.add_child(&mut context, inserted);
1570        storage.add_child(&mut context, kept);
1571
1572        // `terminal_children` is the raw CST view: every error node counts, so a
1573        // deleted token shifts the positions a grammar-derived index relies on.
1574        let raw = context
1575            .terminal_children(&storage, &tokens)
1576            .map(|terminal| terminal.text().to_owned())
1577            .collect::<Vec<_>>();
1578        let labeled = context
1579            .labeled_terminal_children(&storage, &tokens)
1580            .map(|terminal| terminal.text().to_owned())
1581            .collect::<Vec<_>>();
1582
1583        insta::assert_debug_snapshot!("terminal_children_raw_vs_labeled", (raw, labeled));
1584    }
1585
1586    #[test]
1587    fn context_alt_number_does_not_change_public_tree_rendering() {
1588        let tokens = TokenStore::new(None, "");
1589        let mut storage = ParseTreeStorage::new();
1590        let mut context = ParserRuleContext::new(0, -1);
1591        context.set_context_alt_number(2);
1592
1593        assert_eq!(context.alt_number(), 0);
1594        assert_eq!(context.context_alt_number(), 2);
1595        assert_eq!(
1596            context.to_string_tree_with_names(&storage, &tokens, &["root"]),
1597            "root"
1598        );
1599
1600        let root = storage.finish_rule(context);
1601        let parsed = ParsedFile::new(tokens, storage, root);
1602        let rule = parsed.tree().as_rule().expect("root rule");
1603        assert_eq!(rule.alt_number(), 0);
1604        assert_eq!(rule.context_alt_number(), 2);
1605        assert_eq!(parsed.tree().to_string_tree_with_names(&["root"]), "root");
1606    }
1607
1608    #[test]
1609    fn descendants_and_walker_preserve_antlr_order() {
1610        let mut tokens = TokenStore::new(None, "");
1611        let a = token(&mut tokens, 1, "a");
1612        let b = token(&mut tokens, 2, "b");
1613        let mut storage = ParseTreeStorage::new();
1614        let a = storage.terminal(a);
1615        let b = storage.terminal(b);
1616        let mut child = ParserRuleContext::new(1, 7);
1617        storage.add_child(&mut child, b);
1618        let child = storage.finish_rule(child);
1619        let mut root = ParserRuleContext::new(0, -1);
1620        storage.add_child(&mut root, a);
1621        storage.add_child(&mut root, child);
1622        let root = storage.finish_rule(root);
1623        let parsed = ParsedFile::new(tokens, storage, root);
1624
1625        let visited = parsed
1626            .tree()
1627            .descendants()
1628            .map(|node| match node.kind() {
1629                NodeKind::Rule => format!(
1630                    "r{}",
1631                    node.as_rule().expect("rule node kind checked").rule_index()
1632                ),
1633                NodeKind::Terminal => node
1634                    .as_terminal()
1635                    .expect("terminal node kind checked")
1636                    .text()
1637                    .to_owned(),
1638                NodeKind::Error => node
1639                    .as_error()
1640                    .expect("error node kind checked")
1641                    .text()
1642                    .to_owned(),
1643            })
1644            .collect::<Vec<_>>();
1645        assert_eq!(visited, ["r0", "a", "r1", "b"]);
1646
1647        #[derive(Default)]
1648        struct Listener(Vec<String>);
1649        impl ParseTreeListener for Listener {
1650            fn enter_every_rule(&mut self, ctx: RuleNodeView<'_>) -> Result<(), AntlrError> {
1651                self.0.push(format!("enter{}", ctx.rule_index()));
1652                Ok(())
1653            }
1654
1655            fn exit_every_rule(&mut self, ctx: RuleNodeView<'_>) -> Result<(), AntlrError> {
1656                self.0.push(format!("exit{}", ctx.rule_index()));
1657                Ok(())
1658            }
1659
1660            fn visit_terminal(&mut self, node: TerminalNodeView<'_>) -> Result<(), AntlrError> {
1661                self.0.push(node.text().to_owned());
1662                Ok(())
1663            }
1664        }
1665        let mut listener = Listener::default();
1666        ParseTreeWalker::walk(&mut listener, parsed.tree())
1667            .expect("test listener should accept every node");
1668        assert_eq!(listener.0, ["enter0", "a", "enter1", "b", "exit1", "exit0"]);
1669    }
1670
1671    fn visitor_test_tree() -> ParsedFile {
1672        let mut tokens = TokenStore::new(None, "");
1673        let a = token(&mut tokens, 1, "a");
1674        let b = token(&mut tokens, 2, "b");
1675        let error = token(&mut tokens, 3, "!");
1676        let mut storage = ParseTreeStorage::new();
1677        let a = storage.terminal(a);
1678        let b = storage.terminal(b);
1679        let error = storage.error(error);
1680        let mut child = ParserRuleContext::new(1, 7);
1681        storage.add_child(&mut child, b);
1682        let child = storage.finish_rule(child);
1683        let mut root = ParserRuleContext::new(0, -1);
1684        storage.add_child(&mut root, a);
1685        storage.add_child(&mut root, child);
1686        storage.add_child(&mut root, error);
1687        let root = storage.finish_rule(root);
1688        ParsedFile::new(tokens, storage, root)
1689    }
1690
1691    #[test]
1692    fn visitor_dispatches_and_aggregates_all_node_kinds() {
1693        #[derive(Default)]
1694        struct Visitor(Vec<String>);
1695
1696        impl ParseTreeVisitor for Visitor {
1697            type Result = Vec<String>;
1698
1699            fn default_result(&mut self) -> Self::Result {
1700                Vec::new()
1701            }
1702
1703            fn visit_rule(&mut self, node: RuleNodeView<'_>) -> Self::Result {
1704                self.0.push(format!("rule{}", node.rule_index()));
1705                self.visit_children(node)
1706            }
1707
1708            fn visit_terminal(&mut self, node: TerminalNodeView<'_>) -> Self::Result {
1709                vec![format!("terminal:{}", node.text())]
1710            }
1711
1712            fn visit_error_node(&mut self, node: ErrorNodeView<'_>) -> Self::Result {
1713                vec![format!("error:{}", node.text())]
1714            }
1715
1716            fn aggregate_result(
1717                &mut self,
1718                mut aggregate: Self::Result,
1719                next_result: Self::Result,
1720            ) -> Self::Result {
1721                aggregate.extend(next_result);
1722                aggregate
1723            }
1724        }
1725
1726        let parsed = visitor_test_tree();
1727        let mut visitor = Visitor::default();
1728        assert_eq!(
1729            visitor.visit(parsed.tree()),
1730            ["terminal:a", "terminal:b", "error:!"]
1731        );
1732        assert_eq!(visitor.0, ["rule0", "rule1"]);
1733    }
1734
1735    #[test]
1736    fn visitor_default_aggregation_returns_the_latest_child() {
1737        struct Visitor;
1738
1739        impl ParseTreeVisitor for Visitor {
1740            type Result = String;
1741
1742            fn default_result(&mut self) -> Self::Result {
1743                String::new()
1744            }
1745
1746            fn visit_terminal(&mut self, node: TerminalNodeView<'_>) -> Self::Result {
1747                node.text().to_owned()
1748            }
1749
1750            fn visit_error_node(&mut self, node: ErrorNodeView<'_>) -> Self::Result {
1751                node.text().to_owned()
1752            }
1753        }
1754
1755        let parsed = visitor_test_tree();
1756        assert_eq!(Visitor.visit(parsed.tree()), "!");
1757    }
1758
1759    #[test]
1760    fn visitor_can_short_circuit_before_any_or_later_children() {
1761        struct Visitor {
1762            limit: usize,
1763            visited: usize,
1764        }
1765
1766        impl ParseTreeVisitor for Visitor {
1767            type Result = usize;
1768
1769            fn default_result(&mut self) -> Self::Result {
1770                0
1771            }
1772
1773            fn visit_terminal(&mut self, _node: TerminalNodeView<'_>) -> Self::Result {
1774                self.visited += 1;
1775                1
1776            }
1777
1778            fn visit_error_node(&mut self, _node: ErrorNodeView<'_>) -> Self::Result {
1779                self.visited += 1;
1780                1
1781            }
1782
1783            fn aggregate_result(
1784                &mut self,
1785                aggregate: Self::Result,
1786                next_result: Self::Result,
1787            ) -> Self::Result {
1788                aggregate + next_result
1789            }
1790
1791            fn should_visit_next_child(
1792                &mut self,
1793                _node: RuleNodeView<'_>,
1794                current_result: &Self::Result,
1795            ) -> bool {
1796                *current_result < self.limit
1797            }
1798        }
1799
1800        let parsed = visitor_test_tree();
1801        let mut none = Visitor {
1802            limit: 0,
1803            visited: 0,
1804        };
1805        assert_eq!(none.visit(parsed.tree()), 0);
1806        assert_eq!(none.visited, 0);
1807
1808        let mut one = Visitor {
1809            limit: 1,
1810            visited: 0,
1811        };
1812        assert_eq!(one.visit(parsed.tree()), 1);
1813        assert_eq!(one.visited, 1);
1814    }
1815
1816    #[test]
1817    fn visitor_grows_the_stack_for_deep_rule_trees() {
1818        const DEPTH: usize = 20_000;
1819        const STACK_SIZE: usize = 256 * 1024;
1820
1821        std::thread::Builder::new()
1822            .name("visitor-stack-growth".to_owned())
1823            .stack_size(STACK_SIZE)
1824            .spawn(|| {
1825                let tokens = TokenStore::new(None, "");
1826                let mut storage = ParseTreeStorage::new();
1827                let mut child = storage.finish_rule(ParserRuleContext::new(DEPTH, -1));
1828                for rule_index in (0..DEPTH).rev() {
1829                    let mut parent = ParserRuleContext::new(rule_index, -1);
1830                    storage.add_child(&mut parent, child);
1831                    child = storage.finish_rule(parent);
1832                }
1833                let parsed = ParsedFile::new(tokens, storage, child);
1834
1835                struct Visitor;
1836                impl ParseTreeVisitor for Visitor {
1837                    type Result = usize;
1838
1839                    fn default_result(&mut self) -> Self::Result {
1840                        0
1841                    }
1842
1843                    fn visit_rule(&mut self, node: RuleNodeView<'_>) -> Self::Result {
1844                        self.visit_children(node) + 1
1845                    }
1846                }
1847
1848                assert_eq!(Visitor.visit(parsed.tree()), DEPTH + 1);
1849            })
1850            .expect("small-stack thread should start")
1851            .join()
1852            .expect("visitor should not overflow its stack");
1853    }
1854
1855    #[test]
1856    fn invocation_states_exclude_a_nonnegative_root_frame() {
1857        let tokens = TokenStore::new(None, "");
1858        let mut storage = ParseTreeStorage::new();
1859        let grandchild = storage.finish_rule(ParserRuleContext::new(2, 13));
1860        let mut child = ParserRuleContext::new(1, 7);
1861        storage.add_child(&mut child, grandchild);
1862        let child = storage.finish_rule(child);
1863        let mut root = ParserRuleContext::new(0, 4);
1864        storage.add_child(&mut root, child);
1865        let root = storage.finish_rule(root);
1866        let parsed = ParsedFile::new(tokens, storage, root);
1867
1868        let root = parsed
1869            .node(root)
1870            .and_then(Node::as_rule)
1871            .expect("root rule should be stored");
1872        let child = parsed
1873            .node(child)
1874            .and_then(Node::as_rule)
1875            .expect("child rule should be stored");
1876        let grandchild = parsed
1877            .node(grandchild)
1878            .and_then(Node::as_rule)
1879            .expect("grandchild rule should be stored");
1880
1881        assert_eq!(root.invocation_states().collect::<Vec<_>>(), []);
1882        assert_eq!(child.invocation_states().collect::<Vec<_>>(), [7]);
1883        assert_eq!(grandchild.invocation_states().collect::<Vec<_>>(), [13, 7]);
1884    }
1885
1886    #[test]
1887    fn uncommon_rule_payloads_live_in_sparse_extras() {
1888        let tokens = TokenStore::new(None, "");
1889        let mut storage = ParseTreeStorage::new();
1890        let plain = storage.finish_rule(ParserRuleContext::new(0, -1));
1891        let mut rich = ParserRuleContext::new(1, 3);
1892        rich.set_int_return("value", 42);
1893        let rich = storage.finish_rule(rich);
1894        let parsed = ParsedFile::new(tokens, storage, rich);
1895
1896        assert_eq!(parsed.storage().extra_count(), 1);
1897        assert_eq!(
1898            parsed
1899                .node(rich)
1900                .expect("rich rule should be stored")
1901                .as_rule()
1902                .expect("rich node should be a rule")
1903                .int_return("value"),
1904            Some(42)
1905        );
1906        assert!(
1907            parsed
1908                .node(plain)
1909                .expect("plain rule should be stored")
1910                .as_rule()
1911                .expect("plain node should be a rule")
1912                .int_return("value")
1913                .is_none()
1914        );
1915    }
1916
1917    #[test]
1918    fn preserves_maximum_token_id_in_nodes_and_rule_spans() {
1919        let max = TokenId::try_from(u32::MAX as usize).expect("maximum token ID should fit");
1920        let tokens = TokenStore::new(None, "");
1921        let mut storage = ParseTreeStorage::new();
1922        let terminal = storage.terminal(max);
1923        assert_eq!(storage.token_id(terminal), Some(max));
1924
1925        let mut context = ParserRuleContext::new(0, -1);
1926        context.set_start_id(max);
1927        context.set_stop_id(max);
1928        let rule = storage.finish_rule(context);
1929        let rule = storage
1930            .node(&tokens, rule)
1931            .and_then(Node::as_rule)
1932            .expect("rule should be stored");
1933        assert_eq!(rule.start_id(), Some(max));
1934        assert_eq!(rule.stop_id(), Some(max));
1935    }
1936}