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}