oak_core/tree/
incremental.rs

1use crate::{
2    Language, Token,
3    tree::green_tree::{GreenLeaf, GreenNode, GreenTree},
4};
5use triomphe::Arc;
6
7/// Incremental cache for preserving old green trees and optional lexical caches.
8///
9/// This struct maintains state from previous parsing operations to enable
10/// incremental reparsing when source code changes. It stores the last
11/// lexed tokens and the last parsed green tree, allowing the parser to
12/// reuse unchanged portions of the kind tree.
13#[derive(Debug)]
14pub struct IncrementalCache<'pool, L: Language> {
15    /// The green builder for constructing new nodes
16    pub pool: &'pool mut GreenBuilder<L>,
17    /// The tokens from the previous lexical analysis
18    pub last_lex: Option<Vec<Token<L::SyntaxKind>>>,
19    /// The green tree from the previous parsing operation
20    pub last_parse: Option<Arc<GreenNode<L::SyntaxKind>>>,
21}
22
23/// Green tree builder for constructing nodes from child elements.
24///
25/// This builder provides a fluent API for constructing green nodes in an
26/// incremental parsing system.
27#[derive(Debug, Clone)]
28pub struct GreenBuilder<L: Language> {
29    /// Collection of child elements (tokens and nodes) that form this green node
30    children: Vec<GreenTree<L::SyntaxKind>>,
31}
32
33impl<'pool, L: Language> IncrementalCache<'pool, L> {
34    /// Creates a new incremental cache with the provided green builder.
35    ///
36    /// # Arguments
37    ///
38    /// * `pool` - The green builder to use for constructing new nodes
39    ///
40    /// # Returns
41    ///
42    /// A new `IncrementalCache` with no previous tokens or parse tree
43    pub fn new(pool: &'pool mut GreenBuilder<L>) -> Self {
44        Self { pool, last_parse: None, last_lex: None }
45    }
46
47    /// Sets the previously lexed tokens in the cache.
48    ///
49    /// # Arguments
50    ///
51    /// * `tokens` - The tokens from a previous lexical analysis
52    ///
53    /// # Returns
54    ///
55    /// Self with the lexed tokens set
56    pub fn with_lexed(mut self, tokens: Vec<Token<L::SyntaxKind>>) -> Self {
57        self.last_lex = Some(tokens);
58        self
59    }
60
61    /// Sets the previously parsed green tree in the cache.
62    ///
63    /// # Arguments
64    ///
65    /// * `green` - The green tree from a previous parsing operation
66    ///
67    /// # Returns
68    ///
69    /// Self with the parsed tree set
70    pub fn with_parsed(mut self, green: GreenNode<L::SyntaxKind>) -> Self {
71        self.last_parse = Some(Arc::new(green));
72        self
73    }
74
75    /// Get a token from the cached lexical analysis by index.
76    ///
77    /// # Arguments
78    ///
79    /// * `index` - The index of the token to retrieve
80    ///
81    /// # Returns
82    ///
83    /// An optional reference to the token at the specified index,
84    /// or `None` if no tokens are cached or the index is out of bounds
85    pub fn get_token(&self, index: usize) -> Option<&Token<L::SyntaxKind>> {
86        match self.last_lex.as_ref() {
87            Some(s) => s.get(index),
88            None => None,
89        }
90    }
91
92    /// Get the total number of tokens in the cached lexical analysis.
93    ///
94    /// # Returns
95    ///
96    /// The number of tokens in the cache, or 0 if no tokens are cached
97    pub fn count_tokens(&self) -> usize {
98        match self.last_lex.as_ref() {
99            Some(s) => s.len(),
100            None => 0,
101        }
102    }
103}
104
105impl<L: Language> GreenBuilder<L> {
106    /// Creates a new empty green builder.
107    ///
108    /// # Examples
109    ///
110    /// ```
111    /// let builder = GreenBuilder::<K>::new();
112    /// ```
113    pub fn new(capacity: usize) -> Self {
114        Self { children: Vec::with_capacity(capacity) }
115    }
116
117    /// Adds a tokens leaf to the builder.
118    ///
119    /// # Arguments
120    ///
121    /// * `kind` - The tokens kind/type
122    /// * `len` - The tokens length in bytes
123    ///
124    /// # Examples
125    ///
126    /// ```
127    /// let builder = GreenBuilder::new().tokens(K::Identifier, 5);
128    /// ```
129    pub fn token(mut self, kind: L::SyntaxKind, len: usize) -> Self {
130        self.children.push(GreenTree::Leaf(GreenLeaf::new(kind, len)));
131        self
132    }
133
134    /// Adds an existing green tree element to the builder.
135    ///
136    /// # Arguments
137    ///
138    /// * `elem` - The green tree element to add
139    ///
140    /// # Examples
141    ///
142    /// ```
143    /// let child_node = some_green_tree;
144    /// let builder = GreenBuilder::new().push(child_node);
145    /// ```
146    pub fn push(mut self, elem: GreenTree<L::SyntaxKind>) -> Self {
147        self.children.push(elem);
148        self
149    }
150
151    /// Finishes building and creates a new green node with the specified kind.
152    ///
153    /// # Arguments
154    ///
155    /// * `kind` - The node kind/type for the finished green node
156    ///
157    /// # Returns
158    ///
159    /// A `GreenNode<K>` containing all the accumulated children.
160    ///
161    /// # Examples
162    ///
163    /// ```
164    /// let green_node = GreenBuilder::new().token(K::Number, 3).finish(K::Expression);
165    /// ```
166    pub fn finish(self, kind: L::SyntaxKind) -> Arc<GreenNode<L::SyntaxKind>> {
167        GreenNode::new(kind, self.children)
168    }
169}