Skip to main content

ktrs_syntax/tree/
builder.rs

1//! [`TreeBuilder`]: start/token/finish events in, a [`Tree`] out. Every element is a push onto
2//! each array; no per-node allocation.
3
4use super::{ElementId, NONE, TOKEN_BIT, Tree};
5use crate::SyntaxKind;
6
7#[derive(Default)]
8pub struct TreeBuilder {
9    text: String,
10    kinds: Vec<u16>,
11    starts: Vec<u32>,
12    ends: Vec<u32>,
13    parents: Vec<u32>,
14    prev_sibs: Vec<u32>,
15    /// Open nodes, innermost last, each with its most recent child so far.
16    open: Vec<(ElementId, u32)>,
17    /// The smallest capacity of the five element arrays (which always have equal lengths).
18    room: usize,
19}
20
21impl TreeBuilder {
22    pub fn new() -> TreeBuilder {
23        TreeBuilder::default()
24    }
25
26    /// Room for `elements` elements over `text_len` bytes of text, so the arrays never regrow.
27    pub fn with_capacity(elements: usize, text_len: usize) -> TreeBuilder {
28        let mut builder = TreeBuilder { text: String::with_capacity(text_len), ..TreeBuilder::default() };
29        builder.reserve(elements);
30        builder
31    }
32
33    fn reserve(&mut self, additional: usize) {
34        self.kinds.reserve(additional);
35        self.starts.reserve(additional);
36        self.ends.reserve(additional);
37        self.parents.reserve(additional);
38        self.prev_sibs.reserve(additional);
39        self.update_room();
40    }
41
42    fn update_room(&mut self) {
43        self.room = [
44            self.kinds.capacity(),
45            self.starts.capacity(),
46            self.ends.capacity(),
47            self.parents.capacity(),
48            self.prev_sibs.capacity(),
49        ]
50        .into_iter()
51        .min()
52        .unwrap_or(0);
53    }
54
55    #[inline]
56    pub fn start_node(&mut self, kind: SyntaxKind) {
57        let e = self.push(kind as u16, NONE);
58        self.open.push((e, NONE));
59    }
60
61    #[inline]
62    pub fn token(&mut self, kind: SyntaxKind, text: &str) {
63        let e = self.kinds.len() as u32;
64        self.push(kind as u16 | TOKEN_BIT, e + 1);
65        self.text.push_str(text);
66    }
67
68    #[inline]
69    pub fn finish_node(&mut self) {
70        let (e, _) = self.open.pop().expect("finish_node without start_node");
71        self.ends[e as usize] = self.kinds.len() as u32;
72    }
73
74    /// Elements pushed so far; the id the next element gets.
75    pub fn len(&self) -> ElementId {
76        self.kinds.len() as ElementId
77    }
78
79    pub fn is_empty(&self) -> bool {
80        self.kinds.is_empty()
81    }
82
83    /// A standalone copy of the finished subtree rooted at `root` (a node pushed at the current
84    /// nesting level, with nothing pushed after its end).
85    pub fn extract(&self, root: ElementId) -> Tree {
86        let r = root as usize;
87        assert_eq!(self.ends[r], self.len(), "extract of an open or non-final subtree");
88        let base = self.starts[r];
89        // The root's own parent and previous sibling lie before it: it becomes a standalone root.
90        let rebase = |ids: &[u32]| {
91            std::iter::once(NONE).chain(ids[1..].iter().map(|&x| if x == NONE { NONE } else { x - root })).collect()
92        };
93        let parents: Vec<u32> = rebase(&self.parents[r..]);
94        let prev_sibs: Vec<u32> = rebase(&self.prev_sibs[r..]);
95        Tree {
96            text: self.text[base as usize..].into(),
97            kinds: self.kinds[r..].to_vec(),
98            starts: self.starts[r..].iter().map(|s| s - base).collect(),
99            ends: self.ends[r..].iter().map(|e| e - root).collect(),
100            parents,
101            prev_sibs,
102        }
103    }
104
105    /// Appends all of `tree` as the next child of the open node: [`Self::push_subtree`] of its
106    /// root, as block copies.
107    pub fn push_tree(&mut self, tree: &Tree) {
108        let root = self.len();
109        let text_base = self.text.len() as u32;
110        let (parent, prev) = match self.open.last_mut() {
111            Some((parent, last_child)) => (*parent, std::mem::replace(last_child, root)),
112            None => (NONE, NONE),
113        };
114        let shift = |x: u32| if x == NONE { NONE } else { x + root };
115        self.kinds.extend_from_slice(&tree.kinds);
116        self.starts.extend(tree.starts.iter().map(|s| s + text_base));
117        self.ends.extend(tree.ends.iter().map(|&e| e + root));
118        self.parents.push(parent);
119        self.parents.extend(tree.parents[1..].iter().map(|&p| shift(p)));
120        self.prev_sibs.push(prev);
121        self.prev_sibs.extend(tree.prev_sibs[1..].iter().map(|&p| shift(p)));
122        self.text.push_str(&tree.text);
123        self.update_room();
124    }
125
126    /// Appends a copy of `e`'s subtree from another tree.
127    pub fn push_subtree(&mut self, tree: &Tree, e: ElementId) {
128        if tree.is_token(e) {
129            return self.token(tree.kind(e), tree.text_of(e));
130        }
131        self.start_node(tree.kind(e));
132        for child in tree.children(e) {
133            self.push_subtree(tree, child);
134        }
135        self.finish_node();
136    }
137
138    pub fn finish(self) -> Tree {
139        assert!(self.open.is_empty(), "unbalanced tree builder");
140        assert!(self.parents.iter().skip(1).all(|&p| p != NONE), "tree has more than one root");
141        Tree {
142            text: self.text.into_boxed_str(),
143            kinds: self.kinds,
144            starts: self.starts,
145            ends: self.ends,
146            parents: self.parents,
147            prev_sibs: self.prev_sibs,
148        }
149    }
150
151    #[inline]
152    fn push(&mut self, raw_kind: u16, end: u32) -> ElementId {
153        let len = self.kinds.len();
154        if len >= self.room {
155            self.reserve(len.max(64));
156        }
157        let e = len as u32;
158        let (parent, prev) = match self.open.last_mut() {
159            Some((parent, last_child)) => (*parent, std::mem::replace(last_child, e)),
160            None => (NONE, NONE),
161        };
162        let start = self.text.len() as u32;
163        // SAFETY: the five arrays all have length `len` (every mutation appends to each of them)
164        // and capacity of at least `room > len`.
165        unsafe {
166            push_unchecked(&mut self.kinds, raw_kind);
167            push_unchecked(&mut self.starts, start);
168            push_unchecked(&mut self.ends, end);
169            push_unchecked(&mut self.parents, parent);
170            push_unchecked(&mut self.prev_sibs, prev);
171        }
172        e
173    }
174}
175
176/// # Safety
177/// `v.len() < v.capacity()`.
178#[inline(always)]
179unsafe fn push_unchecked<T>(v: &mut Vec<T>, x: T) {
180    debug_assert!(v.len() < v.capacity());
181    let len = v.len();
182    // SAFETY: the slot at `len` is allocated (caller's contract) and uninitialized.
183    unsafe {
184        v.as_mut_ptr().add(len).write(x);
185        v.set_len(len + 1);
186    }
187}