Skip to main content

antlr4_runtime/
tree.rs

1use crate::errors::AntlrError;
2use crate::recognizer::Recognizer;
3use crate::token::{Token, TokenId, TokenStore, TokenView};
4use std::any::Any;
5use std::collections::BTreeMap;
6use std::fmt;
7use std::mem::size_of;
8
9const NONE: u32 = u32::MAX;
10const FLAG_MATCHED_CHILD: u8 = 1 << 0;
11const FLAG_START_PRESENT: u8 = 1 << 1;
12const FLAG_STOP_PRESENT: u8 = 1 << 2;
13
14#[repr(transparent)]
15#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
16pub struct NodeId(u32);
17
18impl NodeId {
19    pub(crate) const fn placeholder() -> Self {
20        Self(NONE)
21    }
22
23    #[must_use]
24    pub const fn index(self) -> usize {
25        self.0 as usize
26    }
27}
28
29/// Compact parser result. The tree data lives in [`ParseTreeStorage`].
30pub type ParseTree = NodeId;
31
32#[repr(u8)]
33#[derive(Clone, Copy, Debug, Eq, PartialEq)]
34pub enum NodeKind {
35    Rule,
36    Terminal,
37    Error,
38}
39
40#[derive(Debug)]
41struct ChildLink {
42    node: NodeId,
43    next: u32,
44}
45
46#[derive(Debug)]
47struct RuleExtra {
48    int_returns: BTreeMap<String, i64>,
49    exception: Option<AntlrError>,
50    attrs: Option<GeneratedAttrs>,
51}
52
53#[derive(Debug)]
54enum ParseTreeExtra {
55    Rule(RuleExtra),
56}
57
58/// Flat, structure-of-arrays concrete syntax tree storage.
59///
60/// Every node is addressed by [`NodeId`]. Rule children occupy one range in
61/// `children`; `child_links` is parser scratch used only while rule contexts
62/// are open and is never exposed as part of the completed tree.
63#[derive(Debug, Default)]
64pub struct ParseTreeStorage {
65    kinds: Vec<NodeKind>,
66    child_starts: Vec<u32>,
67    child_lens: Vec<u32>,
68    payload_a: Vec<u32>,
69    payload_b: Vec<u32>,
70    starts: Vec<u32>,
71    stops: Vec<u32>,
72    alt_numbers: Vec<u32>,
73    extra_ids: Vec<u32>,
74    parents: Vec<u32>,
75    flags: Vec<u8>,
76    children: Vec<NodeId>,
77    extras: Vec<ParseTreeExtra>,
78    child_links: Vec<ChildLink>,
79}
80
81#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
82pub struct ParseTreeStats {
83    pub nodes: usize,
84    pub edges: usize,
85    pub extras: usize,
86    pub scratch_links: usize,
87    pub allocated_bytes: usize,
88}
89
90#[derive(Clone, Copy, Debug, Eq, PartialEq)]
91pub(crate) struct ParseTreeCheckpoint {
92    nodes: usize,
93    children: usize,
94    extras: usize,
95    child_links: usize,
96}
97
98impl ParseTreeStorage {
99    #[must_use]
100    pub const fn new() -> Self {
101        Self {
102            kinds: Vec::new(),
103            child_starts: Vec::new(),
104            child_lens: Vec::new(),
105            payload_a: Vec::new(),
106            payload_b: Vec::new(),
107            starts: Vec::new(),
108            stops: Vec::new(),
109            alt_numbers: Vec::new(),
110            extra_ids: Vec::new(),
111            parents: Vec::new(),
112            flags: Vec::new(),
113            children: Vec::new(),
114            extras: Vec::new(),
115            child_links: Vec::new(),
116        }
117    }
118
119    #[must_use]
120    pub const fn node_count(&self) -> usize {
121        self.kinds.len()
122    }
123
124    #[must_use]
125    pub const fn edge_count(&self) -> usize {
126        self.children.len()
127    }
128
129    #[must_use]
130    pub const fn extra_count(&self) -> usize {
131        self.extras.len()
132    }
133
134    #[must_use]
135    pub const fn stats(&self) -> ParseTreeStats {
136        ParseTreeStats {
137            nodes: self.node_count(),
138            edges: self.edge_count(),
139            extras: self.extra_count(),
140            scratch_links: self.child_links.len(),
141            allocated_bytes: self.kinds.capacity() * size_of::<NodeKind>()
142                + self.child_starts.capacity() * size_of::<u32>()
143                + self.child_lens.capacity() * size_of::<u32>()
144                + self.payload_a.capacity() * size_of::<u32>()
145                + self.payload_b.capacity() * size_of::<u32>()
146                + self.starts.capacity() * size_of::<u32>()
147                + self.stops.capacity() * size_of::<u32>()
148                + self.alt_numbers.capacity() * size_of::<u32>()
149                + self.extra_ids.capacity() * size_of::<u32>()
150                + self.parents.capacity() * size_of::<u32>()
151                + self.flags.capacity() * size_of::<u8>()
152                + self.children.capacity() * size_of::<NodeId>()
153                + self.extras.capacity() * size_of::<ParseTreeExtra>()
154                + self.child_links.capacity() * size_of::<ChildLink>(),
155        }
156    }
157
158    pub(crate) fn reset(&mut self) {
159        self.kinds.clear();
160        self.child_starts.clear();
161        self.child_lens.clear();
162        self.payload_a.clear();
163        self.payload_b.clear();
164        self.starts.clear();
165        self.stops.clear();
166        self.alt_numbers.clear();
167        self.extra_ids.clear();
168        self.parents.clear();
169        self.flags.clear();
170        self.children.clear();
171        self.extras.clear();
172        self.child_links.clear();
173    }
174
175    pub(crate) fn release_scratch(&mut self) {
176        self.child_links.clear();
177    }
178
179    pub(crate) fn discard_scratch(&mut self) {
180        self.child_links = Vec::new();
181    }
182
183    pub(crate) const fn checkpoint(&self) -> ParseTreeCheckpoint {
184        ParseTreeCheckpoint {
185            nodes: self.kinds.len(),
186            children: self.children.len(),
187            extras: self.extras.len(),
188            child_links: self.child_links.len(),
189        }
190    }
191
192    pub(crate) fn rollback(&mut self, checkpoint: ParseTreeCheckpoint) {
193        self.kinds.truncate(checkpoint.nodes);
194        self.child_starts.truncate(checkpoint.nodes);
195        self.child_lens.truncate(checkpoint.nodes);
196        self.payload_a.truncate(checkpoint.nodes);
197        self.payload_b.truncate(checkpoint.nodes);
198        self.starts.truncate(checkpoint.nodes);
199        self.stops.truncate(checkpoint.nodes);
200        self.alt_numbers.truncate(checkpoint.nodes);
201        self.extra_ids.truncate(checkpoint.nodes);
202        self.parents.truncate(checkpoint.nodes);
203        self.flags.truncate(checkpoint.nodes);
204        self.children.truncate(checkpoint.children);
205        self.extras.truncate(checkpoint.extras);
206        self.child_links.truncate(checkpoint.child_links);
207    }
208
209    pub(crate) fn terminal(&mut self, token: TokenId) -> NodeId {
210        self.push_node(NodeRecord {
211            kind: NodeKind::Terminal,
212            payload_a: token.index() as u32,
213            ..NodeRecord::default()
214        })
215    }
216
217    pub(crate) fn error(&mut self, token: TokenId) -> NodeId {
218        self.push_node(NodeRecord {
219            kind: NodeKind::Error,
220            payload_a: token.index() as u32,
221            ..NodeRecord::default()
222        })
223    }
224
225    pub(crate) fn add_child(&mut self, context: &mut ParserRuleContext, child: NodeId) {
226        context.matched_child = true;
227        let link = self.child_links.len_u32("parse-tree scratch child links");
228        self.child_links.push(ChildLink {
229            node: child,
230            next: NONE,
231        });
232        if context.first_child == NONE {
233            context.first_child = link;
234        } else {
235            self.child_links[context.last_child as usize].next = link;
236        }
237        context.last_child = link;
238        context.child_count = context
239            .child_count
240            .checked_add(1)
241            .expect("rule child count exceeds u32");
242    }
243
244    pub(crate) fn finish_rule(&mut self, context: ParserRuleContext) -> NodeId {
245        let parent = NodeId(self.kinds.len_u32("parse-tree node pool"));
246        let child_start = self.children.len_u32("parse-tree child pool");
247        let mut link = context.first_child;
248        while link != NONE {
249            let child = &self.child_links[link as usize];
250            self.children.push(child.node);
251            self.parents[child.node.index()] = parent.0;
252            link = child.next;
253        }
254
255        let extra_id = if context.int_returns.is_empty()
256            && context.exception.is_none()
257            && context.attrs.is_none()
258        {
259            NONE
260        } else {
261            let id = self.extras.len_u32("parse-tree extra pool");
262            self.extras.push(ParseTreeExtra::Rule(RuleExtra {
263                int_returns: context.int_returns,
264                exception: context.exception,
265                attrs: context.attrs,
266            }));
267            id
268        };
269
270        self.push_node(NodeRecord {
271            kind: NodeKind::Rule,
272            child_start,
273            child_len: context.child_count,
274            payload_a: u32::try_from(context.rule_index).expect("rule index exceeds u32"),
275            payload_b: i32::try_from(context.invoking_state)
276                .expect("invoking state exceeds i32")
277                .cast_unsigned(),
278            start: context.start.map_or(NONE, |token| token.index() as u32),
279            stop: context.stop.map_or(NONE, |token| token.index() as u32),
280            alt_number: u32::try_from(context.alt_number).expect("alternative number exceeds u32"),
281            extra_id,
282            flags: (u8::from(context.matched_child) * FLAG_MATCHED_CHILD)
283                | (u8::from(context.start.is_some()) * FLAG_START_PRESENT)
284                | (u8::from(context.stop.is_some()) * FLAG_STOP_PRESENT),
285        })
286    }
287
288    fn push_node(&mut self, record: NodeRecord) -> NodeId {
289        let id = NodeId(self.kinds.len_u32("parse-tree node pool"));
290        self.kinds.push(record.kind);
291        self.child_starts.push(record.child_start);
292        self.child_lens.push(record.child_len);
293        self.payload_a.push(record.payload_a);
294        self.payload_b.push(record.payload_b);
295        self.starts.push(record.start);
296        self.stops.push(record.stop);
297        self.alt_numbers.push(record.alt_number);
298        self.extra_ids.push(record.extra_id);
299        self.parents.push(NONE);
300        self.flags.push(record.flags);
301        id
302    }
303
304    #[must_use]
305    pub fn node<'tree>(&'tree self, tokens: &'tree TokenStore, id: NodeId) -> Option<Node<'tree>> {
306        (id.index() < self.node_count()).then_some(Node {
307            storage: self,
308            tokens,
309            id,
310        })
311    }
312
313    fn kind(&self, id: NodeId) -> NodeKind {
314        self.kinds[id.index()]
315    }
316
317    fn child_ids(&self, id: NodeId) -> &[NodeId] {
318        let index = id.index();
319        let start = self.child_starts[index] as usize;
320        let len = self.child_lens[index] as usize;
321        &self.children[start..start + len]
322    }
323
324    const fn context_child_ids<'a>(
325        &'a self,
326        context: &'a ParserRuleContext,
327    ) -> ContextChildIds<'a> {
328        ContextChildIds {
329            storage: self,
330            next: context.first_child,
331            remaining: context.child_count as usize,
332        }
333    }
334
335    fn token_id(&self, id: NodeId) -> Option<TokenId> {
336        match self.kind(id) {
337            NodeKind::Terminal | NodeKind::Error => {
338                Some(stored_token_id(self.payload_a[id.index()]))
339            }
340            NodeKind::Rule => None,
341        }
342    }
343
344    fn rule_extra(&self, id: NodeId) -> Option<&RuleExtra> {
345        let extra = *self.extra_ids.get(id.index())?;
346        if extra == NONE {
347            return None;
348        }
349        match &self.extras[extra as usize] {
350            ParseTreeExtra::Rule(extra) => Some(extra),
351        }
352    }
353}
354
355#[derive(Clone, Copy)]
356struct NodeRecord {
357    kind: NodeKind,
358    child_start: u32,
359    child_len: u32,
360    payload_a: u32,
361    payload_b: u32,
362    start: u32,
363    stop: u32,
364    alt_number: u32,
365    extra_id: u32,
366    flags: u8,
367}
368
369impl Default for NodeRecord {
370    fn default() -> Self {
371        Self {
372            kind: NodeKind::Rule,
373            child_start: 0,
374            child_len: 0,
375            payload_a: 0,
376            payload_b: 0,
377            start: NONE,
378            stop: NONE,
379            alt_number: 0,
380            extra_id: NONE,
381            flags: 0,
382        }
383    }
384}
385
386trait LenU32 {
387    fn len_u32(&self, name: &str) -> u32;
388}
389
390impl<T> LenU32 for Vec<T> {
391    fn len_u32(&self, name: &str) -> u32 {
392        u32::try_from(self.len()).unwrap_or_else(|_| panic!("{name} exceeds u32"))
393    }
394}
395
396#[derive(Clone, Copy, Debug)]
397pub struct Node<'tree> {
398    storage: &'tree ParseTreeStorage,
399    tokens: &'tree TokenStore,
400    id: NodeId,
401}
402
403impl<'tree> Node<'tree> {
404    #[must_use]
405    pub const fn id(self) -> NodeId {
406        self.id
407    }
408
409    #[must_use]
410    pub fn kind(self) -> NodeKind {
411        self.storage.kind(self.id)
412    }
413
414    #[must_use]
415    pub fn as_rule(self) -> Option<RuleNodeView<'tree>> {
416        (self.kind() == NodeKind::Rule).then_some(RuleNodeView { node: self })
417    }
418
419    #[must_use]
420    pub fn as_terminal(self) -> Option<TerminalNodeView<'tree>> {
421        (self.kind() == NodeKind::Terminal).then_some(TerminalNodeView { node: self })
422    }
423
424    #[must_use]
425    pub fn as_error(self) -> Option<ErrorNodeView<'tree>> {
426        (self.kind() == NodeKind::Error).then_some(ErrorNodeView { node: self })
427    }
428
429    #[must_use]
430    pub fn children(self) -> NodeChildren<'tree> {
431        NodeChildren {
432            storage: self.storage,
433            tokens: self.tokens,
434            ids: self.storage.child_ids(self.id).iter(),
435        }
436    }
437
438    #[must_use]
439    pub fn parent(self) -> Option<Self> {
440        let parent = self.storage.parents[self.id.index()];
441        (parent != NONE)
442            .then(|| self.storage.node(self.tokens, NodeId(parent)))
443            .flatten()
444    }
445
446    #[must_use]
447    pub fn descendants(self) -> ParseTreeDescendants<'tree> {
448        ParseTreeDescendants {
449            storage: self.storage,
450            tokens: self.tokens,
451            stack: vec![self.id],
452        }
453    }
454
455    #[must_use]
456    pub fn pre_order(self) -> ParseTreeDescendants<'tree> {
457        self.descendants()
458    }
459
460    #[must_use]
461    pub fn text(self) -> String {
462        match self.kind() {
463            NodeKind::Terminal | NodeKind::Error => self
464                .storage
465                .token_id(self.id)
466                .and_then(|id| self.tokens.text(id))
467                .unwrap_or("")
468                .to_owned(),
469            NodeKind::Rule => {
470                let mut text = String::new();
471                let mut stack = self
472                    .storage
473                    .child_ids(self.id)
474                    .iter()
475                    .rev()
476                    .copied()
477                    .collect::<Vec<_>>();
478                while let Some(id) = stack.pop() {
479                    match self.storage.kind(id) {
480                        NodeKind::Rule => {
481                            stack.extend(self.storage.child_ids(id).iter().rev().copied());
482                        }
483                        NodeKind::Terminal | NodeKind::Error => text.push_str(
484                            self.storage
485                                .token_id(id)
486                                .and_then(|token| self.tokens.text(token))
487                                .unwrap_or(""),
488                        ),
489                    }
490                }
491                text
492            }
493        }
494    }
495
496    #[must_use]
497    pub fn to_string_tree_with_names<S: AsRef<str>>(self, rule_names: &[S]) -> String {
498        match self.kind() {
499            NodeKind::Rule => self
500                .as_rule()
501                .expect("rule node kind checked")
502                .to_string_tree_with_names(rule_names),
503            NodeKind::Terminal | NodeKind::Error => escape_tree_text(
504                self.storage
505                    .token_id(self.id)
506                    .and_then(|id| self.tokens.text(id))
507                    .unwrap_or(""),
508            ),
509        }
510    }
511
512    #[must_use]
513    pub fn to_string_tree<R: Recognizer>(
514        self,
515        recognizer: Option<&R>,
516        _tokens: &TokenStore,
517    ) -> String {
518        recognizer.map_or_else(
519            || self.to_string_tree_with_names::<&str>(&[]),
520            |recognizer| self.to_string_tree_with_names(recognizer.data().rule_names()),
521        )
522    }
523
524    #[must_use]
525    pub fn first_rule(self, rule_index: usize) -> Option<Self> {
526        self.descendants().find(|node| {
527            node.as_rule()
528                .is_some_and(|rule| rule.rule_index() == rule_index)
529        })
530    }
531
532    #[must_use]
533    pub fn first_rule_stop(self, rule_index: usize) -> Option<TokenView<'tree>> {
534        self.first_rule(rule_index)?.as_rule()?.stop()
535    }
536
537    #[must_use]
538    pub fn first_rule_int_return(self, rule_index: usize, name: &str) -> Option<i64> {
539        self.first_rule(rule_index)?.as_rule()?.int_return(name)
540    }
541
542    #[must_use]
543    pub fn rule_attrs<T: Any>(self) -> Option<&'tree T> {
544        self.as_rule()?.generated_attrs::<T>()
545    }
546
547    #[must_use]
548    pub fn first_error_token(self) -> Option<TokenView<'tree>> {
549        self.descendants()
550            .find_map(Node::as_error)
551            .map(ErrorNodeView::symbol)
552    }
553
554    #[must_use]
555    pub fn rule_invocation_stack<S: AsRef<str>>(
556        self,
557        rule_index: usize,
558        rule_names: &[S],
559    ) -> Option<Vec<String>> {
560        let mut stack = vec![(self.id, 0_usize)];
561        let mut names = Vec::new();
562        while let Some((id, child_index)) = stack.last_mut() {
563            if *child_index == 0 {
564                let Some(rule) = self.storage.node(self.tokens, *id).and_then(Node::as_rule) else {
565                    stack.pop();
566                    continue;
567                };
568                names.push(
569                    rule_names
570                        .get(rule.rule_index())
571                        .map_or("<unknown>", |name| name.as_ref())
572                        .to_owned(),
573                );
574                if rule.rule_index() == rule_index {
575                    names.reverse();
576                    return Some(names);
577                }
578            }
579            let children = self.storage.child_ids(*id);
580            let next = children.get(*child_index).copied();
581            *child_index += 1;
582            if let Some(child) = next {
583                if self.storage.kind(child) == NodeKind::Rule {
584                    stack.push((child, 0));
585                }
586            } else {
587                stack.pop();
588                names.pop();
589            }
590        }
591        None
592    }
593}
594
595#[derive(Clone, Debug)]
596pub struct NodeChildren<'tree> {
597    storage: &'tree ParseTreeStorage,
598    tokens: &'tree TokenStore,
599    ids: std::slice::Iter<'tree, NodeId>,
600}
601
602impl<'tree> Iterator for NodeChildren<'tree> {
603    type Item = Node<'tree>;
604
605    fn next(&mut self) -> Option<Self::Item> {
606        self.ids
607            .next()
608            .and_then(|id| self.storage.node(self.tokens, *id))
609    }
610
611    fn size_hint(&self) -> (usize, Option<usize>) {
612        self.ids.size_hint()
613    }
614}
615
616impl DoubleEndedIterator for NodeChildren<'_> {
617    fn next_back(&mut self) -> Option<Self::Item> {
618        self.ids
619            .next_back()
620            .and_then(|id| self.storage.node(self.tokens, *id))
621    }
622}
623
624impl ExactSizeIterator for NodeChildren<'_> {}
625
626#[derive(Clone, Debug)]
627pub struct ParseTreeDescendants<'tree> {
628    storage: &'tree ParseTreeStorage,
629    tokens: &'tree TokenStore,
630    stack: Vec<NodeId>,
631}
632
633impl<'tree> Iterator for ParseTreeDescendants<'tree> {
634    type Item = Node<'tree>;
635
636    fn next(&mut self) -> Option<Self::Item> {
637        let id = self.stack.pop()?;
638        self.stack
639            .extend(self.storage.child_ids(id).iter().rev().copied());
640        Some(Node {
641            storage: self.storage,
642            tokens: self.tokens,
643            id,
644        })
645    }
646}
647
648#[derive(Clone, Copy, Debug)]
649pub struct RuleNodeView<'tree> {
650    node: Node<'tree>,
651}
652
653impl<'tree> RuleNodeView<'tree> {
654    #[must_use]
655    pub const fn node(self) -> Node<'tree> {
656        self.node
657    }
658
659    #[must_use]
660    pub fn rule_index(self) -> usize {
661        self.node.storage.payload_a[self.node.id.index()] as usize
662    }
663
664    #[must_use]
665    pub fn invoking_state(self) -> isize {
666        self.node.storage.payload_b[self.node.id.index()].cast_signed() as isize
667    }
668
669    #[must_use]
670    pub fn alt_number(self) -> usize {
671        self.node.storage.alt_numbers[self.node.id.index()] as usize
672    }
673
674    #[must_use]
675    pub fn start(self) -> Option<TokenView<'tree>> {
676        self.start_id().and_then(|id| self.node.tokens.view(id))
677    }
678
679    #[must_use]
680    pub fn start_id(self) -> Option<TokenId> {
681        let index = self.node.id.index();
682        (self.node.storage.flags[index] & FLAG_START_PRESENT != 0)
683            .then(|| stored_token_id(self.node.storage.starts[index]))
684    }
685
686    #[must_use]
687    pub fn stop(self) -> Option<TokenView<'tree>> {
688        self.stop_id().and_then(|id| self.node.tokens.view(id))
689    }
690
691    #[must_use]
692    pub fn stop_id(self) -> Option<TokenId> {
693        let index = self.node.id.index();
694        (self.node.storage.flags[index] & FLAG_STOP_PRESENT != 0)
695            .then(|| stored_token_id(self.node.storage.stops[index]))
696    }
697
698    #[must_use]
699    pub fn children(self) -> NodeChildren<'tree> {
700        self.node.children()
701    }
702
703    #[must_use]
704    pub fn child_count(self) -> usize {
705        self.node.storage.child_lens[self.node.id.index()] as usize
706    }
707
708    #[must_use]
709    pub fn child_rule(self, rule_index: usize) -> Option<Self> {
710        self.child_rules(rule_index).next()
711    }
712
713    pub fn child_rules(self, rule_index: usize) -> impl DoubleEndedIterator<Item = Self> + 'tree {
714        self.children().filter_map(move |child| {
715            let rule = child.as_rule()?;
716            (rule.rule_index() == rule_index).then_some(rule)
717        })
718    }
719
720    pub fn child_rule_trees(
721        self,
722        rule_index: usize,
723    ) -> impl DoubleEndedIterator<Item = Node<'tree>> + 'tree {
724        self.child_rules(rule_index).map(Self::node)
725    }
726
727    #[must_use]
728    pub fn child_token(self, token_type: i32) -> Option<TerminalNodeView<'tree>> {
729        self.child_tokens(token_type).next()
730    }
731
732    pub fn child_tokens(
733        self,
734        token_type: i32,
735    ) -> impl DoubleEndedIterator<Item = TerminalNodeView<'tree>> + 'tree {
736        self.children().filter_map(move |child| {
737            let terminal = match child.kind() {
738                NodeKind::Terminal => child.as_terminal(),
739                NodeKind::Error => child.as_error().map(ErrorNodeView::terminal),
740                NodeKind::Rule => None,
741            }?;
742            (terminal.symbol().token_type() == token_type).then_some(terminal)
743        })
744    }
745
746    pub fn terminal_children(
747        self,
748    ) -> impl DoubleEndedIterator<Item = TerminalNodeView<'tree>> + 'tree {
749        self.children().filter_map(|child| match child.kind() {
750            NodeKind::Terminal => child.as_terminal(),
751            NodeKind::Error => child.as_error().map(ErrorNodeView::terminal),
752            NodeKind::Rule => None,
753        })
754    }
755
756    #[must_use]
757    pub fn has_token(self, token_type: i32) -> bool {
758        self.child_token(token_type).is_some()
759    }
760
761    #[must_use]
762    pub fn text(self) -> String {
763        self.node.text()
764    }
765
766    #[must_use]
767    pub fn int_return(self, name: &str) -> Option<i64> {
768        self.node
769            .storage
770            .rule_extra(self.node.id)?
771            .int_returns
772            .get(name)
773            .copied()
774    }
775
776    #[must_use]
777    pub fn generated_attrs<T: Any>(self) -> Option<&'tree T> {
778        self.node
779            .storage
780            .rule_extra(self.node.id)?
781            .attrs
782            .as_ref()?
783            .downcast_ref::<T>()
784    }
785
786    #[must_use]
787    pub fn exception(self) -> Option<&'tree AntlrError> {
788        self.node
789            .storage
790            .rule_extra(self.node.id)?
791            .exception
792            .as_ref()
793    }
794
795    #[must_use]
796    pub fn downcast_ref<T: FromRuleNode<'tree>>(self) -> Option<T> {
797        T::from_rule_node(self)
798    }
799
800    pub fn invocation_states(self) -> impl Iterator<Item = isize> + 'tree {
801        std::iter::successors(Some(self), |rule| rule.node.parent()?.as_rule())
802            .take_while(|rule| rule.node.parent().is_some() && rule.invoking_state() >= 0)
803            .map(Self::invoking_state)
804    }
805
806    #[must_use]
807    pub fn to_string_tree_with_names<S: AsRef<str>>(self, rule_names: &[S]) -> String {
808        let name = rule_names
809            .get(self.rule_index())
810            .map_or("<unknown>", |name| name.as_ref());
811        let display_name = if self.alt_number() == 0 {
812            name.to_owned()
813        } else {
814            format!("{name}:{}", self.alt_number())
815        };
816        if self.child_count() == 0 {
817            return display_name;
818        }
819        let children = self
820            .children()
821            .map(|child| child.to_string_tree_with_names(rule_names))
822            .collect::<Vec<_>>()
823            .join(" ");
824        format!("({display_name} {children})")
825    }
826
827    #[must_use]
828    pub fn to_string_tree<R: Recognizer>(self, recognizer: Option<&R>) -> String {
829        recognizer.map_or_else(
830            || self.to_string_tree_with_names::<&str>(&[]),
831            |recognizer| self.to_string_tree_with_names(recognizer.data().rule_names()),
832        )
833    }
834}
835
836#[derive(Clone, Copy, Debug)]
837pub struct TerminalNodeView<'tree> {
838    node: Node<'tree>,
839}
840
841impl<'tree> TerminalNodeView<'tree> {
842    #[must_use]
843    pub const fn node(self) -> Node<'tree> {
844        self.node
845    }
846
847    #[must_use]
848    pub fn token_id(self) -> TokenId {
849        self.node
850            .storage
851            .token_id(self.node.id)
852            .expect("terminal node should contain a token ID")
853    }
854
855    #[must_use]
856    pub fn symbol(self) -> TokenView<'tree> {
857        self.node
858            .tokens
859            .view(self.token_id())
860            .expect("terminal node token ID should remain valid")
861    }
862
863    #[must_use]
864    pub fn text(self) -> &'tree str {
865        self.node.tokens.text(self.token_id()).unwrap_or("")
866    }
867}
868
869#[derive(Clone, Copy, Debug)]
870pub struct ErrorNodeView<'tree> {
871    node: Node<'tree>,
872}
873
874impl<'tree> ErrorNodeView<'tree> {
875    #[must_use]
876    pub const fn node(self) -> Node<'tree> {
877        self.node
878    }
879
880    #[must_use]
881    pub const fn terminal(self) -> TerminalNodeView<'tree> {
882        TerminalNodeView { node: self.node }
883    }
884
885    #[must_use]
886    pub fn token_id(self) -> TokenId {
887        self.terminal().token_id()
888    }
889
890    #[must_use]
891    pub fn symbol(self) -> TokenView<'tree> {
892        self.terminal().symbol()
893    }
894
895    #[must_use]
896    pub fn text(self) -> &'tree str {
897        self.terminal().text()
898    }
899}
900
901#[derive(Debug)]
902struct ContextChildIds<'a> {
903    storage: &'a ParseTreeStorage,
904    next: u32,
905    remaining: usize,
906}
907
908impl Iterator for ContextChildIds<'_> {
909    type Item = NodeId;
910
911    fn next(&mut self) -> Option<Self::Item> {
912        if self.next == NONE {
913            return None;
914        }
915        let link = &self.storage.child_links[self.next as usize];
916        self.next = link.next;
917        self.remaining -= 1;
918        Some(link.node)
919    }
920
921    fn size_hint(&self) -> (usize, Option<usize>) {
922        (self.remaining, Some(self.remaining))
923    }
924}
925
926impl ExactSizeIterator for ContextChildIds<'_> {}
927
928/// Transient builder for one open rule.
929///
930/// This value owns no tree nodes or child vector. Child IDs are appended to
931/// parser-owned scratch links and are copied once into the global child pool
932/// when the rule completes.
933#[derive(Debug)]
934pub struct ParserRuleContext {
935    rule_index: usize,
936    invoking_state: isize,
937    alt_number: usize,
938    start: Option<TokenId>,
939    stop: Option<TokenId>,
940    int_returns: BTreeMap<String, i64>,
941    first_child: u32,
942    last_child: u32,
943    child_count: u32,
944    matched_child: bool,
945    exception: Option<AntlrError>,
946    attrs: Option<GeneratedAttrs>,
947}
948
949impl ParserRuleContext {
950    #[must_use]
951    pub const fn new(rule_index: usize, invoking_state: isize) -> Self {
952        Self {
953            rule_index,
954            invoking_state,
955            alt_number: 0,
956            start: None,
957            stop: None,
958            int_returns: BTreeMap::new(),
959            first_child: NONE,
960            last_child: NONE,
961            child_count: 0,
962            matched_child: false,
963            exception: None,
964            attrs: None,
965        }
966    }
967
968    pub(crate) const fn with_child_capacity(
969        rule_index: usize,
970        invoking_state: isize,
971        _capacity: usize,
972    ) -> Self {
973        Self::new(rule_index, invoking_state)
974    }
975
976    #[must_use]
977    pub const fn rule_index(&self) -> usize {
978        self.rule_index
979    }
980
981    #[must_use]
982    pub const fn invoking_state(&self) -> isize {
983        self.invoking_state
984    }
985
986    #[must_use]
987    pub const fn alt_number(&self) -> usize {
988        self.alt_number
989    }
990
991    pub const fn set_alt_number(&mut self, alt_number: usize) {
992        self.alt_number = alt_number;
993    }
994
995    pub fn start<'a>(&self, tokens: &'a TokenStore) -> Option<TokenView<'a>> {
996        self.start.and_then(|id| tokens.view(id))
997    }
998
999    pub(crate) const fn start_id(&self) -> Option<TokenId> {
1000        self.start
1001    }
1002
1003    pub fn stop<'a>(&self, tokens: &'a TokenStore) -> Option<TokenView<'a>> {
1004        self.stop.and_then(|id| tokens.view(id))
1005    }
1006
1007    pub(crate) const fn set_start_id(&mut self, token: TokenId) {
1008        self.start = Some(token);
1009    }
1010
1011    pub(crate) const fn set_stop_id(&mut self, token: TokenId) {
1012        self.stop = Some(token);
1013    }
1014
1015    pub(crate) const fn set_start_from_context(&mut self, other: &Self) {
1016        self.start = other.start;
1017    }
1018
1019    pub fn set_int_return(&mut self, name: impl Into<String>, value: i64) {
1020        self.int_returns.insert(name.into(), value);
1021    }
1022
1023    #[must_use]
1024    pub fn int_return(&self, name: &str) -> Option<i64> {
1025        self.int_returns.get(name).copied()
1026    }
1027
1028    pub fn set_generated_attrs(&mut self, attrs: GeneratedAttrs) {
1029        self.attrs = Some(attrs);
1030    }
1031
1032    #[must_use]
1033    pub fn generated_attrs<T: Any>(&self) -> Option<&T> {
1034        self.attrs.as_ref().and_then(GeneratedAttrs::downcast_ref)
1035    }
1036
1037    #[must_use]
1038    pub const fn exception(&self) -> Option<&AntlrError> {
1039        self.exception.as_ref()
1040    }
1041
1042    pub fn set_exception(&mut self, error: AntlrError) {
1043        self.exception = Some(error);
1044    }
1045
1046    #[must_use]
1047    pub const fn child_count(&self) -> usize {
1048        self.child_count as usize
1049    }
1050
1051    #[must_use]
1052    pub const fn has_matched_child(&self) -> bool {
1053        self.matched_child
1054    }
1055
1056    pub const fn note_matched_child(&mut self) {
1057        self.matched_child = true;
1058    }
1059
1060    pub fn child_nodes<'a>(
1061        &'a self,
1062        storage: &'a ParseTreeStorage,
1063        tokens: &'a TokenStore,
1064    ) -> impl Iterator<Item = Node<'a>> + 'a {
1065        storage
1066            .context_child_ids(self)
1067            .filter_map(move |id| storage.node(tokens, id))
1068    }
1069
1070    pub fn child_rules<'a>(
1071        &'a self,
1072        storage: &'a ParseTreeStorage,
1073        tokens: &'a TokenStore,
1074        rule_index: usize,
1075    ) -> impl Iterator<Item = RuleNodeView<'a>> + 'a {
1076        self.child_nodes(storage, tokens).filter_map(move |child| {
1077            let rule = child.as_rule()?;
1078            (rule.rule_index() == rule_index).then_some(rule)
1079        })
1080    }
1081
1082    pub fn child_rule_trees<'a>(
1083        &'a self,
1084        storage: &'a ParseTreeStorage,
1085        tokens: &'a TokenStore,
1086        rule_index: usize,
1087    ) -> impl Iterator<Item = Node<'a>> + 'a {
1088        self.child_rules(storage, tokens, rule_index)
1089            .map(RuleNodeView::node)
1090    }
1091
1092    pub fn child_tokens<'a>(
1093        &'a self,
1094        storage: &'a ParseTreeStorage,
1095        tokens: &'a TokenStore,
1096        token_type: i32,
1097    ) -> impl Iterator<Item = TerminalNodeView<'a>> + 'a {
1098        self.child_nodes(storage, tokens).filter_map(move |child| {
1099            let terminal = match child.kind() {
1100                NodeKind::Terminal => child.as_terminal(),
1101                NodeKind::Error => child.as_error().map(ErrorNodeView::terminal),
1102                NodeKind::Rule => None,
1103            }?;
1104            (terminal.symbol().token_type() == token_type).then_some(terminal)
1105        })
1106    }
1107
1108    pub fn terminal_children<'a>(
1109        &'a self,
1110        storage: &'a ParseTreeStorage,
1111        tokens: &'a TokenStore,
1112    ) -> impl Iterator<Item = TerminalNodeView<'a>> + 'a {
1113        self.child_nodes(storage, tokens)
1114            .filter_map(|child| match child.kind() {
1115                NodeKind::Terminal => child.as_terminal(),
1116                NodeKind::Error => child.as_error().map(ErrorNodeView::terminal),
1117                NodeKind::Rule => None,
1118            })
1119    }
1120
1121    #[must_use]
1122    pub fn text(&self, storage: &ParseTreeStorage, tokens: &TokenStore) -> String {
1123        self.child_nodes(storage, tokens).map(Node::text).collect()
1124    }
1125
1126    #[must_use]
1127    pub fn to_string_tree_with_names<S: AsRef<str>>(
1128        &self,
1129        storage: &ParseTreeStorage,
1130        tokens: &TokenStore,
1131        rule_names: &[S],
1132    ) -> String {
1133        let name = rule_names
1134            .get(self.rule_index)
1135            .map_or("<unknown>", |name| name.as_ref());
1136        let display_name = if self.alt_number == 0 {
1137            name.to_owned()
1138        } else {
1139            format!("{name}:{}", self.alt_number)
1140        };
1141        if self.child_count == 0 {
1142            return display_name;
1143        }
1144        let children = self
1145            .child_nodes(storage, tokens)
1146            .map(|child| child.to_string_tree_with_names(rule_names))
1147            .collect::<Vec<_>>()
1148            .join(" ");
1149        format!("({display_name} {children})")
1150    }
1151
1152    #[must_use]
1153    pub fn to_string_tree<R: Recognizer>(
1154        &self,
1155        recognizer: Option<&R>,
1156        storage: &ParseTreeStorage,
1157        tokens: &TokenStore,
1158    ) -> String {
1159        recognizer.map_or_else(
1160            || self.to_string_tree_with_names::<&str>(storage, tokens, &[]),
1161            |recognizer| {
1162                self.to_string_tree_with_names(storage, tokens, recognizer.data().rule_names())
1163            },
1164        )
1165    }
1166}
1167
1168/// Type-erased generated-rule attributes stored only for rules that use them.
1169pub struct GeneratedAttrs(Box<dyn Any>);
1170
1171impl GeneratedAttrs {
1172    #[must_use]
1173    pub fn new<T: Any>(attrs: T) -> Self {
1174        Self(Box::new(attrs))
1175    }
1176
1177    #[must_use]
1178    pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
1179        self.0.downcast_ref::<T>()
1180    }
1181}
1182
1183impl fmt::Debug for GeneratedAttrs {
1184    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1185        f.write_str("GeneratedAttrs(..)")
1186    }
1187}
1188
1189pub trait FromRuleNode<'tree>: Sized {
1190    fn from_rule_node(node: RuleNodeView<'tree>) -> Option<Self>;
1191}
1192
1193pub trait ParseTreeListener {
1194    fn enter_every_rule(&mut self, _ctx: RuleNodeView<'_>) -> Result<(), AntlrError> {
1195        Ok(())
1196    }
1197
1198    fn exit_every_rule(&mut self, _ctx: RuleNodeView<'_>) -> Result<(), AntlrError> {
1199        Ok(())
1200    }
1201
1202    fn visit_terminal(&mut self, _node: TerminalNodeView<'_>) -> Result<(), AntlrError> {
1203        Ok(())
1204    }
1205
1206    fn visit_error_node(&mut self, _node: ErrorNodeView<'_>) -> Result<(), AntlrError> {
1207        Ok(())
1208    }
1209}
1210
1211#[derive(Debug, Default)]
1212pub struct ParseTreeWalker;
1213
1214impl ParseTreeWalker {
1215    pub fn walk<L: ParseTreeListener>(listener: &mut L, tree: Node<'_>) -> Result<(), AntlrError> {
1216        enum Event {
1217            Enter(NodeId),
1218            Exit(NodeId),
1219        }
1220
1221        let storage = tree.storage;
1222        let tokens = tree.tokens;
1223        let mut stack = vec![Event::Enter(tree.id)];
1224        while let Some(event) = stack.pop() {
1225            match event {
1226                Event::Enter(id) => {
1227                    let node = storage
1228                        .node(tokens, id)
1229                        .expect("walker node ID should remain valid");
1230                    match node.kind() {
1231                        NodeKind::Rule => {
1232                            let rule = node.as_rule().expect("rule node kind checked");
1233                            listener.enter_every_rule(rule)?;
1234                            stack.push(Event::Exit(id));
1235                            stack.extend(
1236                                storage
1237                                    .child_ids(id)
1238                                    .iter()
1239                                    .rev()
1240                                    .copied()
1241                                    .map(Event::Enter),
1242                            );
1243                        }
1244                        NodeKind::Terminal => listener.visit_terminal(
1245                            node.as_terminal().expect("terminal node kind checked"),
1246                        )?,
1247                        NodeKind::Error => {
1248                            listener.visit_error_node(
1249                                node.as_error().expect("error node kind checked"),
1250                            )?;
1251                        }
1252                    }
1253                }
1254                Event::Exit(id) => {
1255                    let rule = storage
1256                        .node(tokens, id)
1257                        .and_then(Node::as_rule)
1258                        .expect("walker exit node should remain a rule");
1259                    listener.exit_every_rule(rule)?;
1260                }
1261            }
1262        }
1263        Ok(())
1264    }
1265}
1266
1267#[derive(Debug)]
1268pub struct ParsedFile {
1269    tokens: TokenStore,
1270    tree: ParseTreeStorage,
1271    root: NodeId,
1272}
1273
1274impl ParsedFile {
1275    #[must_use]
1276    pub fn new(tokens: TokenStore, mut tree: ParseTreeStorage, root: NodeId) -> Self {
1277        tree.discard_scratch();
1278        Self { tokens, tree, root }
1279    }
1280
1281    #[must_use]
1282    pub const fn tokens(&self) -> &TokenStore {
1283        &self.tokens
1284    }
1285
1286    #[must_use]
1287    pub const fn storage(&self) -> &ParseTreeStorage {
1288        &self.tree
1289    }
1290
1291    #[must_use]
1292    pub const fn root_id(&self) -> NodeId {
1293        self.root
1294    }
1295
1296    #[must_use]
1297    pub fn tree(&self) -> Node<'_> {
1298        self.tree
1299            .node(&self.tokens, self.root)
1300            .expect("parsed file root ID should remain valid")
1301    }
1302
1303    #[must_use]
1304    pub fn node(&self, id: NodeId) -> Option<Node<'_>> {
1305        self.tree.node(&self.tokens, id)
1306    }
1307
1308    #[must_use]
1309    pub fn into_parts(self) -> (TokenStore, ParseTreeStorage, NodeId) {
1310        (self.tokens, self.tree, self.root)
1311    }
1312}
1313
1314fn escape_tree_text(text: &str) -> String {
1315    let mut escaped = String::with_capacity(text.len());
1316    for ch in text.chars() {
1317        match ch {
1318            '\n' => escaped.push_str("\\n"),
1319            '\r' => escaped.push_str("\\r"),
1320            '\t' => escaped.push_str("\\t"),
1321            _ => escaped.push(ch),
1322        }
1323    }
1324    escaped
1325}
1326
1327fn stored_token_id(raw: u32) -> TokenId {
1328    TokenId::try_from(raw as usize).expect("stored token ID should fit in u32")
1329}
1330
1331#[cfg(test)]
1332mod tests {
1333    use super::*;
1334    use crate::token::TokenSpec;
1335
1336    fn token(store: &mut TokenStore, token_type: i32, text: &str) -> TokenId {
1337        store
1338            .push(TokenSpec::explicit(token_type, text))
1339            .expect("test token should fit")
1340    }
1341
1342    #[test]
1343    fn stores_rule_children_in_one_pooled_range() {
1344        let mut tokens = TokenStore::new(None, "");
1345        let first = token(&mut tokens, 1, "a");
1346        let second = token(&mut tokens, 2, "b");
1347        let mut storage = ParseTreeStorage::new();
1348        let first = storage.terminal(first);
1349        let second = storage.error(second);
1350        let mut context = ParserRuleContext::new(0, -1);
1351        storage.add_child(&mut context, first);
1352        storage.add_child(&mut context, second);
1353        let root = storage.finish_rule(context);
1354        let parsed = ParsedFile::new(tokens, storage, root);
1355
1356        assert_eq!(parsed.tree().text(), "ab");
1357        assert_eq!(parsed.tree().children().count(), 2);
1358        assert_eq!(parsed.storage().stats().edges, 2);
1359        assert_eq!(parsed.storage().stats().scratch_links, 0);
1360        assert_eq!(
1361            parsed.tree().to_string_tree_with_names(&["root"]),
1362            "(root a b)"
1363        );
1364    }
1365
1366    #[test]
1367    fn descendants_and_walker_preserve_antlr_order() {
1368        let mut tokens = TokenStore::new(None, "");
1369        let a = token(&mut tokens, 1, "a");
1370        let b = token(&mut tokens, 2, "b");
1371        let mut storage = ParseTreeStorage::new();
1372        let a = storage.terminal(a);
1373        let b = storage.terminal(b);
1374        let mut child = ParserRuleContext::new(1, 7);
1375        storage.add_child(&mut child, b);
1376        let child = storage.finish_rule(child);
1377        let mut root = ParserRuleContext::new(0, -1);
1378        storage.add_child(&mut root, a);
1379        storage.add_child(&mut root, child);
1380        let root = storage.finish_rule(root);
1381        let parsed = ParsedFile::new(tokens, storage, root);
1382
1383        let visited = parsed
1384            .tree()
1385            .descendants()
1386            .map(|node| match node.kind() {
1387                NodeKind::Rule => format!(
1388                    "r{}",
1389                    node.as_rule().expect("rule node kind checked").rule_index()
1390                ),
1391                NodeKind::Terminal => node
1392                    .as_terminal()
1393                    .expect("terminal node kind checked")
1394                    .text()
1395                    .to_owned(),
1396                NodeKind::Error => node
1397                    .as_error()
1398                    .expect("error node kind checked")
1399                    .text()
1400                    .to_owned(),
1401            })
1402            .collect::<Vec<_>>();
1403        assert_eq!(visited, ["r0", "a", "r1", "b"]);
1404
1405        #[derive(Default)]
1406        struct Listener(Vec<String>);
1407        impl ParseTreeListener for Listener {
1408            fn enter_every_rule(&mut self, ctx: RuleNodeView<'_>) -> Result<(), AntlrError> {
1409                self.0.push(format!("enter{}", ctx.rule_index()));
1410                Ok(())
1411            }
1412
1413            fn exit_every_rule(&mut self, ctx: RuleNodeView<'_>) -> Result<(), AntlrError> {
1414                self.0.push(format!("exit{}", ctx.rule_index()));
1415                Ok(())
1416            }
1417
1418            fn visit_terminal(&mut self, node: TerminalNodeView<'_>) -> Result<(), AntlrError> {
1419                self.0.push(node.text().to_owned());
1420                Ok(())
1421            }
1422        }
1423        let mut listener = Listener::default();
1424        ParseTreeWalker::walk(&mut listener, parsed.tree())
1425            .expect("test listener should accept every node");
1426        assert_eq!(listener.0, ["enter0", "a", "enter1", "b", "exit1", "exit0"]);
1427    }
1428
1429    #[test]
1430    fn invocation_states_exclude_a_nonnegative_root_frame() {
1431        let tokens = TokenStore::new(None, "");
1432        let mut storage = ParseTreeStorage::new();
1433        let grandchild = storage.finish_rule(ParserRuleContext::new(2, 13));
1434        let mut child = ParserRuleContext::new(1, 7);
1435        storage.add_child(&mut child, grandchild);
1436        let child = storage.finish_rule(child);
1437        let mut root = ParserRuleContext::new(0, 4);
1438        storage.add_child(&mut root, child);
1439        let root = storage.finish_rule(root);
1440        let parsed = ParsedFile::new(tokens, storage, root);
1441
1442        let root = parsed
1443            .node(root)
1444            .and_then(Node::as_rule)
1445            .expect("root rule should be stored");
1446        let child = parsed
1447            .node(child)
1448            .and_then(Node::as_rule)
1449            .expect("child rule should be stored");
1450        let grandchild = parsed
1451            .node(grandchild)
1452            .and_then(Node::as_rule)
1453            .expect("grandchild rule should be stored");
1454
1455        assert_eq!(root.invocation_states().collect::<Vec<_>>(), []);
1456        assert_eq!(child.invocation_states().collect::<Vec<_>>(), [7]);
1457        assert_eq!(grandchild.invocation_states().collect::<Vec<_>>(), [13, 7]);
1458    }
1459
1460    #[test]
1461    fn uncommon_rule_payloads_live_in_sparse_extras() {
1462        let tokens = TokenStore::new(None, "");
1463        let mut storage = ParseTreeStorage::new();
1464        let plain = storage.finish_rule(ParserRuleContext::new(0, -1));
1465        let mut rich = ParserRuleContext::new(1, 3);
1466        rich.set_int_return("value", 42);
1467        let rich = storage.finish_rule(rich);
1468        let parsed = ParsedFile::new(tokens, storage, rich);
1469
1470        assert_eq!(parsed.storage().extra_count(), 1);
1471        assert_eq!(
1472            parsed
1473                .node(rich)
1474                .expect("rich rule should be stored")
1475                .as_rule()
1476                .expect("rich node should be a rule")
1477                .int_return("value"),
1478            Some(42)
1479        );
1480        assert!(
1481            parsed
1482                .node(plain)
1483                .expect("plain rule should be stored")
1484                .as_rule()
1485                .expect("plain node should be a rule")
1486                .int_return("value")
1487                .is_none()
1488        );
1489    }
1490
1491    #[test]
1492    fn preserves_maximum_token_id_in_nodes_and_rule_spans() {
1493        let max = TokenId::try_from(u32::MAX as usize).expect("maximum token ID should fit");
1494        let tokens = TokenStore::new(None, "");
1495        let mut storage = ParseTreeStorage::new();
1496        let terminal = storage.terminal(max);
1497        assert_eq!(storage.token_id(terminal), Some(max));
1498
1499        let mut context = ParserRuleContext::new(0, -1);
1500        context.set_start_id(max);
1501        context.set_stop_id(max);
1502        let rule = storage.finish_rule(context);
1503        let rule = storage
1504            .node(&tokens, rule)
1505            .and_then(Node::as_rule)
1506            .expect("rule should be stored");
1507        assert_eq!(rule.start_id(), Some(max));
1508        assert_eq!(rule.stop_id(), Some(max));
1509    }
1510}