1use ktrs_syntax::{MissedTokens, 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 let root = sink.len();
55 self.bind(root_kind, &skipped_errors, sink, lazy);
56 self.skipped_errors = skipped_errors;
57 if self.current_lexeme < self.lexeme_count() {
58 let tokens = self.lex_types[self.current_lexeme..].iter().map(|kind| kind.debug_name()).collect();
59 sink.missed_tokens.push(MissedTokens { element: root, tokens, text: self.text.to_string() });
60 }
61 }
62
63 fn balance_white_spaces(&mut self) {
64 let mut last_index: i32 = 0;
65 let mut prev_index = self.production.get_lexeme_index_at(0);
67 let size = self.production.size().saturating_sub(1);
68 for i in 1..size {
69 let id = self.production.list[i];
70 let done = id < 0;
71 let item = self.production.marker(id);
72 assert!(done || item.is_error_item || item.is_done(), "Unbalanced tree: marker not done");
73
74 let binder = if item.is_error_item { EdgeBinder::DefaultRight } else { item.get_binder(done) };
75 let mut lexeme_index = item.get_lexeme_index(done);
76
77 if binder == EdgeBinder::DefaultLeft {
80 lexeme_index = self.shift_over_whitespace_forward(lexeme_index as usize) as i32;
81 self.production.marker_mut(id).set_lexeme_index(lexeme_index, done);
82 (last_index, prev_index) = (lexeme_index, lexeme_index);
83 continue;
84 }
85 let prev_production_lex_index = prev_index;
86 let mut ws_start_index = lexeme_index.max(last_index);
87 while ws_start_index > prev_production_lex_index
88 && self.is_whitespace_or_comment(self.lex_types[ws_start_index as usize - 1])
89 {
90 ws_start_index -= 1;
91 }
92 if binder == EdgeBinder::DefaultRight {
93 self.production.marker_mut(id).set_lexeme_index(ws_start_index, done);
94 (last_index, prev_index) = (ws_start_index, ws_start_index);
95 continue;
96 }
97 let ws_end_index = self.shift_over_whitespace_forward(lexeme_index as usize) as i32;
98
99 if ws_start_index != ws_end_index {
100 debug_assert!(ws_start_index < ws_end_index);
102 let (start, end) = (ws_start_index as usize, ws_end_index as usize);
103 let at_end = ws_start_index == 0 || end == self.lexeme_count();
104 let getter = |i: usize| self.token_text(start + i);
105 let edge = binder.get_edge_position(&self.lex_types[start..end], at_end, &getter);
106 lexeme_index = ws_start_index + edge as i32;
107 self.production.marker_mut(id).set_lexeme_index(lexeme_index, done);
108 } else if lexeme_index < ws_start_index {
109 lexeme_index = ws_start_index;
110 self.production.marker_mut(id).set_lexeme_index(ws_start_index, done);
111 }
112
113 last_index = lexeme_index;
114 prev_index = lexeme_index;
115 }
116 }
117
118 fn duplicate_error_items(&self, skipped: &mut Vec<bool>) {
120 skipped.clear();
121 if !self.production.has_error_items() {
123 return;
124 }
125 skipped.resize(self.production.size(), false);
126 let mut last_error_index = -1;
127 for (i, &id) in self.production.list.iter().enumerate().skip(1) {
128 if id > 0 && self.production.marker(id).is_error_item {
129 let cur_token = self.production.marker(id).lexeme;
130 if cur_token != last_error_index {
131 last_error_index = cur_token;
132 } else {
133 skipped[i] = true;
134 }
135 }
136 }
137 }
138
139 fn bind(&self, root_kind: Option<SyntaxKind>, skipped_errors: &[bool], out: &mut TreeSink, lazy: &impl LazyReparse) {
141 let list = &self.production.list;
142 let root = self.production.marker(list[0]);
143 out.start_node(root_kind.unwrap_or_else(|| kind_of(root.kind)));
144 let mut depth = 1;
145 let mut lex_index = root.lexeme.max(0) as usize;
146
147 let mut i = 1;
148 while i < list.len() {
149 let id = list[i];
150 let item = self.production.marker(id);
151 if id < 0 {
152 lex_index = self.insert_leaves(lex_index, item.done_lexeme, out, lazy);
153 if id == -list[0] {
155 break;
156 }
157 out.finish_node();
158 depth -= 1;
159 } else if item.is_error_item {
160 if !skipped_errors[i] {
161 lex_index = self.insert_leaves(lex_index, item.lexeme, out, lazy);
162 out.errors.push(self.production.message(id).unwrap_or_default().to_owned());
163 out.start_node(SyntaxKind::ERROR_ELEMENT);
164 out.finish_node();
165 }
166 } else {
167 lex_index = self.insert_leaves(lex_index, item.lexeme, out, lazy);
168 if item.collapsed {
169 lex_index = self.collapse_leaves(item.lexeme, item.done_lexeme, kind_of(item.kind), out, lazy);
170 i = list[i..].iter().position(|&x| x == -id).map_or(list.len(), |p| i + p);
171 } else {
172 let kind = kind_of(item.kind);
173 if kind == SyntaxKind::ERROR_ELEMENT {
174 out.errors.push(self.production.message(id).expect("error marker without message").to_owned());
175 }
176 out.start_node(kind);
177 depth += 1;
178 }
179 }
180 i += 1;
181 }
182 for _ in 0..depth {
184 out.finish_node();
185 }
186 }
187
188 fn insert_leaves(&self, cur_token: usize, last_idx: i32, out: &mut TreeSink, lazy: &impl LazyReparse) -> usize {
189 let last_idx = (last_idx.max(0) as usize).min(self.lexeme_count());
190 if cur_token >= last_idx {
191 return cur_token;
192 }
193 let kinds = &self.lex_types[cur_token..last_idx];
194 let starts = &self.lex_starts[cur_token..=last_idx];
195 for (i, (&kind, bounds)) in kinds.iter().zip(starts.windows(2)).enumerate() {
196 if bounds[0] < bounds[1] {
198 let text = &self.text[bounds[0] as usize..bounds[1] as usize];
199 self.create_leaf(kind, cur_token + i, cur_token + i + 1, text, out, lazy);
200 }
201 }
202 last_idx
203 }
204
205 fn collapse_leaves(&self, start: i32, end: i32, kind: SyntaxKind, out: &mut TreeSink, lazy: &impl LazyReparse) -> usize {
206 let (start, end) = (start as usize, end as usize);
207 let text = &self.text[self.lex_starts[start] as usize..self.lex_starts[end] as usize];
208 self.create_leaf(kind, start, end, text, out, lazy);
209 end
210 }
211
212 fn create_leaf(
214 &self,
215 kind: SyntaxKind,
216 start: usize,
217 end: usize,
218 text: &str,
219 out: &mut TreeSink,
220 lazy: &impl LazyReparse,
221 ) {
222 let leaf = LazyLeaf { kind, text, outer: self, start, end };
223 if !lazy(&leaf, out) {
224 out.token(kind, leaf.text);
225 }
226 }
227
228 pub(crate) fn token_text(&self, lexeme: usize) -> &str {
229 &self.text[self.lex_starts[lexeme] as usize..self.lex_starts[lexeme + 1] as usize]
230 }
231}
232
233fn kind_of(kind: Option<SyntaxKind>) -> SyntaxKind {
234 kind.expect("Unbalanced tree. Most probably caused by unbalanced markers.")
235}