1use ktrs_syntax::{Parse, SyntaxKind};
10
11use super::binders::EdgeBinder;
12use super::psi_builder::PsiBuilder;
13use super::sink::TreeSink;
14
15pub trait LazyReparse: Fn(&LazyLeaf<'_>, &mut TreeSink) -> bool {}
18impl<F: Fn(&LazyLeaf<'_>, &mut TreeSink) -> bool> LazyReparse for F {}
19
20pub struct LazyLeaf<'a> {
22 pub kind: SyntaxKind,
23 pub text: &'a str,
24 outer: &'a PsiBuilder,
26 start: usize,
27 end: usize,
28}
29
30impl LazyLeaf<'_> {
31 pub(crate) fn relexed_builder(&self) -> PsiBuilder {
36 let (start, end) = (self.start, self.end);
37 PsiBuilder::from_lexemes(self.text, &self.outer.lex_starts[start..=end], &self.outer.orig_types[start..end])
38 }
39}
40
41impl PsiBuilder {
42 pub fn get_tree_built(&mut self, lazy: &impl LazyReparse) -> Parse {
43 let mut sink = TreeSink::new();
44 self.build_tree_into(None, &mut sink, lazy);
45 sink.finish()
46 }
47
48 pub fn build_tree_into(&mut self, root_kind: Option<SyntaxKind>, sink: &mut TreeSink, lazy: &impl LazyReparse) {
50 assert!(!self.production.is_empty(), "Parser produced no markers");
51 self.balance_white_spaces();
52 let mut skipped_errors = std::mem::take(&mut self.skipped_errors);
53 self.duplicate_error_items(&mut skipped_errors);
54 self.bind(root_kind, &skipped_errors, sink, lazy);
55 self.skipped_errors = skipped_errors;
56 }
57
58 fn balance_white_spaces(&mut self) {
59 let mut last_index: i32 = 0;
60 let mut prev_index = self.production.get_lexeme_index_at(0);
62 let size = self.production.size().saturating_sub(1);
63 for i in 1..size {
64 let id = self.production.list[i];
65 let done = id < 0;
66 let item = self.production.marker(id);
67 assert!(done || item.is_error_item || item.is_done(), "Unbalanced tree: marker not done");
68
69 let binder = if item.is_error_item { EdgeBinder::DefaultRight } else { item.get_binder(done) };
70 let mut lexeme_index = item.get_lexeme_index(done);
71
72 if binder == EdgeBinder::DefaultLeft {
75 lexeme_index = self.shift_over_whitespace_forward(lexeme_index as usize) as i32;
76 self.production.marker_mut(id).set_lexeme_index(lexeme_index, done);
77 (last_index, prev_index) = (lexeme_index, lexeme_index);
78 continue;
79 }
80 let prev_production_lex_index = prev_index;
81 let mut ws_start_index = lexeme_index.max(last_index);
82 while ws_start_index > prev_production_lex_index
83 && self.is_whitespace_or_comment(self.lex_types[ws_start_index as usize - 1])
84 {
85 ws_start_index -= 1;
86 }
87 if binder == EdgeBinder::DefaultRight {
88 self.production.marker_mut(id).set_lexeme_index(ws_start_index, done);
89 (last_index, prev_index) = (ws_start_index, ws_start_index);
90 continue;
91 }
92 let ws_end_index = self.shift_over_whitespace_forward(lexeme_index as usize) as i32;
93
94 if ws_start_index != ws_end_index {
95 debug_assert!(ws_start_index < ws_end_index);
97 let (start, end) = (ws_start_index as usize, ws_end_index as usize);
98 let at_end = ws_start_index == 0 || end == self.lexeme_count();
99 let getter = |i: usize| self.token_text(start + i);
100 let edge = binder.get_edge_position(&self.lex_types[start..end], at_end, &getter);
101 lexeme_index = ws_start_index + edge as i32;
102 self.production.marker_mut(id).set_lexeme_index(lexeme_index, done);
103 } else if lexeme_index < ws_start_index {
104 lexeme_index = ws_start_index;
105 self.production.marker_mut(id).set_lexeme_index(ws_start_index, done);
106 }
107
108 last_index = lexeme_index;
109 prev_index = lexeme_index;
110 }
111 }
112
113 fn duplicate_error_items(&self, skipped: &mut Vec<bool>) {
115 skipped.clear();
116 if !self.production.has_error_items() {
118 return;
119 }
120 skipped.resize(self.production.size(), false);
121 let mut last_error_index = -1;
122 for (i, &id) in self.production.list.iter().enumerate().skip(1) {
123 if id > 0 && self.production.marker(id).is_error_item {
124 let cur_token = self.production.marker(id).lexeme;
125 if cur_token != last_error_index {
126 last_error_index = cur_token;
127 } else {
128 skipped[i] = true;
129 }
130 }
131 }
132 }
133
134 fn bind(&self, root_kind: Option<SyntaxKind>, skipped_errors: &[bool], out: &mut TreeSink, lazy: &impl LazyReparse) {
136 let list = &self.production.list;
137 let root = self.production.marker(list[0]);
138 out.start_node(root_kind.unwrap_or_else(|| kind_of(root.kind)));
139 let mut depth = 1;
140 let mut lex_index = root.lexeme.max(0) as usize;
141
142 let mut i = 1;
143 while i < list.len() {
144 let id = list[i];
145 let item = self.production.marker(id);
146 if id < 0 {
147 lex_index = self.insert_leaves(lex_index, item.done_lexeme, out, lazy);
148 if id == -list[0] {
150 break;
151 }
152 out.finish_node();
153 depth -= 1;
154 } else if item.is_error_item {
155 if !skipped_errors[i] {
156 lex_index = self.insert_leaves(lex_index, item.lexeme, out, lazy);
157 out.errors.push(self.production.message(id).unwrap_or_default().to_owned());
158 out.start_node(SyntaxKind::ERROR_ELEMENT);
159 out.finish_node();
160 }
161 } else {
162 lex_index = self.insert_leaves(lex_index, item.lexeme, out, lazy);
163 if item.collapsed {
164 lex_index = self.collapse_leaves(item.lexeme, item.done_lexeme, kind_of(item.kind), out, lazy);
165 i = list[i..].iter().position(|&x| x == -id).map_or(list.len(), |p| i + p);
166 } else {
167 let kind = kind_of(item.kind);
168 if kind == SyntaxKind::ERROR_ELEMENT {
169 out.errors.push(self.production.message(id).expect("error marker without message").to_owned());
170 }
171 out.start_node(kind);
172 depth += 1;
173 }
174 }
175 i += 1;
176 }
177 for _ in 0..depth {
179 out.finish_node();
180 }
181 }
182
183 fn insert_leaves(&self, cur_token: usize, last_idx: i32, out: &mut TreeSink, lazy: &impl LazyReparse) -> usize {
184 let last_idx = (last_idx.max(0) as usize).min(self.lexeme_count());
185 if cur_token >= last_idx {
186 return cur_token;
187 }
188 let kinds = &self.lex_types[cur_token..last_idx];
189 let starts = &self.lex_starts[cur_token..=last_idx];
190 for (i, (&kind, bounds)) in kinds.iter().zip(starts.windows(2)).enumerate() {
191 if bounds[0] < bounds[1] {
193 let text = &self.text[bounds[0] as usize..bounds[1] as usize];
194 self.create_leaf(kind, cur_token + i, cur_token + i + 1, text, out, lazy);
195 }
196 }
197 last_idx
198 }
199
200 fn collapse_leaves(&self, start: i32, end: i32, kind: SyntaxKind, out: &mut TreeSink, lazy: &impl LazyReparse) -> usize {
201 let (start, end) = (start as usize, end as usize);
202 let text = &self.text[self.lex_starts[start] as usize..self.lex_starts[end] as usize];
203 self.create_leaf(kind, start, end, text, out, lazy);
204 end
205 }
206
207 fn create_leaf(
209 &self,
210 kind: SyntaxKind,
211 start: usize,
212 end: usize,
213 text: &str,
214 out: &mut TreeSink,
215 lazy: &impl LazyReparse,
216 ) {
217 let leaf = LazyLeaf { kind, text, outer: self, start, end };
218 if !lazy(&leaf, out) {
219 out.token(kind, leaf.text);
220 }
221 }
222
223 pub(crate) fn token_text(&self, lexeme: usize) -> &str {
224 &self.text[self.lex_starts[lexeme] as usize..self.lex_starts[lexeme + 1] as usize]
225 }
226}
227
228fn kind_of(kind: Option<SyntaxKind>) -> SyntaxKind {
229 kind.expect("Unbalanced tree. Most probably caused by unbalanced markers.")
230}