1use crate::{
2 Language,
3 errors::OakError,
4 lexer::{LexOutput, Token, Tokens},
5 memory::arena::SyntaxArena,
6 source::Source,
7 tree::{Cursor, GreenLeaf, GreenNode, GreenTree},
8};
9use core::range::Range;
10use triomphe::Arc;
11
12pub fn deep_clone_node<'a, L: Language>(node: &'a GreenNode<'a, L>, arena: &'a SyntaxArena) -> &'a GreenNode<'a, L> {
17 let children_iter = node.children.iter().map(|child| match child {
18 GreenTree::Node(n) => GreenTree::Node(deep_clone_node(n, arena)),
19 GreenTree::Leaf(l) => GreenTree::Leaf(*l),
20 });
21
22 let slice = arena.alloc_slice_fill_iter(node.children.len(), children_iter);
23 let new_node = GreenNode::new(node.kind, slice);
24 arena.alloc(new_node)
25}
26
27pub struct TokenSource<L: Language> {
29 tokens: Tokens<L>,
30 index: usize,
31}
32
33impl<L: Language> Clone for TokenSource<L> {
34 fn clone(&self) -> Self {
35 Self { tokens: self.tokens.clone(), index: self.index }
36 }
37}
38
39impl<L: Language> TokenSource<L> {
40 pub fn new(tokens: Tokens<L>) -> Self {
42 Self { tokens, index: 0 }
43 }
44
45 #[inline]
47 pub fn current(&self) -> Option<&Token<L::TokenType>> {
48 self.tokens.get(self.index)
49 }
50
51 #[inline]
53 pub fn peek_at(&self, offset: usize) -> Option<&Token<L::TokenType>> {
54 self.tokens.get(self.index + offset)
55 }
56
57 #[inline]
59 pub fn advance(&mut self) {
60 self.index += 1;
61 }
62
63 #[inline]
65 pub fn is_end(&self) -> bool {
66 self.index >= self.tokens.len()
67 }
68
69 #[inline]
71 pub fn index(&self) -> usize {
72 self.index
73 }
74
75 #[inline]
77 pub fn set_index(&mut self, index: usize) {
78 self.index = index;
79 }
80}
81
82pub struct TreeSink<'a, L: Language> {
84 arena: &'a SyntaxArena,
85 children: Vec<GreenTree<'a, L>>,
86}
87
88impl<'a, L: Language> TreeSink<'a, L> {
89 pub fn new(arena: &'a SyntaxArena, capacity_hint: usize) -> Self {
91 Self { arena, children: Vec::with_capacity(capacity_hint) }
92 }
93
94 pub fn push_leaf(&mut self, kind: L::TokenType, len: usize) {
96 self.children.push(GreenTree::Leaf(GreenLeaf::new(kind, len as u32)));
97 }
98
99 pub fn push_node(&mut self, node: &'a GreenNode<'a, L>) {
101 self.children.push(GreenTree::Node(node));
102 }
103
104 pub fn checkpoint(&self) -> usize {
106 self.children.len()
107 }
108
109 pub fn finish_node(&mut self, checkpoint: usize, kind: L::ElementType) -> &'a GreenNode<'a, L> {
111 let children_slice = self.arena.alloc_slice_copy(&self.children[checkpoint..]);
112 self.children.truncate(checkpoint);
113 let node = GreenNode::new(kind, children_slice);
114 let node_ref = self.arena.alloc(node);
115 self.children.push(GreenTree::Node(node_ref));
116 node_ref
117 }
118}
119
120pub struct IncrementalContext<'a, L: Language> {
122 cursor: Cursor<'a, L>,
123 edits: Vec<(Range<usize>, isize)>,
126}
127
128impl<'a, L: Language> IncrementalContext<'a, L> {
129 pub fn new(old_root: &'a GreenNode<'a, L>, edits: &[crate::source::TextEdit]) -> Self {
131 let mut sorted_edits: Vec<_> = edits.iter().collect();
132 sorted_edits.sort_by_key(|e| e.span.start);
133
134 let mut cumulative_delta = 0isize;
135 let mut processed_edits = Vec::with_capacity(edits.len());
136
137 for edit in sorted_edits {
138 let old_len = edit.span.end - edit.span.start;
139 let new_len = edit.text.len();
140 cumulative_delta += new_len as isize - old_len as isize;
141 processed_edits.push((edit.span, cumulative_delta));
142 }
143
144 Self { cursor: Cursor::new(old_root), edits: processed_edits }
145 }
146
147 fn map_new_to_old(&self, new_pos: usize) -> Option<usize> {
148 let mut current_delta = 0isize;
149
150 for (old_range, cumulative_delta) in &self.edits {
151 let new_start = (old_range.start as isize + current_delta) as usize;
152 let edit_delta = *cumulative_delta - current_delta;
153 let new_end = (old_range.end as isize + current_delta + edit_delta) as usize;
154
155 if new_pos < new_start {
156 return Some((new_pos as isize - current_delta) as usize);
157 }
158 else if new_pos < new_end {
159 return None;
161 }
162
163 current_delta = *cumulative_delta;
164 }
165
166 Some((new_pos as isize - current_delta) as usize)
167 }
168
169 fn is_dirty(&self, old_start: usize, old_end: usize) -> bool {
170 for (old_range, _) in &self.edits {
171 if old_start < old_range.end && old_end > old_range.start {
173 return true;
174 }
175 }
176 false
177 }
178}
179
180pub struct ParserState<'a, L: Language, S: Source + ?Sized = crate::source::SourceText> {
182 pub tokens: TokenSource<L>,
184
185 pub sink: TreeSink<'a, L>,
187
188 pub incremental: Option<IncrementalContext<'a, L>>,
190
191 pub errors: Vec<OakError>,
193 pub source: &'a S,
195}
196
197impl<'a, L: Language, S: Source + ?Sized> ParserState<'a, L, S> {
198 pub fn source_url(&self) -> Option<crate::source::Url> {
200 self.source.url()
201 }
202
203 pub fn new(arena: &'a SyntaxArena, lex_output: LexOutput<L>, source: &'a S, capacity_hint: usize) -> Self {
211 let (tokens, mut errors) = match lex_output.result {
212 Ok(tokens) => (tokens, Vec::new()),
213 Err(e) => (Arc::from(Vec::new()), vec![e]),
214 };
215 errors.extend(lex_output.diagnostics);
216
217 Self { tokens: TokenSource::new(tokens), sink: TreeSink::new(arena, capacity_hint), incremental: None, errors, source }
218 }
219
220 pub fn nested(&self) -> ParserState<'a, L, S> {
223 ParserState { tokens: self.tokens.clone(), sink: TreeSink::new(self.sink.arena, 1024), incremental: None, errors: Vec::new(), source: self.source }
224 }
225
226 pub fn peek_text(&self) -> Option<std::borrow::Cow<'_, str>> {
228 self.current().map(|t| self.source.get_text_in(t.span))
229 }
230
231 pub fn promote(&mut self, node: &'a GreenNode<'a, L>) -> &'a GreenNode<'a, L> {
234 deep_clone_node(node, self.sink.arena)
235 }
236
237 pub fn set_incremental(&mut self, old: &'a GreenNode<'a, L>, edits: &[crate::source::TextEdit]) {
243 self.incremental = Some(IncrementalContext::new(old, edits));
244 }
245
246 pub fn current_offset(&self) -> usize {
250 self.tokens.current().map(|t| t.span.start).unwrap_or_else(|| self.source.length())
251 }
252
253 pub fn syntax_error(&mut self, message: impl Into<String>) -> OakError {
255 let err = OakError::syntax_error(message, self.current_offset(), self.source.url());
256 self.errors.push(err.clone());
257 err
258 }
259
260 pub fn record_unexpected_token(&mut self, token: impl Into<String>) {
262 let err = OakError::unexpected_token(token, self.current_offset(), self.source.url());
263 self.errors.push(err);
264 }
265
266 pub fn record_expected(&mut self, expected: impl Into<String>) {
268 let offset = self.tokens.current().map(|t| t.span.start).unwrap_or(self.source.length());
269 let err = OakError::expected_token(expected, offset, self.source.url());
270 self.errors.push(err);
271 }
272
273 pub fn record_expected_name(&mut self, name_kind: impl Into<String>) {
275 let offset = self.tokens.current().map(|t| t.span.start).unwrap_or(self.source.length());
276 let err = OakError::expected_name(name_kind, offset, self.source.url());
277 self.errors.push(err);
278 }
279
280 pub fn record_trailing_comma_not_allowed(&mut self) {
282 let offset = self.tokens.current().map(|t| t.span.start).unwrap_or(self.source.length());
283 let err = OakError::trailing_comma_not_allowed(offset, self.source.url());
284 self.errors.push(err);
285 }
286
287 pub fn record_unexpected_eof(&mut self) {
289 let offset = self.source.length();
290 let err = OakError::unexpected_eof(offset, self.source.url());
291 self.errors.push(err);
292 }
293
294 pub fn unexpected_eof(&mut self) -> OakError {
296 let offset = self.source.length();
297 let err = OakError::unexpected_eof(offset, self.source.url());
298 self.errors.push(err.clone());
299 err
300 }
301
302 #[inline]
306 pub fn current(&self) -> Option<&Token<L::TokenType>> {
307 self.tokens.current()
308 }
309
310 #[inline]
312 pub fn peek_kind(&self) -> Option<L::TokenType> {
313 self.current().map(|t| t.kind)
314 }
315
316 #[inline]
318 pub fn peek_at(&self, offset: usize) -> Option<&Token<L::TokenType>> {
319 self.tokens.peek_at(offset)
320 }
321
322 #[inline]
324 pub fn peek_kind_at(&self, offset: usize) -> Option<L::TokenType> {
325 self.tokens.peek_at(offset).map(|t| t.kind)
326 }
327
328 #[inline]
330 pub fn not_at_end(&self) -> bool {
331 !self.tokens.is_end()
332 }
333
334 #[inline]
336 pub fn at(&self, kind: L::TokenType) -> bool {
337 self.peek_kind() == Some(kind)
338 }
339
340 pub fn advance(&mut self) {
342 self.tokens.advance();
343 }
344
345 pub fn advance_until(&mut self, kind: L::TokenType) {
347 while self.not_at_end() && !self.at(kind) {
348 self.advance();
349 }
350 }
351
352 pub fn advance_until_any(&mut self, kinds: &[L::TokenType]) {
354 while self.not_at_end() && !kinds.iter().any(|&k| self.at(k)) {
355 self.advance();
356 }
357 }
358
359 pub fn bump(&mut self)
361 where
362 L::ElementType: From<L::TokenType>,
363 {
364 if let Some(token) = self.current() {
365 self.sink.push_leaf(token.kind, token.length());
366 self.tokens.advance();
367 }
368 }
369
370 pub fn eat(&mut self, kind: L::TokenType) -> bool
373 where
374 L::ElementType: From<L::TokenType>,
375 {
376 if self.at(kind) {
377 self.bump();
378 true
379 }
380 else {
381 false
382 }
383 }
384
385 pub fn expect(&mut self, kind: L::TokenType) -> Result<(), OakError>
388 where
389 L::ElementType: From<L::TokenType>,
390 {
391 if self.eat(kind) {
392 Ok(())
393 }
394 else {
395 let err = OakError::expected_token(format!("{:?}", kind), self.current_offset(), self.source.url());
396 self.errors.push(err.clone());
397 Err(err)
398 }
399 }
400
401 pub fn checkpoint(&self) -> usize {
405 self.sink.checkpoint()
406 }
407
408 pub fn finish_at(&mut self, checkpoint: usize, kind: L::ElementType) -> &'a GreenNode<'a, L> {
410 self.sink.finish_node(checkpoint, kind)
411 }
412
413 pub fn push_child(&mut self, node: &'a GreenNode<'a, L>) {
415 self.sink.push_node(node);
416 }
417
418 pub fn try_reuse(&mut self, kind: L::ElementType) -> bool {
421 let Some(inc) = &mut self.incremental
422 else {
423 return false;
424 };
425 let current_index = self.tokens.index();
426 let new_pos = self.tokens.current().map(|t| t.span.start).unwrap_or(self.source.length());
427
428 #[cfg(test)]
429 println!("try_reuse: kind={:?}, new_pos={}", kind, new_pos);
430
431 let Some(target_old_pos) = inc.map_new_to_old(new_pos)
432 else {
433 return false;
434 };
435
436 #[cfg(test)]
437 println!("Trying to reuse node at pos {}: {:?}", new_pos, kind);
438
439 let mut steps = 0;
440 const MAX_STEPS: usize = 100;
441
442 loop {
443 let start = inc.cursor.offset();
444 let end = inc.cursor.end_offset();
445
446 if start == target_old_pos {
447 if let Some(node) = inc.cursor.as_node() {
448 if node.kind == kind {
449 if !inc.is_dirty(start, end) {
450 let node_len = node.text_len() as usize;
452
453 let mut lookahead = 0;
455 let mut current_pos = new_pos;
456 let target_new_end = new_pos + node_len;
457
458 while let Some(t) = self.tokens.peek_at(lookahead) {
459 if t.span.start != current_pos {
460 break;
462 }
463 current_pos = t.span.end;
464
465 if t.span.end == target_new_end {
466 let tokens_consumed = lookahead + 1;
468 let new_node = deep_clone_node(node, self.sink.arena);
469 self.sink.push_node(new_node);
470 self.tokens.set_index(current_index + tokens_consumed);
471 inc.cursor.step_over();
472 return true;
473 }
474 else if t.span.end > target_new_end {
475 break;
476 }
477 lookahead += 1;
478 }
479 }
480 }
481 }
482 if !inc.cursor.step_into() && !inc.cursor.step_next() {
483 return false;
484 }
485 }
486 else if start < target_old_pos && end > target_old_pos {
487 if !inc.cursor.step_into() && !inc.cursor.step_next() {
488 return false;
489 }
490 }
491 else if end <= target_old_pos {
492 if !inc.cursor.step_next() {
493 return false;
494 }
495 }
496 else {
497 return false;
498 }
499
500 steps += 1;
501 if steps > MAX_STEPS {
502 return false;
503 }
504 }
505 }
506
507 pub fn finish(self, result: Result<&'a GreenNode<'a, L>, OakError>) -> crate::parser::ParseOutput<'a, L> {
509 crate::errors::OakDiagnostics { result, diagnostics: self.errors }
510 }
511
512 pub fn incremental_node<F>(&mut self, kind: L::ElementType, f: F) -> Result<(), OakError>
519 where
520 F: FnOnce(&mut Self) -> Result<(), OakError>,
521 {
522 if self.try_reuse(kind) {
523 return Ok(());
524 }
525
526 let checkpoint = self.checkpoint();
527 let res = f(self);
528 self.finish_at(checkpoint, kind);
529 res
530 }
531
532 pub fn incremental_opt<F>(&mut self, kind: L::ElementType, f: F) -> Result<bool, OakError>
537 where
538 F: FnOnce(&mut Self) -> Result<bool, OakError>,
539 {
540 if self.try_reuse(kind) {
541 return Ok(true);
542 }
543
544 let checkpoint = self.checkpoint();
545 match f(self) {
546 Ok(true) => {
547 self.finish_at(checkpoint, kind);
548 Ok(true)
549 }
550 Ok(false) => Ok(false),
551 Err(e) => {
552 self.finish_at(checkpoint, kind);
553 Err(e)
554 }
555 }
556 }
557}