lady_deirdre/syntax/tree.rs
1////////////////////////////////////////////////////////////////////////////////
2// This file is part of "Lady Deirdre", a compiler front-end foundation //
3// technology. //
4// //
5// This work is proprietary software with source-available code. //
6// //
7// To copy, use, distribute, or contribute to this work, you must agree to //
8// the terms of the General License Agreement: //
9// //
10// https://github.com/Eliah-Lakhin/lady-deirdre/blob/master/EULA.md //
11// //
12// The agreement grants a Basic Commercial License, allowing you to use //
13// this work in non-commercial and limited commercial products with a total //
14// gross revenue cap. To remove this commercial limit for one of your //
15// products, you must acquire a Full Commercial License. //
16// //
17// If you contribute to the source code, documentation, or related materials, //
18// you must grant me an exclusive license to these contributions. //
19// Contributions are governed by the "Contributions" section of the General //
20// License Agreement. //
21// //
22// Copying the work in parts is strictly forbidden, except as permitted //
23// under the General License Agreement. //
24// //
25// If you do not or cannot agree to the terms of this Agreement, //
26// do not use this work. //
27// //
28// This work is provided "as is", without any warranties, express or implied, //
29// except where such disclaimers are legally invalid. //
30// //
31// Copyright (c) 2024 Ilya Lakhin (Илья Александрович Лахин). //
32// All rights reserved. //
33////////////////////////////////////////////////////////////////////////////////
34
35use std::iter::FusedIterator;
36
37use crate::{
38 arena::{Entry, Identifiable},
39 lexis::TokenRef,
40 syntax::{AbstractNode, ErrorRef, Node, NodeRef, RefKind, SyntaxError},
41};
42
43/// An object that provides access to the syntax structure of
44/// a compilation unit.
45///
46/// The syntax structure consists of a set of [nodes](Node) forming an abstract
47/// syntax tree, and a set of syntax [errors](SyntaxError) that may occur during
48/// parsing or incremental reparsing.
49///
50/// In Lady Deirdre, instances of these objects are owned by the compilation
51/// units, rather than by the syntax tree nodes. This ownership structure allows
52/// compilation units to have full control over the syntax structure,
53/// especially for the purpose of incremental reparsing.
54///
55/// Syntax tree nodes reference their children, parents, and other nodes
56/// through a system of versioned indices ([Entry]).
57///
58/// This trait provides a low-level interface to borrow instance of syntax nodes
59/// and the syntax errors by index from the compilation unit.
60///
61/// Higher-level referential objects, such as [NodeRef] and [ErrorRef], offer
62/// a more convenient interface for borrowing these objects from the SyntaxTree.
63///
64/// Additionally, the SyntaxTree interface provides higher-level functions
65/// to retrieve the syntax tree root node, iterate through all nodes and errors
66/// currently managed by the compilation unit, and perform a depth-first
67/// traversal of the syntax tree.
68///
69/// Typically, manual implementation of this trait is unnecessary unless
70/// creating a new type of compilation unit manager.
71///
72/// To create a wrapper of an existing compilation unit,
73/// a [Syntax](crate::units::Syntax) facade-interface can be utilized,
74/// which auto-implements this trait through delegation.
75pub trait SyntaxTree: Identifiable {
76 /// Specifies the type of the tree node.
77 ///
78 /// [Node::Token] inherently specifies the lexical grammar of the language.
79 ///
80 /// [Node::parse] inherently specifies the syntax parser of the language.
81 type Node: Node;
82
83 /// Specifies the type of the iterator that walks through all node
84 /// [NodeRef] references currently managed by this SyntaxTree instance.
85 type NodeIterator<'tree>: Iterator<Item = NodeRef> + FusedIterator + 'tree
86 where
87 Self: 'tree;
88
89 /// Specifies the type of the iterator that walks through all syntax error
90 /// [ErrorRef] references currently managed by this SyntaxTree instance.
91 type ErrorIterator<'tree>: Iterator<Item = ErrorRef> + FusedIterator + 'tree
92 where
93 Self: 'tree;
94
95 /// Provides access to the root node of the syntax tree.
96 ///
97 /// **Panic**
98 ///
99 /// Depending on the implementation, this function may panic if
100 /// the SyntaxTree does not have a root node.
101 ///
102 /// However, all objects within this crate that implement
103 /// the SyntaxTree trait always have the root node regardless of the input.
104 /// Therefore, they would **never** panic.
105 #[inline(always)]
106 fn root(&self) -> &Self::Node
107 where
108 Self: Sized,
109 {
110 match self.root_node_ref().deref(self) {
111 Some(node) => node,
112 None => panic!("Syntax tree without root."),
113 }
114 }
115
116 /// Returns a [NodeRef] reference to the root node of this syntax tree.
117 fn root_node_ref(&self) -> NodeRef;
118
119 /// Returns an iterator over all nodes currently managed by this syntax tree.
120 ///
121 /// The order of iteration is not specified.
122 #[inline(always)]
123 fn nodes(&self) -> NodeIter<'_, Self>
124 where
125 Self: Sized,
126 {
127 NodeIter {
128 tree: self,
129 inner: self.node_refs(),
130 }
131 }
132
133 /// Returns an iterator of the [NodeRef] references over all nodes currently
134 /// managed by this syntax tree.
135 ///
136 /// The order of iteration is not specified.
137 fn node_refs(&self) -> Self::NodeIterator<'_>;
138
139 /// Returns an iterator over all syntax errors currently managed by
140 /// this syntax tree.
141 ///
142 /// The order of iteration is not specified.
143 #[inline(always)]
144 fn errors(&self) -> ErrorIter<'_, Self>
145 where
146 Self: Sized,
147 {
148 ErrorIter {
149 tree: self,
150 inner: self.error_refs(),
151 }
152 }
153
154 /// Returns an iterator of the [ErrorRef] references over all syntax errors
155 /// currently managed by this syntax tree.
156 ///
157 /// The order of iteration is not specified.
158 fn error_refs(&self) -> Self::ErrorIterator<'_>;
159
160 /// Performs a depth-first traverse of the syntax tree starting from
161 /// the root node.
162 ///
163 /// The `visitor` object will be called on each node entering and
164 /// leaving events, as well as the token entering event.
165 ///
166 /// The traverse algorithm will not visit descending nodes of the tree
167 /// branch if the [Visitor::enter_node] returns false. Thus, the visitor
168 /// can control the descending process.
169 ///
170 /// The algorithm relies on the [AbstractNode::children_iter] function
171 /// to determine the node's children to descend to, which in turn relies on
172 /// the node's captures description.
173 ///
174 /// In other words, the traverser will only visit the nodes for which you
175 /// have specified `#[child]` attribute:
176 ///
177 /// ```ignore
178 /// #[derive(Node)]
179 /// enum MyNode {
180 /// #[rule(...)]
181 /// SomeVariant {
182 /// #[child]
183 /// child_1: NodeRef, // will be visited
184 /// #[child]
185 /// child_2: NodeRef, // will be visited
186 /// not_a_child: NodeRef, // will not be visited
187 /// }
188 /// }
189 /// ```
190 #[inline(always)]
191 fn traverse_tree(&self, visitor: &mut impl Visitor)
192 where
193 Self: Sized,
194 {
195 self.traverse_subtree(&self.root_node_ref(), visitor);
196 }
197
198 /// Performs a depth-first traverse of a branch of the syntax tree.
199 ///
200 /// The `top` parameter specifies a reference into the top node of
201 /// the branch.
202 ///
203 /// For details, see [SyntaxTree::traverse_tree].
204 fn traverse_subtree(&self, top: &NodeRef, visitor: &mut impl Visitor)
205 where
206 Self: Sized,
207 {
208 if visitor.enter_node(top) {
209 let node: &Self::Node = match top.deref(self) {
210 Some(node) => node,
211 None => return,
212 };
213
214 for child in node.children_iter() {
215 match child.kind() {
216 RefKind::Token => visitor.visit_token(child.as_token_ref()),
217 RefKind::Node => self.traverse_subtree(child.as_node_ref(), visitor),
218 }
219 }
220 }
221
222 visitor.leave_node(top)
223 }
224
225 /// Checks if the node referred to by the versioned index exists in this
226 /// syntax tree.
227 fn has_node(&self, entry: &Entry) -> bool;
228
229 /// Provides immutable access to the node referred to by the versioned index.
230 ///
231 /// If the index parameter `entry` is not valid, returns None.
232 fn get_node(&self, entry: &Entry) -> Option<&Self::Node>;
233
234 /// Provides mutable access to the node referred to by the versioned index.
235 ///
236 /// If the index parameter `entry` is not valid, returns None.
237 fn get_node_mut(&mut self, entry: &Entry) -> Option<&mut Self::Node>;
238
239 /// Checks if the syntax error referred to by the versioned index exists in
240 /// this syntax tree.
241 fn has_error(&self, entry: &Entry) -> bool;
242
243 /// Provides access to the syntax error referred to by the versioned index.
244 ///
245 /// If the index parameter `entry` is not valid, returns None.
246 fn get_error(&self, entry: &Entry) -> Option<&SyntaxError>;
247}
248
249/// An iterator over all nodes of the [SyntaxTree].
250///
251/// This object is created by the [SyntaxTree::nodes] function.
252pub struct NodeIter<'tree, T: SyntaxTree> {
253 tree: &'tree T,
254 inner: <T as SyntaxTree>::NodeIterator<'tree>,
255}
256
257impl<'tree, T: SyntaxTree> Iterator for NodeIter<'tree, T> {
258 type Item = &'tree <T as SyntaxTree>::Node;
259
260 #[inline(always)]
261 fn next(&mut self) -> Option<Self::Item> {
262 loop {
263 let next = self.inner.next()?;
264
265 let Some(node) = self.tree.get_node(&next.entry) else {
266 continue;
267 };
268
269 return Some(node);
270 }
271 }
272}
273
274impl<'tree, T: SyntaxTree> FusedIterator for NodeIter<'tree, T> {}
275
276/// An iterator over all syntax errors of the [SyntaxTree].
277///
278/// This object is created by the [SyntaxTree::errors] function.
279pub struct ErrorIter<'tree, T: SyntaxTree> {
280 tree: &'tree T,
281 inner: <T as SyntaxTree>::ErrorIterator<'tree>,
282}
283
284impl<'tree, T: SyntaxTree> Iterator for ErrorIter<'tree, T> {
285 type Item = &'tree SyntaxError;
286
287 #[inline(always)]
288 fn next(&mut self) -> Option<Self::Item> {
289 loop {
290 let next = self.inner.next()?;
291
292 let Some(error) = self.tree.get_error(&next.entry) else {
293 continue;
294 };
295
296 return Some(error);
297 }
298 }
299}
300
301impl<'tree, T: SyntaxTree> FusedIterator for ErrorIter<'tree, T> {}
302
303/// Visits individual nodes and tokens during the syntax tree
304/// depth-first traversing.
305///
306/// See [SyntaxTree::traverse_tree] for details.
307pub trait Visitor {
308 /// Triggers when the traverser visits a token child of a node.
309 ///
310 /// ```ignore
311 /// #[derive(Node)]
312 /// enum MyNode {
313 /// #[rule(...)]
314 /// SomeVariant {
315 /// #[child]
316 /// node_child: NodeRef,
317 /// #[child]
318 /// token_child: TokenRef, // <- when this type of children is visited
319 /// }
320 /// }
321 /// ```
322 fn visit_token(&mut self, token_ref: &TokenRef);
323
324 /// Triggers when the traverser enters a node.
325 ///
326 /// ```ignore
327 /// #[derive(Node)]
328 /// enum MyNode {
329 /// #[rule(...)]
330 /// SomeVariant {
331 /// #[child]
332 /// node_child: NodeRef, // <- when this type of children is visited
333 /// #[child]
334 /// token_child: TokenRef,
335 /// }
336 /// }
337 /// ```
338 ///
339 /// Returning false prevents the traverser further descending into
340 /// the node's sub-branch.
341 fn enter_node(&mut self, node_ref: &NodeRef) -> bool;
342
343 /// Triggers when the traverser leaves a node.
344 ///
345 /// In practice, this function observes depth-first traversing
346 /// in reverse order.
347 fn leave_node(&mut self, node_ref: &NodeRef);
348}