1use std::fmt::{self, Write as _};
14
15use crate::error::SyntaxError;
16use crate::kind::SyntaxKind;
17use crate::lexer::Token;
18use crate::text::TextRange;
19
20#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
22pub struct NodeId(u32);
23
24#[derive(Debug, Clone, Copy, PartialEq, Eq)]
26pub enum Element {
27 Node(NodeId),
28 Token(Token),
29}
30
31#[derive(Debug, Clone)]
32struct NodeData {
33 kind: SyntaxKind,
34 range: TextRange,
35 children: Vec<Element>,
36}
37
38#[derive(Debug, Clone)]
40pub struct SyntaxTree {
41 source: String,
42 nodes: Vec<NodeData>,
43 root: NodeId,
44 errors: Vec<SyntaxError>,
45}
46
47impl SyntaxTree {
48 #[must_use]
50 pub fn text(&self) -> &str {
51 &self.source
52 }
53
54 #[must_use]
56 pub fn root(&self) -> SyntaxNode<'_> {
57 SyntaxNode {
58 tree: self,
59 id: self.root,
60 }
61 }
62
63 #[must_use]
69 pub fn errors(&self) -> &[SyntaxError] {
70 &self.errors
71 }
72
73 #[must_use]
75 pub fn has_errors(&self) -> bool {
76 !self.errors.is_empty()
77 }
78
79 #[must_use]
81 pub fn node(&self, id: NodeId) -> SyntaxNode<'_> {
82 SyntaxNode { tree: self, id }
83 }
84
85 fn data(&self, id: NodeId) -> &NodeData {
86 &self.nodes[id.0 as usize]
87 }
88}
89
90#[derive(Debug, Clone, Copy)]
92pub struct SyntaxNode<'a> {
93 tree: &'a SyntaxTree,
94 id: NodeId,
95}
96
97impl<'a> SyntaxNode<'a> {
98 #[must_use]
99 pub fn id(self) -> NodeId {
100 self.id
101 }
102
103 #[must_use]
108 pub fn tree(self) -> &'a SyntaxTree {
109 self.tree
110 }
111
112 #[must_use]
113 pub fn kind(self) -> SyntaxKind {
114 self.tree.data(self.id).kind
115 }
116
117 #[must_use]
118 pub fn range(self) -> TextRange {
119 self.tree.data(self.id).range
120 }
121
122 #[must_use]
124 pub fn text(self) -> &'a str {
125 self.range().slice(self.tree.text())
126 }
127
128 pub fn children(self) -> impl Iterator<Item = Element> + 'a {
130 self.tree.data(self.id).children.iter().copied()
131 }
132
133 pub fn child_nodes(self) -> impl Iterator<Item = SyntaxNode<'a>> + 'a {
135 let tree = self.tree;
136 self.children().filter_map(move |element| match element {
137 Element::Node(id) => Some(SyntaxNode { tree, id }),
138 Element::Token(_) => None,
139 })
140 }
141
142 pub fn child_tokens(self) -> impl Iterator<Item = Token> + 'a {
144 self.children().filter_map(|element| match element {
145 Element::Token(token) => Some(token),
146 Element::Node(_) => None,
147 })
148 }
149
150 #[must_use]
152 pub fn child_node_of(self, kind: SyntaxKind) -> Option<SyntaxNode<'a>> {
153 self.child_nodes().find(|node| node.kind() == kind)
154 }
155
156 #[must_use]
158 pub fn child_token_of(self, kind: SyntaxKind) -> Option<Token> {
159 self.child_tokens().find(|token| token.kind == kind)
160 }
161
162 #[must_use]
164 pub fn descendants(self) -> Descendants<'a> {
165 Descendants { stack: vec![self] }
166 }
167}
168
169#[derive(Debug)]
171pub struct Descendants<'a> {
172 stack: Vec<SyntaxNode<'a>>,
173}
174
175impl<'a> Iterator for Descendants<'a> {
176 type Item = SyntaxNode<'a>;
177
178 fn next(&mut self) -> Option<Self::Item> {
179 let node = self.stack.pop()?;
180 let children: Vec<_> = node.child_nodes().collect();
182 self.stack.extend(children.into_iter().rev());
183 Some(node)
184 }
185}
186
187impl fmt::Display for SyntaxTree {
188 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
190 let mut out = String::new();
191 write_node(&mut out, self.root(), 0)?;
192 f.write_str(&out)
193 }
194}
195
196fn write_node(out: &mut String, node: SyntaxNode<'_>, depth: usize) -> fmt::Result {
197 let indent = " ".repeat(depth);
198 writeln!(out, "{indent}{:?}@{}", node.kind(), node.range())?;
199 for element in node.children() {
200 match element {
201 Element::Node(id) => write_node(out, node.tree.node(id), depth + 1)?,
202 Element::Token(token) => {
203 let indent = " ".repeat(depth + 1);
204 let text = token.text(node.tree.text());
205 if text.is_empty() {
206 writeln!(out, "{indent}{:?}@{}", token.kind, token.range)?;
207 } else {
208 writeln!(out, "{indent}{:?}@{} {:?}", token.kind, token.range, text)?;
209 }
210 }
211 }
212 }
213 Ok(())
214}
215
216#[derive(Debug, Clone, Copy, PartialEq, Eq)]
223pub struct Checkpoint(usize);
224
225#[derive(Debug)]
231pub struct TreeBuilder {
232 nodes: Vec<NodeData>,
233 children: Vec<Element>,
234 stack: Vec<(SyntaxKind, usize)>,
235 last_offset: u32,
237}
238
239impl TreeBuilder {
240 #[must_use]
241 pub fn new() -> Self {
242 Self {
243 nodes: Vec::new(),
244 children: Vec::new(),
245 stack: Vec::new(),
246 last_offset: 0,
247 }
248 }
249
250 pub fn start_node(&mut self, kind: SyntaxKind) {
251 debug_assert!(kind.is_node(), "{kind:?} is a token, not a node");
252 self.stack.push((kind, self.children.len()));
253 }
254
255 #[must_use]
256 pub fn checkpoint(&self) -> Checkpoint {
257 Checkpoint(self.children.len())
258 }
259
260 pub fn start_node_at(&mut self, checkpoint: Checkpoint, kind: SyntaxKind) {
263 debug_assert!(kind.is_node(), "{kind:?} is a token, not a node");
264 debug_assert!(
265 checkpoint.0 <= self.children.len(),
266 "checkpoint outlived its buffer"
267 );
268 self.stack.push((kind, checkpoint.0));
269 }
270
271 pub fn token(&mut self, token: Token) {
272 debug_assert!(token.kind.is_token(), "{:?} is a node", token.kind);
273 self.last_offset = token.range.end();
274 self.children.push(Element::Token(token));
275 }
276
277 pub fn finish_node(&mut self) {
278 let (kind, start) = self.stack.pop().expect("finish_node without start_node");
279 let children: Vec<Element> = self.children.drain(start..).collect();
280
281 let range = children
282 .iter()
283 .map(|element| match element {
284 Element::Token(token) => token.range,
285 Element::Node(id) => self.nodes[id.0 as usize].range,
286 })
287 .reduce(TextRange::cover)
288 .unwrap_or_else(|| TextRange::empty(self.last_offset));
289
290 let id = NodeId(self.nodes.len() as u32);
291 self.nodes.push(NodeData {
292 kind,
293 range,
294 children,
295 });
296 self.children.push(Element::Node(id));
297 }
298
299 #[must_use]
306 pub fn finish(mut self, source: String, errors: Vec<SyntaxError>) -> SyntaxTree {
307 assert!(self.stack.is_empty(), "unclosed nodes remain");
308 assert_eq!(self.children.len(), 1, "expected exactly one root node");
309
310 let root = match self.children.pop().expect("checked non-empty") {
311 Element::Node(id) => id,
312 Element::Token(_) => panic!("root must be a node"),
313 };
314
315 SyntaxTree {
316 source,
317 nodes: self.nodes,
318 root,
319 errors,
320 }
321 }
322}
323
324impl Default for TreeBuilder {
325 fn default() -> Self {
326 Self::new()
327 }
328}
329
330#[cfg(test)]
331mod tests {
332 use super::*;
333
334 fn token(kind: SyntaxKind, start: u32, end: u32) -> Token {
335 Token {
336 kind,
337 range: TextRange::new(start, end),
338 }
339 }
340
341 #[test]
342 fn builds_a_nested_tree() {
343 let mut builder = TreeBuilder::new();
344 builder.start_node(SyntaxKind::SourceFile);
345 builder.start_node(SyntaxKind::PassStmt);
346 builder.token(token(SyntaxKind::PassKw, 0, 4));
347 builder.finish_node();
348 builder.token(token(SyntaxKind::Newline, 4, 5));
349 builder.finish_node();
350
351 let tree = builder.finish("pass\n".to_string(), Vec::new());
352 assert_eq!(tree.root().kind(), SyntaxKind::SourceFile);
353 assert_eq!(tree.root().range(), TextRange::new(0, 5));
354 assert_eq!(tree.text(), "pass\n");
355
356 let stmt = tree.root().child_nodes().next().expect("one child node");
357 assert_eq!(stmt.kind(), SyntaxKind::PassStmt);
358 assert_eq!(stmt.text(), "pass");
359 }
360
361 #[test]
362 fn checkpoint_wraps_already_added_children() {
363 let mut builder = TreeBuilder::new();
366 builder.start_node(SyntaxKind::SourceFile);
367 let checkpoint = builder.checkpoint();
368 builder.token(token(SyntaxKind::Ident, 0, 1));
369 builder.start_node_at(checkpoint, SyntaxKind::BinaryExpr);
370 builder.token(token(SyntaxKind::Plus, 2, 3));
371 builder.token(token(SyntaxKind::Ident, 4, 5));
372 builder.finish_node();
373 builder.finish_node();
374
375 let tree = builder.finish("a + b".to_string(), Vec::new());
376 let binary = tree.root().child_nodes().next().expect("binary expr");
377 assert_eq!(binary.kind(), SyntaxKind::BinaryExpr);
378 assert_eq!(binary.range(), TextRange::new(0, 5));
379 assert_eq!(binary.child_tokens().count(), 3);
380 }
381
382 #[test]
383 fn empty_nodes_get_a_position() {
384 let mut builder = TreeBuilder::new();
385 builder.start_node(SyntaxKind::SourceFile);
386 builder.token(token(SyntaxKind::PassKw, 0, 4));
387 builder.start_node(SyntaxKind::Block);
388 builder.finish_node();
389 builder.finish_node();
390
391 let tree = builder.finish("pass".to_string(), Vec::new());
392 let block = tree.root().child_nodes().next().expect("block");
393 assert_eq!(block.range(), TextRange::empty(4));
394 assert_eq!(block.text(), "");
395 }
396
397 #[test]
398 fn descendants_walk_in_source_order() {
399 let mut builder = TreeBuilder::new();
400 builder.start_node(SyntaxKind::SourceFile);
401 builder.start_node(SyntaxKind::VarDecl);
402 builder.token(token(SyntaxKind::VarKw, 0, 3));
403 builder.finish_node();
404 builder.start_node(SyntaxKind::PassStmt);
405 builder.token(token(SyntaxKind::PassKw, 4, 8));
406 builder.finish_node();
407 builder.finish_node();
408
409 let tree = builder.finish("var pass".to_string(), Vec::new());
410 let kinds: Vec<_> = tree.root().descendants().map(SyntaxNode::kind).collect();
411 assert_eq!(
412 kinds,
413 vec![
414 SyntaxKind::SourceFile,
415 SyntaxKind::VarDecl,
416 SyntaxKind::PassStmt
417 ]
418 );
419 }
420}