1use std::borrow::Cow;
10use std::error::Error;
11use std::fmt::{Display, Formatter};
12use std::ops::Range;
13use std::sync::Arc;
14use std::vec::IntoIter;
15
16use crate::native::{LambdaArguments, assignment_list, installation_value, lambda_arguments};
17use crate::nodes::*;
18use crate::trivia_transfer::TriviaTransfer;
19use crate::{
20 CSTNodeClassLabel, CellStream, CellStreamError, CommentTrivia, DelimiterKind, DelimiterToken,
21 DoubleSpan, ExternalCstChild, ExternalCstNode, LexError, Migrate, MigrateError, Parser,
22 Punctuated, Recovered, Source, SourceFile, Span, Spanned, TextEdit, TokenStream, TokenTree,
23 Tokenize, TriviaKind, lex_str, lex_str_recovering,
24};
25
26#[derive(Debug)]
27pub enum ParseError {
29 Lex(LexError),
31 Tokenize(CellStreamError),
33 Language(tree_sitter::LanguageError),
35 Cancelled,
37 InvalidEdit,
39 InvalidSyntax(Span),
41 Migrate(MigrateError),
43 UnsupportedNode {
45 kind: String,
47 span: Span,
49 },
50}
51
52impl Display for ParseError {
53 fn fmt(&self, formatter: &mut Formatter<'_>) -> std::fmt::Result {
54 match self {
55 Self::Lex(error) => error.fmt(formatter),
56 Self::Tokenize(error) => error.fmt(formatter),
57 Self::Language(error) => error.fmt(formatter),
58 Self::Cancelled => formatter.write_str("Tree-sitter parsing was cancelled"),
59 Self::InvalidEdit => formatter.write_str("source edit is outside the current buffer"),
60 Self::InvalidSyntax(span) if span.line_column_range().is_some() => {
61 write!(formatter, "invalid Macaulay2 syntax at {span}")
62 }
63 Self::InvalidSyntax(_) => formatter.write_str("invalid Macaulay2 syntax"),
64 Self::Migrate(error) => error.fmt(formatter),
65 Self::UnsupportedNode { kind, .. } => {
66 write!(
67 formatter,
68 "Tree-sitter node `{kind}` has no typed representation"
69 )
70 }
71 }
72 }
73}
74
75impl Error for ParseError {
76 fn source(&self) -> Option<&(dyn Error + 'static)> {
77 match self {
78 Self::Lex(error) => Some(error),
79 Self::Tokenize(error) => Some(error),
80 Self::Language(error) => Some(error),
81 Self::Migrate(error) => Some(error),
82 Self::Cancelled
83 | Self::InvalidEdit
84 | Self::InvalidSyntax(_)
85 | Self::UnsupportedNode { .. } => None,
86 }
87 }
88}
89
90impl From<MigrateError> for ParseError {
91 fn from(error: MigrateError) -> Self {
92 Self::Migrate(error)
93 }
94}
95
96impl From<LexError> for ParseError {
97 fn from(error: LexError) -> Self {
98 Self::Lex(error)
99 }
100}
101
102impl From<CellStreamError> for ParseError {
103 fn from(error: CellStreamError) -> Self {
104 Self::Tokenize(error)
105 }
106}
107
108pub struct TreeSitterParser {
110 parser: tree_sitter::Parser,
112}
113
114pub struct RealtimeParser {
122 parser: tree_sitter::Parser,
124 source: Arc<Source>,
126 parse_view: String,
128 tree: tree_sitter::Tree,
130 syntax: SourceFile,
132 diagnostics: Vec<LexError>,
134 changed_ranges: Vec<Span>,
136}
137
138impl RealtimeParser {
139 pub fn new(source: impl Into<String>) -> Result<Self, ParseError> {
146 let source = Source::new(source.into());
147 let mut parser = TreeSitterParser::new()?.parser;
148 let ParsedTree {
149 parse_view,
150 tree,
151 syntax,
152 diagnostics,
153 } = parse_recovered_tree(&mut parser, Arc::clone(&source), None)?;
154 Ok(Self {
155 parser,
156 source,
157 parse_view,
158 tree,
159 syntax,
160 diagnostics,
161 changed_ranges: Vec::new(),
162 })
163 }
164
165 pub fn apply_edit(&mut self, edit: &TextEdit) -> Result<(), ParseError> {
176 let source_text = edit
177 .apply(self.source.text())
178 .ok_or(ParseError::InvalidEdit)?;
179 let source = Source::with_file(self.source.file(), source_text);
180 let (view, aliases, diagnostics) = renamed_source_recovering(source.text())?;
181 let parse_view = view.into_owned();
182
183 let mut edited_tree = self.tree.clone();
184 edited_tree.edit(&input_edit_between(&self.parse_view, &parse_view));
185 let tree = self
186 .parser
187 .parse(parse_view.as_bytes(), Some(&edited_tree))
188 .ok_or(ParseError::Cancelled)?;
189 if let Some(error) = first_error(tree.root_node()) {
190 return Err(ParseError::InvalidSyntax(Span::ranged(
191 Arc::clone(&source),
192 error.start_byte().min(source.text().len())
193 ..error.end_byte().min(source.text().len()),
194 )));
195 }
196 let syntax = Lowerer::new(Arc::clone(&source), source.text(), aliases)
197 .source_file(tree.root_node())?;
198 let changed_ranges = edited_tree
199 .changed_ranges(&tree)
200 .map(|range| {
201 Span::ranged(
202 Arc::clone(&source),
203 range.start_byte.min(source.text().len())
204 ..range.end_byte.min(source.text().len()),
205 )
206 })
207 .collect();
208
209 self.source = source;
210 self.parse_view = parse_view;
211 self.tree = tree;
212 self.syntax = syntax;
213 self.diagnostics = diagnostics;
214 self.changed_ranges = changed_ranges;
215 Ok(())
216 }
217
218 pub fn source(&self) -> &str {
220 self.source.text()
221 }
222
223 pub fn syntax(&self) -> &SourceFile {
225 &self.syntax
226 }
227
228 pub fn diagnostics(&self) -> &[LexError] {
230 &self.diagnostics
231 }
232
233 pub fn changed_ranges(&self) -> &[Span] {
235 &self.changed_ranges
236 }
237
238 pub fn into_syntax(self) -> SourceFile {
240 self.syntax
241 }
242}
243
244struct ParsedTree {
246 parse_view: String,
248 tree: tree_sitter::Tree,
250 syntax: SourceFile,
252 diagnostics: Vec<LexError>,
254}
255
256fn parse_recovered_tree(
258 parser: &mut tree_sitter::Parser,
259 source: Arc<Source>,
260 old_tree: Option<&tree_sitter::Tree>,
261) -> Result<ParsedTree, ParseError> {
262 let source_text = source.text();
263 let (view, aliases, diagnostics) = renamed_source_recovering(source_text)?;
264 let parse_view = view.into_owned();
265 let tree = parser
266 .parse(parse_view.as_bytes(), old_tree)
267 .ok_or(ParseError::Cancelled)?;
268 if let Some(error) = first_error(tree.root_node()) {
269 return Err(ParseError::InvalidSyntax(Span::ranged(
270 Arc::clone(&source),
271 error.start_byte().min(source_text.len())..error.end_byte().min(source_text.len()),
272 )));
273 }
274 let syntax =
275 Lowerer::new(Arc::clone(&source), source_text, aliases).source_file(tree.root_node())?;
276 Ok(ParsedTree {
277 parse_view,
278 tree,
279 syntax,
280 diagnostics,
281 })
282}
283
284fn input_edit_between(old: &str, new: &str) -> tree_sitter::InputEdit {
286 let mut start = old
287 .as_bytes()
288 .iter()
289 .zip(new.as_bytes())
290 .take_while(|(old, new)| old == new)
291 .count();
292 while !old.is_char_boundary(start) || !new.is_char_boundary(start) {
293 start -= 1;
294 }
295
296 let available_suffix = old.len().min(new.len()).saturating_sub(start);
297 let mut suffix = old
298 .as_bytes()
299 .iter()
300 .rev()
301 .zip(new.as_bytes().iter().rev())
302 .take(available_suffix)
303 .take_while(|(old, new)| old == new)
304 .count();
305 while !old.is_char_boundary(old.len() - suffix) || !new.is_char_boundary(new.len() - suffix) {
306 suffix -= 1;
307 }
308
309 let old_end = old.len() - suffix;
310 let new_end = new.len() - suffix;
311 tree_sitter::InputEdit {
312 start_byte: start,
313 old_end_byte: old_end,
314 new_end_byte: new_end,
315 start_position: point_at(old, start),
316 old_end_position: point_at(old, old_end),
317 new_end_position: point_at(new, new_end),
318 }
319}
320
321fn point_at(source: &str, offset: usize) -> tree_sitter::Point {
323 let before = &source[..offset];
324 let row = before.bytes().filter(|byte| *byte == b'\n').count();
325 let column = before
326 .as_bytes()
327 .iter()
328 .rposition(|byte| *byte == b'\n')
329 .map_or(before.len(), |newline| before.len() - newline - 1);
330 tree_sitter::Point { row, column }
331}
332
333impl TreeSitterParser {
334 pub fn new() -> Result<Self, ParseError> {
341 let mut parser = tree_sitter::Parser::new();
342 parser
343 .set_language(&tree_sitter_macaulay2::language())
344 .map_err(ParseError::Language)?;
345 Ok(Self { parser })
346 }
347
348 fn parse_source_in(&mut self, source: Arc<Source>) -> Result<SourceFile, ParseError> {
350 let source_text = source.text();
351 let (renamed, aliases) = renamed_source(source_text)?;
352 let tree = self
353 .parser
354 .parse(renamed.as_bytes(), None)
355 .ok_or(ParseError::Cancelled)?;
356 if let Some(error) = first_error(tree.root_node()) {
357 return Err(ParseError::InvalidSyntax(Span::ranged(
358 Arc::clone(&source),
359 error.start_byte()..error.end_byte(),
360 )));
361 }
362 Lowerer::new(Arc::clone(&source), source_text, aliases).source_file(tree.root_node())
363 }
364
365 pub fn parse_recovering(
375 &mut self,
376 source: &str,
377 ) -> Result<Recovered<SourceFile, LexError>, ParseError> {
378 let source = Source::new(source);
379 let source_text = source.text();
380 let (renamed, aliases, diagnostics) = renamed_source_recovering(source_text)?;
381 let tree = self
382 .parser
383 .parse(renamed.as_bytes(), None)
384 .ok_or(ParseError::Cancelled)?;
385 if let Some(error) = first_error(tree.root_node()) {
386 return Err(ParseError::InvalidSyntax(Span::ranged(
387 Arc::clone(&source),
388 error.start_byte().min(source_text.len())..error.end_byte().min(source_text.len()),
389 )));
390 }
391 let syntax = Lowerer::new(Arc::clone(&source), source_text, aliases)
392 .source_file(tree.root_node())?;
393 Ok(Recovered::new(syntax, diagnostics))
394 }
395}
396
397impl Parser for TreeSitterParser {
398 type Error = ParseError;
399
400 fn parse_cells(&mut self, cells: CellStream) -> Result<SourceFile, Self::Error> {
401 match cells.complete_source() {
402 Some(source) => self.parse_source_in(source),
403 None => self.parse_source_in(Source::new(cells.to_string())),
404 }
405 }
406}
407
408pub fn parse_file(source: &str) -> Result<SourceFile, ParseError> {
414 let mut parser = TreeSitterParser::new()?;
415 let cells = lex_str(source)?.to_cell_stream()?;
416 parser.parse_cells(cells)
417}
418
419pub fn parse_file_recovering(source: &str) -> Result<Recovered<SourceFile, LexError>, ParseError> {
427 TreeSitterParser::new()?.parse_recovering(source)
428}
429
430pub fn parse_tokens(tokens: &TokenStream) -> Result<SourceFile, ParseError> {
437 let cells = tokens.to_cell_stream()?;
438 TreeSitterParser::new()?.parse_cells(cells)
439}
440
441fn first_error(root: tree_sitter::Node<'_>) -> Option<tree_sitter::Node<'_>> {
443 let mut pending = vec![root];
444 while let Some(node) = pending.pop() {
445 if node.is_error() || node.is_missing() {
446 return Some(node);
447 }
448 pending.extend((0..node.child_count()).rev().filter_map(|index| {
449 node.child(u32::try_from(index).expect("Tree-sitter child count fits u32"))
450 }));
451 }
452 None
453}
454
455struct Lowerer<'source> {
457 source: &'source [u8],
459 source_span: Span,
461 aliases: Vec<CoreAlias>,
463}
464
465enum IterationDomain {
467 Range(Option<RangeBoundFrom>, Option<RangeBoundTo>),
469 In(Token![in], Box<Expr>),
471}
472
473impl<'source> Lowerer<'source> {
474 fn new(source_owner: Arc<Source>, source: &'source str, aliases: Vec<CoreAlias>) -> Self {
476 Self {
477 source: source.as_bytes(),
478 source_span: Span::ranged(source_owner, 0..source.len()),
479 aliases,
480 }
481 }
482
483 fn source_file(&self, root: tree_sitter::Node<'_>) -> Result<SourceFile, ParseError> {
485 let mut cells = Vec::new();
486 let raw_cells = self.semantic_children(root);
487 for (index, child) in raw_cells.iter().copied().enumerate() {
488 match child.kind() {
489 "cell" | "muted" => {
490 let next = raw_cells.get(index + 1).copied();
491 cells.push(self.cell(child, self.eoc_offset(child, next))?);
492 }
493 kind => return Err(self.unsupported(kind, child)),
494 }
495 }
496 let mut source_file = SourceFile::new(
497 BOF::new("", self.leading_span()),
498 cells,
499 EOF::new("", self.trailing_span()),
500 );
501 TriviaTransfer::from_source(self.source_span.source())?.apply(&mut source_file);
502 Ok(source_file)
503 }
504
505 fn leading_span(&self) -> Span {
508 let source = self.source_span.source();
509 Span::ranged(Arc::clone(source), source.leading_whitespace())
510 }
511
512 fn trailing_span(&self) -> Span {
517 let source = self.source_span.source();
518 Span::ranged(Arc::clone(source), source.trailing_whitespace())
519 }
520
521 fn cell(&self, node: tree_sitter::Node<'_>, eoc_offset: usize) -> Result<Cell, ParseError> {
523 let (content, semicolon) = if node.kind() == "muted" {
524 let semicolon = self.required_kind(node, ";")?;
525 (
526 self.packed_content(self.children(node))?,
527 Some(self.migrate(semicolon)?),
528 )
529 } else {
530 let child = self.only_semantic_child(node)?;
531 let content = if child.kind() == "naked_sequence" {
532 self.expr_pack(self.children(child))?.into()
533 } else {
534 self.expr(child)?.into()
535 };
536 (content, None)
537 };
538 Ok(Cell::new(
539 content,
540 semicolon,
541 EOC::new("", self.source_span.at(eoc_offset)),
542 ))
543 }
544
545 fn eoc_offset(
547 &self,
548 _node: tree_sitter::Node<'_>,
549 next: Option<tree_sitter::Node<'_>>,
550 ) -> usize {
551 next.map_or(self.source.len(), |next| next.start_byte())
552 .min(self.source.len())
553 }
554
555 fn expr_pack(&self, nodes: Vec<tree_sitter::Node<'_>>) -> Result<ExprPack, ParseError> {
557 let pack_span = nodes
558 .iter()
559 .map(|node| self.span(*node))
560 .reduce(|left, right| {
561 left.join(right)
562 .expect("Tree-sitter nodes share one source snapshot")
563 })
564 .unwrap_or_else(|| Span::unlocated(Arc::clone(self.source_span.source())));
565 let mut values = Vec::new();
566 let mut commas = Vec::new();
567 for node in nodes.into_iter().filter(|node| !node.is_extra()) {
568 match node.kind() {
569 "," => commas.push(self.migrate::<Token![,]>(node)?),
570 "empty_component" => values.push(Component::Empty(Empty::new("", self.span(node)))),
571 ";" | "(" | ")" | "[" | "]" | "{" | "}" | "<|" | "|>" | "muted" => {}
572 _ if node.is_named() => values.push(Component::Expr(Box::new(self.expr(node)?))),
573 _ => {}
574 }
575 }
576 let mut values = values.into_iter();
577 let Some(first) = values.next() else {
578 return Err(self.unsupported_span("empty expression pack", pack_span));
579 };
580 let value_count = values.len() + 1;
581 let comma_count = commas.len();
582 if value_count != comma_count + 1 {
583 return Err(self.unsupported_span("invalid expression pack", pack_span));
584 }
585 let rest = commas
586 .into_iter()
587 .zip(values)
588 .collect::<Vec<(Token![,], Component)>>();
589 let mut rest = rest.into_iter();
590 let Some((punctuation, second)) = rest.next() else {
591 return Err(self.unsupported_span("expression pack without a comma", pack_span));
592 };
593 let mut pack = Punctuated::new(first, punctuation, second);
594 for (punctuation, value) in rest {
595 pack.push(punctuation, value);
596 }
597 Ok(ExprPack::new(pack))
598 }
599
600 fn packed_content(
602 &self,
603 nodes: Vec<tree_sitter::Node<'_>>,
604 ) -> Result<PackedContent, ParseError> {
605 if nodes.iter().any(|node| node.kind() == ",") {
606 return self.expr_pack(nodes).map(Into::into);
607 }
608 let mut expressions = nodes
609 .into_iter()
610 .filter(|node| !node.is_extra() && node.is_named() && node.kind() != "muted");
611 let Some(expression) = expressions.next() else {
612 return Err(self.unsupported_span("empty packed content", self.source_span.clone()));
613 };
614 if expressions.next().is_some() {
615 return Err(self.unsupported("unseparated packed content", expression));
616 }
617 self.expr(expression).map(Into::into)
618 }
619
620 fn expr(&self, node: tree_sitter::Node<'_>) -> Result<Expr, ParseError> {
622 match node.kind() {
623 "symbol" => Ok(self.migrate::<Symbol>(node)?.into()),
624 "integer_literal" if self.text(node).contains('p') => {
625 Ok(FloatLiteral::new(self.text(node), self.span(node)).into())
626 }
627 "integer_literal" => Ok(self.migrate::<IntegerLiteral>(node)?.into()),
628 "float_literal" => Ok(self.migrate::<FloatLiteral>(node)?.into()),
629 "string_literal" => self.string_literal(node),
630 "raw_string_literal" => self.raw_string_literal(node),
631 "array" | "list" | "angle_bar_list" | "sequence" | "parenthesized_expression" => {
632 self.collection(node)
633 }
634 "binary_expression" => self.binary_expr(node),
635 "prefix_expression" => self.prefix_expr(node),
636 "postfix_expression" => self.postfix_expr(node),
637 "lambda_expression" => self.lambda_expression(node),
638 "assignment"
639 | "local_assignment"
640 | "binary_assignment"
641 | "prefix_assignment"
642 | "postfix_assignment"
643 | "binary_installation"
644 | "prefix_installation"
645 | "postfix_installation"
646 | "structured_binding"
647 | "local_structured_binding" => self.assignment(node),
648 "evaluated_assignment" => Ok(Expr!(Assign::Evaluated {
649 evaluated_domain: Box::new(self.expr(self.required_field(node, "left")?)?),
650 operator: self.migrate(self.required_field(node, "operator")?)?,
651 value: Box::new(self.expr(self.required_field(node, "right")?)?),
652 })),
653 "option" => Ok(Expr!(Option {
654 key: Box::new(self.expr(self.required_field(node, "left")?)?),
655 operator: self.migrate(self.required_field(node, "operator")?)?,
656 value: Box::new(self.expr(self.required_field(node, "right")?)?),
657 })),
658 "if_statement" => self.if_statement(node),
659 "for_loop" => self.for_loop(node),
660 "while_loop" => self.while_loop(node),
661 "try_statement" => self.try_statement(node),
662 "quote_expression" => self.quote_expression(node),
663 "new_statement" => self.new_statement(node),
664 "break_statement" => Ok(Expr!(Control::Break {
665 break_token: self.migrate(self.required_kind(node, "break")?)?,
666 value: self
667 .first_expression_child(node)
668 .map(|child| self.expr(child).map(Box::new))
669 .transpose()?,
670 })),
671 "continue_statement" => Ok(Expr!(Control::Continue {
672 continue_token: self.migrate(self.required_kind(node, "continue")?)?,
673 value: self
674 .first_expression_child(node)
675 .map(|child| self.expr(child).map(Box::new))
676 .transpose()?,
677 })),
678 "return_statement" => Ok(Expr!(Control::Return {
679 return_token: self.migrate(self.required_kind(node, "return")?)?,
680 value: self
681 .first_expression_child(node)
682 .map(|child| self.expr(child).map(Box::new))
683 .transpose()?,
684 })),
685 "catch_statement" => Ok(Expr!(Catch {
686 catch_token: self.migrate(self.required_kind(node, "catch")?)?,
687 value: Box::new(self.expr(self.required_expression_child(node)?)?),
688 })),
689 "throw_statement" => Ok(Expr!(Throw {
690 throw_token: self.migrate(self.required_kind(node, "throw")?)?,
691 value: Box::new(self.expr(self.required_expression_child(node)?)?),
692 })),
693 "trap_statement" => Ok(Expr!(Trap {
694 trap_token: self.migrate(self.required_kind(node, "trap")?)?,
695 value: Box::new(self.expr(self.required_expression_child(node)?)?),
696 })),
697 "debug_clause" => self.debug_clause(node),
698 kind => Err(self.unsupported(kind, node)),
699 }
700 }
701
702 fn collection(&self, node: tree_sitter::Node<'_>) -> Result<Expr, ParseError> {
704 let spans = self.delimiter_spans(node)?;
705 let statements = self
706 .semantic_children(node)
707 .into_iter()
708 .filter(|child| child.kind() == "muted")
709 .map(|child| self.statement(child))
710 .collect::<Result<Vec<_>, _>>()?;
711
712 if node.kind() == "parenthesized_expression" {
713 let value = self
714 .semantic_children(node)
715 .into_iter()
716 .find(|child| child.kind() != "muted")
717 .map(|child| self.expr(child))
718 .transpose()?;
719 let mut holder = Holder::new(statements, value.map(Box::new));
720 holder.delimiter = <Delimiter![()] as DelimiterToken>::new(spans);
721 return Ok(holder.into());
722 }
723
724 let has_elements = self.children(node).into_iter().any(|child| {
725 !child.is_extra()
726 && (child.kind() == ","
727 || child.kind() == "empty_component"
728 || (child.is_named() && child.kind() != "muted"))
729 });
730 let elements = has_elements
731 .then(|| self.packed_content(self.children(node)))
732 .transpose()?;
733 Ok(match node.kind() {
734 "array" => {
735 let mut value = Array::new(statements, elements);
736 value.delimiter = <Delimiter![[]] as DelimiterToken>::new(spans);
737 value.into()
738 }
739 "list" => {
740 let mut value = List::new(statements, elements);
741 value.delimiter = <Delimiter![{}] as DelimiterToken>::new(spans);
742 value.into()
743 }
744 "angle_bar_list" => {
745 let mut value = AngleBarList::new(statements, elements);
746 value.delimiter = <Delimiter![<| |>] as DelimiterToken>::new(spans);
747 value.into()
748 }
749 "sequence" => {
750 let mut value = Sequence::new(statements, elements);
751 value.delimiter = <Delimiter![()] as DelimiterToken>::new(spans);
752 value.into()
753 }
754 kind => return Err(self.unsupported(kind, node)),
755 })
756 }
757
758 fn statement(&self, node: tree_sitter::Node<'_>) -> Result<Statement, ParseError> {
760 Ok(Statement::new(
761 self.packed_content(self.children(node))?,
762 self.migrate(self.required_kind(node, ";")?)?,
763 ))
764 }
765
766 fn string_literal(&self, node: tree_sitter::Node<'_>) -> Result<Expr, ParseError> {
768 let elements = self
769 .children(node)
770 .into_iter()
771 .filter(|child| child.kind() != "\"")
772 .filter(|child| !child.is_extra())
773 .map(|child| match child.kind() {
774 "escape_sequence" => self.migrate(child).map(StringElement::Escape),
775 "string_content" => self.migrate(child).map(StringElement::Content),
776 _ => Ok(StringElement::Content(StringContent::new(
777 self.text(child),
778 self.span(child),
779 ))),
780 })
781 .collect::<Result<Vec<_>, ParseError>>()?;
782 Ok(StringLiteral::new(elements, self.span(node)).into())
783 }
784
785 fn raw_string_literal(&self, node: tree_sitter::Node<'_>) -> Result<Expr, ParseError> {
787 let elements = self
788 .children(node)
789 .into_iter()
790 .filter(|child| child.kind() != "///")
791 .filter(|child| !child.is_extra())
792 .map(|child| match child.kind() {
793 "escape_sequence" => self.migrate(child).map(RawStringElement::Escape),
794 "raw_string_content" => self.migrate(child).map(RawStringElement::Content),
795 kind => Err(self.unsupported(kind, child)),
796 })
797 .collect::<Result<Vec<_>, ParseError>>()?;
798 Ok(RawStringLiteral::new(elements, self.span(node)).into())
799 }
800
801 fn binary_expr(&self, node: tree_sitter::Node<'_>) -> Result<Expr, ParseError> {
803 let left = self.expr(
804 self.child_by_field(node, "left_operand")
805 .or_else(|| self.child_by_field(node, "left"))
806 .ok_or_else(|| self.unsupported("left operand", node))?,
807 )?;
808 let operator = self.required_field(node, "operator")?;
809 let right = self.expr(self.required_field(node, "right")?)?;
810 if operator.kind() == "SPACE" {
811 Ok(Expr!(Op::Bin::Adj {
812 left_operand: Box::new(left),
813 operator: Adj::new("", self.span(operator)),
814 right_operand: Box::new(right),
815 }))
816 } else {
817 match self.text(operator).as_ref() {
818 spelling if GENERATED_AUGMENTED_OPERATOR_SPELLINGS.contains(&spelling) => {
819 Ok(Expr!(Assign::Augmented {
820 target: Box::new(left),
821 operator: self.migrate(operator)?,
822 value: Box::new(right),
823 }))
824 }
825 "." => Ok(Expr!(Op::Bin::Member::Dot {
826 receiver: Box::new(left),
827 operator: self.migrate(operator)?,
828 member: Box::new(right),
829 })),
830 ".?" => Ok(Expr!(Op::Bin::Member::Optional {
831 receiver: Box::new(left),
832 operator: self.migrate(operator)?,
833 member: Box::new(right),
834 })),
835 "#" => Ok(Expr!(Op::Bin::Index {
836 receiver: Box::new(left),
837 operator: self.migrate(operator)?,
838 index: Box::new(right),
839 })),
840 _ => Ok(Expr!(Op::Bin::Regular {
841 left_operand: Box::new(left),
842 operator: self.migrate(operator)?,
843 right_operand: Box::new(right),
844 })),
845 }
846 }
847 }
848
849 fn prefix_expr(&self, node: tree_sitter::Node<'_>) -> Result<Expr, ParseError> {
851 Ok(Expr!(Op::Prefix {
852 operator: self.migrate(self.required_field(node, "operator")?)?,
853 operand: Box::new(self.expr(self.required_field(node, "operand")?)?),
854 }))
855 }
856
857 fn postfix_expr(&self, node: tree_sitter::Node<'_>) -> Result<Expr, ParseError> {
859 Ok(Expr!(Op::Postfix {
860 operand: Box::new(self.expr(self.required_field(node, "operand")?)?),
861 operator: self.migrate(self.required_field(node, "operator")?)?,
862 }))
863 }
864
865 fn lambda_expression(&self, node: tree_sitter::Node<'_>) -> Result<Expr, ParseError> {
867 let argument_expr = self.expr(self.required_field(node, "parameters")?)?;
868 let arguments = lambda_arguments(argument_expr)
869 .ok_or_else(|| self.unsupported("lambda arguments", node))?;
870 let operator = self.migrate(self.required_field(node, "operator")?)?;
871 let body = Box::new(self.expr(self.required_field(node, "body")?)?);
872 Ok(match arguments {
873 LambdaArguments::Variadic(argument) => Expr!(Lambda::Variadic {
874 argument,
875 operator,
876 body,
877 }),
878 LambdaArguments::List(arguments) => Expr!(Lambda::List {
879 arguments: *arguments,
880 operator,
881 body,
882 }),
883 })
884 }
885
886 fn assignment(&self, node: tree_sitter::Node<'_>) -> Result<Expr, ParseError> {
888 let right = self.expr(self.required_field(node, "right")?)?;
889 Ok(match node.kind() {
890 "assignment" => Expr!(Assign::Simple::Global {
891 variable: self.migrate(self.required_field(node, "left")?)?,
892 operator: self.migrate(self.required_field(node, "operator")?)?,
893 value: Box::new(right),
894 }),
895 "local_assignment" => Expr!(Assign::Simple::Local {
896 variable: self.migrate(self.required_field(node, "left")?)?,
897 operator: self.migrate(self.required_field(node, "operator")?)?,
898 value: Box::new(right),
899 }),
900 "binary_assignment" | "prefix_assignment" | "postfix_assignment" => {
901 let Expr::Op(left) = self.expr(self.required_field(node, "left")?)? else {
902 return Err(self.unsupported("operator assignment target", node));
903 };
904 Expr!(Assign::Op {
905 argument_expr: left,
906 operator: self.migrate(self.required_field(node, "operator")?)?,
907 value_expr: Box::new(right),
908 })
909 }
910 "binary_installation" | "prefix_installation" | "postfix_installation" => {
911 let Expr::Op(left) = self.expr(self.required_field(node, "left")?)? else {
912 return Err(self.unsupported("operator installation target", node));
913 };
914 let (typical_value, function) = installation_value(right);
915 match left {
916 ExprOp::Bin(ExprOpBin::Adj(application)) => Expr!(Assign::Install::Method {
917 method: application.left_operand,
918 operator: application.operator,
919 signature: application.right_operand,
920 assign_op: self.migrate(self.required_field(node, "operator")?)?,
921 typical_value,
922 function: Box::new(function),
923 }),
924 domain_expr => Expr!(Assign::Install::Op {
925 domain_expr,
926 assign_op: self.migrate(self.required_field(node, "operator")?)?,
927 typical_value,
928 function: Box::new(function),
929 }),
930 }
931 }
932 "structured_binding" | "local_structured_binding" => {
933 let list_expr = self.expr(self.required_field(node, "binding_pack")?)?;
934 let argument_list = assignment_list(list_expr)
935 .ok_or_else(|| self.unsupported("assignment argument list", node))?;
936 if node.kind() == "local_structured_binding" {
937 Expr!(Assign::Parallel::Local {
938 argument_list: Box::new(argument_list),
939 operator: self.migrate(self.required_field(node, "operator")?)?,
940 value: Box::new(right),
941 })
942 } else {
943 Expr!(Assign::Parallel::Global {
944 argument_list: Box::new(argument_list),
945 operator: self.migrate(self.required_field(node, "operator")?)?,
946 value: Box::new(right),
947 })
948 }
949 }
950 kind => return Err(self.unsupported(kind, node)),
951 })
952 }
953
954 fn then_clause(&self, node: tree_sitter::Node<'_>) -> Result<ThenClause, ParseError> {
956 Ok(ThenClause::new(
957 self.migrate(self.required_kind(node, "then")?)?,
958 Box::new(self.expr(self.required_expression_child(node)?)?),
959 ))
960 }
961
962 fn else_clause(&self, node: tree_sitter::Node<'_>) -> Result<ElseClause, ParseError> {
964 Ok(ElseClause::new(
965 self.migrate(self.required_kind(node, "else")?)?,
966 Box::new(self.expr(self.required_expression_child(node)?)?),
967 ))
968 }
969
970 fn if_statement(&self, node: tree_sitter::Node<'_>) -> Result<Expr, ParseError> {
972 Ok(Expr!(If {
973 if_token: self.migrate(self.required_kind(node, "if")?)?,
974 condition: Box::new(self.expr(self.required_field(node, "condition")?)?),
975 then_clause: self.then_clause(self.required_kind(node, "then_clause")?)?,
976 else_clause: self
977 .optional_kind(node, "else_clause")
978 .map(|child| self.else_clause(child))
979 .transpose()?,
980 }))
981 }
982
983 fn loop_body(&self, node: tree_sitter::Node<'_>) -> Result<LoopBody, ParseError> {
985 let list_step = self
986 .optional_kind(node, "list")
987 .map(|token| {
988 Ok::<_, ParseError>(ListStep::new(
989 self.migrate(token)?,
990 Box::new(self.expr(self.required_field(node, "listed_value")?)?),
991 ))
992 })
993 .transpose()?;
994 let do_step = self
995 .optional_kind(node, "do")
996 .map(|token| {
997 Ok::<_, ParseError>(DoStep::new(
998 self.migrate(token)?,
999 Box::new(self.expr(self.required_field(node, "ignored_value")?)?),
1000 ))
1001 })
1002 .transpose()?;
1003 Ok(LoopBody::new(list_step, do_step))
1004 }
1005
1006 fn for_loop(&self, node: tree_sitter::Node<'_>) -> Result<Expr, ParseError> {
1008 let iteration_domain = self
1009 .optional_kind(node, "iteration_range")
1010 .map(|range| self.iteration_domain(range))
1011 .transpose()?;
1012 let when_condition = self
1013 .optional_kind(node, "when")
1014 .map(|token| {
1015 Ok::<_, ParseError>(WhenCondition::new(
1016 self.migrate(token)?,
1017 Box::new(self.expr(self.required_field(node, "filter")?)?),
1018 ))
1019 })
1020 .transpose()?;
1021 let for_token = self.migrate(self.required_kind(node, "for")?)?;
1022 let variable = self.migrate(self.required_field(node, "variable")?)?;
1023 let body = self.loop_body(self.required_kind(node, "loop_body")?)?;
1024 Ok(match iteration_domain {
1025 None => Expr!(For::Bare {
1026 for_token,
1027 variable,
1028 condition: when_condition,
1029 body,
1030 }),
1031 Some(IterationDomain::Range(lower_bound, upper_bound)) => Expr!(For::Range {
1032 for_token,
1033 variable,
1034 lower_bound,
1035 upper_bound,
1036 condition: when_condition,
1037 body,
1038 }),
1039 Some(IterationDomain::In(in_token, collection)) => Expr!(For::In {
1040 for_token,
1041 variable,
1042 in_token,
1043 collection,
1044 condition: when_condition,
1045 body,
1046 }),
1047 })
1048 }
1049
1050 fn iteration_domain(&self, node: tree_sitter::Node<'_>) -> Result<IterationDomain, ParseError> {
1052 if let Some(token) = self.optional_kind(node, "in") {
1053 return Ok(IterationDomain::In(
1054 self.migrate(token)?,
1055 Box::new(self.expr(self.required_field(node, "iterated_collection")?)?),
1056 ));
1057 }
1058 let lower_bound = self
1059 .optional_kind(node, "from")
1060 .map(|token| {
1061 Ok::<_, ParseError>(RangeBoundFrom::new(
1062 self.migrate(token)?,
1063 Box::new(self.expr(self.required_field(node, "range_start")?)?),
1064 ))
1065 })
1066 .transpose()?;
1067 let upper_bound = self
1068 .optional_kind(node, "to")
1069 .map(|token| {
1070 Ok::<_, ParseError>(RangeBoundTo::new(
1071 self.migrate(token)?,
1072 Box::new(self.expr(self.required_field(node, "range_end")?)?),
1073 ))
1074 })
1075 .transpose()?;
1076 Ok(IterationDomain::Range(lower_bound, upper_bound))
1077 }
1078
1079 fn while_loop(&self, node: tree_sitter::Node<'_>) -> Result<Expr, ParseError> {
1081 Ok(Expr!(While {
1082 while_token: self.migrate(self.required_kind(node, "while")?)?,
1083 condition: Box::new(self.expr(self.required_field(node, "condition")?)?),
1084 body: self.loop_body(self.required_kind(node, "loop_body")?)?,
1085 }))
1086 }
1087
1088 fn new_statement(&self, node: tree_sitter::Node<'_>) -> Result<Expr, ParseError> {
1090 let mut installation = None;
1091 let class =
1092 self.new_statement_element(self.required_field(node, "class")?, &mut installation)?;
1093 let parent_class = self
1094 .optional_kind(node, "of")
1095 .map(|token| {
1096 Ok::<_, ParseError>(OfClass::new(
1097 self.migrate(token)?,
1098 Box::new(self.new_statement_element(
1099 self.required_field(node, "parent")?,
1100 &mut installation,
1101 )?),
1102 ))
1103 })
1104 .transpose()?;
1105 let instance = self
1106 .optional_kind(node, "from")
1107 .map(|token| {
1108 Ok::<_, ParseError>(FromInstance::new(
1109 self.migrate(token)?,
1110 Box::new(self.new_statement_element(
1111 self.required_field(node, "instance")?,
1112 &mut installation,
1113 )?),
1114 ))
1115 })
1116 .transpose()?;
1117 let statement = Expr!(New {
1118 new_token: self.migrate(self.required_kind(node, "new")?)?,
1119 class: Box::new(class),
1120 parent_class,
1121 instance,
1122 });
1123 Ok(match installation {
1124 Some((operator, function)) => {
1125 let Expr::New(new_statement) = statement else {
1126 unreachable!("the constructor selected the new-statement specialization")
1127 };
1128 Expr!(Assign::Install::New {
1129 new_statement,
1130 operator,
1131 function: Box::new(function),
1132 })
1133 }
1134 None => statement,
1135 })
1136 }
1137
1138 fn new_statement_element(
1140 &self,
1141 node: tree_sitter::Node<'_>,
1142 installation: &mut Option<(Token![:=], Expr)>,
1143 ) -> Result<Expr, ParseError> {
1144 match node.kind() {
1145 "assignment" => return Err(self.unsupported("`new` assignment with `=`", node)),
1146 "local_assignment" => {}
1147 _ => return self.expr(node),
1148 }
1149 *installation = Some((
1150 self.migrate(self.required_field(node, "operator")?)?,
1151 self.expr(self.required_field(node, "right")?)?,
1152 ));
1153 self.expr(self.required_field(node, "left")?)
1154 }
1155
1156 fn try_statement(&self, node: tree_sitter::Node<'_>) -> Result<Expr, ParseError> {
1158 let value = self
1159 .semantic_children(node)
1160 .into_iter()
1161 .find(|child| {
1162 child.kind() != "then_clause"
1163 && child.kind() != "else_clause"
1164 && child.kind() != "except_clause"
1165 })
1166 .ok_or_else(|| self.unsupported("try value", node))?;
1167 let on_success = self
1168 .optional_kind(node, "then_clause")
1169 .map(|child| self.then_clause(child))
1170 .transpose()?;
1171 let fallback = self
1172 .child_by_field(node, "fallback")
1173 .map(|child| match child.kind() {
1174 "else_clause" => self.else_clause(child).map(TryFallback::Else),
1175 "except_clause" => self.except_do(child),
1176 kind => Err(self.unsupported(kind, child)),
1177 })
1178 .transpose()?;
1179 Ok(Expr!(Try {
1180 try_token: self.migrate(self.required_kind(node, "try")?)?,
1181 value: Box::new(self.expr(value)?),
1182 on_success,
1183 fallback,
1184 }))
1185 }
1186
1187 fn except_do(&self, node: tree_sitter::Node<'_>) -> Result<TryFallback, ParseError> {
1189 Ok(TryFallback!(Except {
1190 except_token: self.migrate(self.required_kind(node, "except")?)?,
1191 exception: self.migrate(self.required_field(node, "exception")?)?,
1192 do_token: self.migrate(self.required_kind(node, "do")?)?,
1193 value: Box::new(self.expr(self.required_expression_child(node)?)?),
1194 }))
1195 }
1196
1197 fn quote_expression(&self, node: tree_sitter::Node<'_>) -> Result<Expr, ParseError> {
1199 let token = self
1200 .children(node)
1201 .into_iter()
1202 .find(|child| {
1203 matches!(
1204 child.kind(),
1205 "symbol" | "local" | "global" | "threadVariable" | "threadLocal"
1206 ) && self.child_by_field(node, "token") != Some(*child)
1207 })
1208 .ok_or_else(|| self.unsupported("quote specifier", node))?;
1209 let quoted = self.required_field(node, "token")?;
1210 let symbol = Symbol::new(self.text(quoted), self.span(quoted));
1211 Ok(match token.kind() {
1212 "symbol" => Expr!(Quote::Symbol {
1213 specifier: self.migrate(token)?,
1214 symbol,
1215 }),
1216 "local" => Expr!(Quote::Local {
1217 specifier: self.migrate(token)?,
1218 symbol,
1219 }),
1220 "global" => Expr!(Quote::Global {
1221 specifier: self.migrate(token)?,
1222 symbol,
1223 }),
1224 "threadVariable" => Expr!(Quote::ThreadVariable {
1225 specifier: self.migrate(token)?,
1226 symbol,
1227 }),
1228 "threadLocal" => Expr!(Quote::ThreadLocal {
1229 specifier: self.migrate(token)?,
1230 symbol,
1231 }),
1232 kind => return Err(self.unsupported(kind, token)),
1233 })
1234 }
1235
1236 fn debug_clause(&self, node: tree_sitter::Node<'_>) -> Result<Expr, ParseError> {
1238 let keyword = self.required_field(node, "keyword")?;
1239 let value = self
1240 .first_expression_child(node)
1241 .map(|child| self.expr(child))
1242 .transpose()?;
1243 Ok(match keyword.kind() {
1244 "elapsedTime" => Expr!(Profile::ElapsedTime {
1245 modifier: self.migrate(keyword)?,
1246 value: Box::new(value.ok_or_else(|| self.unsupported("profiling operand", node))?,),
1247 }),
1248 "elapsedTiming" => Expr!(Profile::ElapsedTiming {
1249 modifier: self.migrate(keyword)?,
1250 value: Box::new(value.ok_or_else(|| self.unsupported("profiling operand", node))?,),
1251 }),
1252 "profile" => Expr!(Profile::Profile {
1253 modifier: self.migrate(keyword)?,
1254 value: Box::new(value.ok_or_else(|| self.unsupported("profiling operand", node))?,),
1255 }),
1256 "time" => Expr!(Profile::Time {
1257 modifier: self.migrate(keyword)?,
1258 value: Box::new(value.ok_or_else(|| self.unsupported("profiling operand", node))?,),
1259 }),
1260 "timing" => Expr!(Profile::Timing {
1261 modifier: self.migrate(keyword)?,
1262 value: Box::new(value.ok_or_else(|| self.unsupported("profiling operand", node))?,),
1263 }),
1264 "TEST" => Expr!(Debug::Test {
1265 keyword: self.migrate(keyword)?,
1266 value: value.map(Box::new),
1267 }),
1268 "step" => Expr!(Debug::Step {
1269 keyword: self.migrate(keyword)?,
1270 value: value.map(Box::new),
1271 }),
1272 "finish" => Expr!(Debug::Finish {
1273 keyword: self.migrate(keyword)?,
1274 value: value.map(Box::new),
1275 }),
1276 "shield" => Expr!(Debug::Shield {
1277 keyword: self.migrate(keyword)?,
1278 value: value.map(Box::new),
1279 }),
1280 "breakpoint" => Expr!(Debug::Breakpoint {
1281 keyword: self.migrate(keyword)?,
1282 value: value.map(Box::new),
1283 }),
1284 kind => return Err(self.unsupported(kind, keyword)),
1285 })
1286 }
1287
1288 fn migrate<T>(&self, node: tree_sitter::Node<'_>) -> Result<T, ParseError>
1290 where
1291 for<'tree> T: Migrate<TreeSitterNode<'tree, 'source>>,
1292 {
1293 T::migrate(TreeSitterNode::with_span(
1294 node,
1295 self.source,
1296 self.span(node),
1297 ))
1298 .map_err(Into::into)
1299 }
1300
1301 fn delimiter_spans(&self, node: tree_sitter::Node<'_>) -> Result<DoubleSpan, ParseError> {
1303 let kind = match node.kind() {
1304 "parenthesized_expression" | "sequence" => DelimiterKind::Parenthesis,
1305 "array" => DelimiterKind::Bracket,
1306 "list" => DelimiterKind::Brace,
1307 "angle_bar_list" => DelimiterKind::AngleBar,
1308 other => return Err(self.unsupported(other, node)),
1309 };
1310 let opening = self.span(self.required_kind(node, kind.opening())?);
1311 let closing = self.required_kind(node, kind.closing())?;
1312 if closing.start_byte() >= self.source.len() {
1313 Ok(DoubleSpan::unclosed(opening))
1314 } else {
1315 Ok(DoubleSpan::new(opening, self.span(closing)))
1316 }
1317 }
1318
1319 fn children<'tree>(&self, node: tree_sitter::Node<'tree>) -> Vec<tree_sitter::Node<'tree>> {
1321 (0..node.child_count())
1322 .filter_map(|index| node.child(u32::try_from(index).expect("child count fits u32")))
1323 .collect()
1324 }
1325
1326 fn semantic_children<'tree>(
1328 &self,
1329 node: tree_sitter::Node<'tree>,
1330 ) -> Vec<tree_sitter::Node<'tree>> {
1331 self.children(node)
1332 .into_iter()
1333 .filter(|child| child.is_named() && !child.is_extra())
1334 .collect()
1335 }
1336
1337 fn only_semantic_child<'tree>(
1339 &self,
1340 node: tree_sitter::Node<'tree>,
1341 ) -> Result<tree_sitter::Node<'tree>, ParseError> {
1342 let children = self.semantic_children(node);
1343 match children.as_slice() {
1344 [child] => Ok(*child),
1345 _ => Err(self.unsupported("cell contents", node)),
1346 }
1347 }
1348
1349 fn first_expression_child<'tree>(
1351 &self,
1352 node: tree_sitter::Node<'tree>,
1353 ) -> Option<tree_sitter::Node<'tree>> {
1354 self.semantic_children(node).into_iter().find(|child| {
1355 !matches!(
1356 child.kind(),
1357 "then_clause" | "else_clause" | "except_clause" | "iteration_range" | "loop_body"
1358 )
1359 })
1360 }
1361
1362 fn required_expression_child<'tree>(
1364 &self,
1365 node: tree_sitter::Node<'tree>,
1366 ) -> Result<tree_sitter::Node<'tree>, ParseError> {
1367 self.first_expression_child(node)
1368 .ok_or_else(|| self.unsupported("expression child", node))
1369 }
1370
1371 fn child_by_field<'tree>(
1373 &self,
1374 node: tree_sitter::Node<'tree>,
1375 field: &str,
1376 ) -> Option<tree_sitter::Node<'tree>> {
1377 node.child_by_field_name(field)
1378 }
1379
1380 fn required_field<'tree>(
1382 &self,
1383 node: tree_sitter::Node<'tree>,
1384 field: &str,
1385 ) -> Result<tree_sitter::Node<'tree>, ParseError> {
1386 self.child_by_field(node, field)
1387 .ok_or_else(|| self.unsupported(field, node))
1388 }
1389
1390 fn optional_kind<'tree>(
1392 &self,
1393 node: tree_sitter::Node<'tree>,
1394 kind: &str,
1395 ) -> Option<tree_sitter::Node<'tree>> {
1396 self.children(node)
1397 .into_iter()
1398 .find(|child| !child.is_extra() && child.kind() == kind)
1399 }
1400
1401 fn required_kind<'tree>(
1403 &self,
1404 node: tree_sitter::Node<'tree>,
1405 kind: &str,
1406 ) -> Result<tree_sitter::Node<'tree>, ParseError> {
1407 self.optional_kind(node, kind)
1408 .ok_or_else(|| self.unsupported(kind, node))
1409 }
1410
1411 fn text(&self, node: tree_sitter::Node<'_>) -> Cow<'_, str> {
1413 let range = self
1414 .span(node)
1415 .bounds()
1416 .map_or_else(|| node.byte_range(), |(start, end)| start..end);
1417 String::from_utf8_lossy(&self.source[range])
1418 }
1419
1420 fn span(&self, node: tree_sitter::Node<'_>) -> Span {
1422 let range = node.byte_range();
1423 self.aliases
1424 .iter()
1425 .find(|alias| alias.bare == range)
1426 .map_or_else(
1427 || {
1428 self.source_span.subspan(
1429 node.start_byte().min(self.source.len()),
1430 node.end_byte().min(self.source.len()),
1431 )
1432 },
1433 |alias| self.source_span.subspan(alias.full.start, alias.full.end),
1434 )
1435 }
1436
1437 fn unsupported(&self, kind: impl Into<String>, node: tree_sitter::Node<'_>) -> ParseError {
1439 self.unsupported_span(kind, self.span(node))
1440 }
1441
1442 fn unsupported_span(&self, kind: impl Into<String>, span: Span) -> ParseError {
1444 ParseError::UnsupportedNode {
1445 kind: kind.into(),
1446 span,
1447 }
1448 }
1449}
1450
1451#[derive(Clone)]
1452struct CoreAlias {
1454 full: Range<usize>,
1456 bare: Range<usize>,
1458}
1459
1460fn renamed_source(source: &str) -> Result<(Cow<'_, str>, Vec<CoreAlias>), LexError> {
1462 let tokens = lex_str(source)?;
1463 let mut aliases = Vec::new();
1464 collect_core_aliases(&tokens, &mut aliases);
1465 if aliases.is_empty() {
1466 return Ok((Cow::Borrowed(source), aliases));
1467 }
1468
1469 let mut renamed = source.as_bytes().to_vec();
1470 for alias in &aliases {
1471 renamed[alias.full.start..alias.bare.start].fill(b' ');
1472 }
1473 Ok((
1474 Cow::Owned(String::from_utf8(renamed).expect("replacing ASCII bytes preserves UTF-8")),
1475 aliases,
1476 ))
1477}
1478
1479type RecoveredSource<'source> = (Cow<'source, str>, Vec<CoreAlias>, Vec<LexError>);
1481
1482fn renamed_source_recovering(source: &str) -> Result<RecoveredSource<'_>, LexError> {
1484 let recovered = lex_str_recovering(source)?;
1485 let (tokens, diagnostics) = recovered.into_parts();
1486 let mut aliases = Vec::new();
1487 collect_core_aliases(&tokens, &mut aliases);
1488 let mut missing = Vec::new();
1489 collect_missing_closers(&tokens, &mut missing);
1490 let missing_literal = diagnostics
1491 .iter()
1492 .find_map(|diagnostic| match diagnostic.kind() {
1493 crate::LexErrorKind::UnterminatedString => Some("\""),
1494 crate::LexErrorKind::UnterminatedRawString => Some("///"),
1495 _ => None,
1496 });
1497
1498 if aliases.is_empty() && missing.is_empty() && missing_literal.is_none() {
1499 return Ok((Cow::Borrowed(source), aliases, diagnostics));
1500 }
1501
1502 let mut renamed = source.as_bytes().to_vec();
1503 for alias in &aliases {
1504 renamed[alias.full.start..alias.bare.start].fill(b' ');
1505 }
1506 if !missing.is_empty() && ends_in_line_comment(&tokens, source.len()) {
1509 renamed.push(b'\n');
1510 }
1511 if let Some(closer) = missing_literal {
1512 renamed.extend_from_slice(closer.as_bytes());
1513 }
1514 for kind in missing {
1515 renamed.extend_from_slice(kind.closing().as_bytes());
1516 }
1517 Ok((
1518 Cow::Owned(String::from_utf8(renamed).expect("ASCII recovery preserves UTF-8")),
1519 aliases,
1520 diagnostics,
1521 ))
1522}
1523
1524fn ends_in_line_comment(tokens: &TokenStream, source_len: usize) -> bool {
1526 CommentTrivia::of(tokens)
1527 .into_trivia()
1528 .last()
1529 .is_some_and(|comment| {
1530 comment.kind() == TriviaKind::LineComment && comment.span().end() == Some(source_len)
1531 })
1532}
1533
1534fn collect_missing_closers(tokens: &TokenStream, missing: &mut Vec<DelimiterKind>) {
1536 for token in tokens.iter() {
1537 let TokenTree::Group(group) = token else {
1538 continue;
1539 };
1540 collect_missing_closers(group.stream(), missing);
1541 if !group.delimiter().is_closed() {
1542 missing.push(group.delim_kind());
1543 }
1544 }
1545}
1546
1547fn collect_core_aliases(tokens: &TokenStream, aliases: &mut Vec<CoreAlias>) {
1549 for token in tokens.iter() {
1550 match token {
1551 TokenTree::Group(group) => collect_core_aliases(group.stream(), aliases),
1552 TokenTree::Ident(identifier) => {
1553 let spelling = identifier.text();
1554 let bare = crate::lexer::canonical_word_spelling(spelling);
1555 if bare == spelling {
1556 continue;
1557 }
1558 let Some((start, end)) = identifier.expect_span().bounds() else {
1559 continue;
1560 };
1561 aliases.push(CoreAlias {
1562 full: start..end,
1563 bare: end - bare.len()..end,
1564 });
1565 }
1566 TokenTree::Literal(_) | TokenTree::Punct(_) => {}
1567 }
1568 }
1569}
1570
1571#[derive(Clone)]
1572pub struct TreeSitterNode<'tree, 'source> {
1574 node: tree_sitter::Node<'tree>,
1576 source: &'source [u8],
1578 span: Option<Span>,
1580}
1581
1582impl<'tree, 'source> TreeSitterNode<'tree, 'source> {
1583 pub fn new(node: tree_sitter::Node<'tree>, source: &'source [u8]) -> Self {
1585 Self {
1586 node,
1587 source,
1588 span: None,
1589 }
1590 }
1591
1592 fn with_span(node: tree_sitter::Node<'tree>, source: &'source [u8], span: Span) -> Self {
1594 Self {
1595 node,
1596 source,
1597 span: Some(span),
1598 }
1599 }
1600}
1601
1602impl ExternalCstNode for TreeSitterNode<'_, '_> {
1603 type Children<'syntax>
1604 = IntoIter<ExternalCstChild<Self>>
1605 where
1606 Self: 'syntax;
1607
1608 fn identity(&self) -> CSTNodeClassLabel<'_> {
1609 CSTNodeClassLabel::new(self.node.kind(), self.node.is_named())
1610 }
1611
1612 fn children(&self) -> Self::Children<'_> {
1613 let parent = self.node;
1614 (0..parent.child_count())
1615 .filter_map(|index| {
1616 let index = u32::try_from(index).expect("Tree-sitter child count fits u32");
1617 parent.child(index).map(|node| ExternalCstChild {
1618 field: parent.field_name_for_child(index),
1619 node: Self::new(node, self.source),
1620 })
1621 })
1622 .collect::<Vec<_>>()
1623 .into_iter()
1624 }
1625
1626 fn text(&self) -> Cow<'_, str> {
1627 let range = self
1628 .span
1629 .as_ref()
1630 .and_then(Span::bounds)
1631 .map_or_else(|| self.node.byte_range(), |(start, end)| start..end);
1632 String::from_utf8_lossy(&self.source[range])
1633 }
1634
1635 fn is_extra(&self) -> bool {
1636 self.node.is_extra()
1637 }
1638}
1639
1640impl Spanned for TreeSitterNode<'_, '_> {
1641 fn try_span(&self) -> Option<Span> {
1642 self.span.clone()
1643 }
1644}
1645
1646#[cfg(test)]
1647mod tests {
1648 use super::*;
1649
1650 fn expressions(source: &str) -> [Expr; 2] {
1651 [
1652 parse_file(source).unwrap(),
1653 crate::parse_native(source).unwrap(),
1654 ]
1655 .map(|mut file| {
1656 assert_eq!(file.cells.len(), 1, "source: {source}");
1657 let PackedContent::Expr(value) = file.cells.pop().unwrap().content else {
1658 panic!("expected one expression for {source}");
1659 };
1660 *value
1661 })
1662 }
1663
1664 #[test]
1665 fn empty_parentheses_are_empty_sequences_in_both_backends() {
1666 for source in ["()", "( )", "(-* comment *-)", "(-- comment\n)"] {
1667 for expression in expressions(source) {
1668 let Expr::Collection(ExprCollection::Sequence(sequence)) = expression else {
1669 panic!("expected an empty sequence for {source}, found {expression:?}");
1670 };
1671 assert!(sequence.statements.is_empty(), "source: {source}");
1672 assert!(sequence.elements.is_none(), "source: {source}");
1673 assert_eq!(sequence.span().text(), Some(source));
1674 }
1675 }
1676 }
1677
1678 #[test]
1679 fn parenthesized_values_and_statements_remain_holders() {
1680 for source in ["(x)", "(x;)", "(x; y)"] {
1681 for expression in expressions(source) {
1682 assert!(matches!(expression, Expr::Holder(_)), "source: {source}");
1683 }
1684 }
1685 }
1686}