1use std::borrow::Cow;
10use std::error::Error;
11use std::fmt::{Display, Formatter};
12use std::ops::Range;
13use std::vec::IntoIter;
14
15use crate::native::{assignment_pack, installation_value, lambda_parameters};
16use crate::nodes::*;
17use crate::{
18 CSTNodeClassLabel, DelimiterKind, DelimiterToken, DoubleSpan, ExternalCstChild,
19 ExternalCstNode, LexError, Parser, Punctuated, Reconstruct, ReconstructError, Recovered,
20 SourceFile, Span, Spanned, TextEdit, TokenStream, TokenTree, lex_str, lex_str_recovering,
21};
22
23#[derive(Debug)]
24pub enum ParseError {
26 Lex(LexError),
28 Language(tree_sitter::LanguageError),
30 Cancelled,
32 InvalidEdit,
34 InvalidSyntax(Span),
36 Reconstruct(ReconstructError),
38 UnsupportedNode {
40 kind: String,
42 span: Span,
44 },
45}
46
47impl Display for ParseError {
48 fn fmt(&self, formatter: &mut Formatter<'_>) -> std::fmt::Result {
49 match self {
50 Self::Lex(error) => error.fmt(formatter),
51 Self::Language(error) => error.fmt(formatter),
52 Self::Cancelled => formatter.write_str("Tree-sitter parsing was cancelled"),
53 Self::InvalidEdit => formatter.write_str("source edit is outside the current buffer"),
54 Self::InvalidSyntax(span) => match span.start() {
55 Some(start) => write!(formatter, "invalid Macaulay2 syntax at byte {start}"),
56 None => formatter.write_str("invalid Macaulay2 syntax"),
57 },
58 Self::Reconstruct(error) => error.fmt(formatter),
59 Self::UnsupportedNode { kind, .. } => {
60 write!(
61 formatter,
62 "Tree-sitter node `{kind}` has no typed representation"
63 )
64 }
65 }
66 }
67}
68
69impl Error for ParseError {
70 fn source(&self) -> Option<&(dyn Error + 'static)> {
71 match self {
72 Self::Lex(error) => Some(error),
73 Self::Language(error) => Some(error),
74 Self::Reconstruct(error) => Some(error),
75 Self::Cancelled
76 | Self::InvalidEdit
77 | Self::InvalidSyntax(_)
78 | Self::UnsupportedNode { .. } => None,
79 }
80 }
81}
82
83impl From<ReconstructError> for ParseError {
84 fn from(error: ReconstructError) -> Self {
85 Self::Reconstruct(error)
86 }
87}
88
89impl From<LexError> for ParseError {
90 fn from(error: LexError) -> Self {
91 Self::Lex(error)
92 }
93}
94
95pub struct TreeSitterParser {
97 parser: tree_sitter::Parser,
98}
99
100pub struct RealtimeParser {
108 parser: tree_sitter::Parser,
109 source: String,
110 parse_view: String,
111 tree: tree_sitter::Tree,
112 syntax: SourceFile,
113 diagnostics: Vec<LexError>,
114 changed_ranges: Vec<Span>,
115}
116
117impl RealtimeParser {
118 pub fn new(source: impl Into<String>) -> Result<Self, ParseError> {
125 let source = source.into();
126 let mut parser = TreeSitterParser::new()?.parser;
127 let ParsedTree {
128 parse_view,
129 tree,
130 syntax,
131 diagnostics,
132 } = parse_recovered_tree(&mut parser, &source, None)?;
133 Ok(Self {
134 parser,
135 source,
136 parse_view,
137 tree,
138 syntax,
139 diagnostics,
140 changed_ranges: Vec::new(),
141 })
142 }
143
144 pub fn apply_edit(&mut self, edit: &TextEdit) -> Result<(), ParseError> {
155 let source = edit.apply(&self.source).ok_or(ParseError::InvalidEdit)?;
156 let (view, aliases, diagnostics) = renamed_source_recovering(&source)?;
157 let parse_view = view.into_owned();
158
159 let mut edited_tree = self.tree.clone();
160 edited_tree.edit(&input_edit_between(&self.parse_view, &parse_view));
161 let tree = self
162 .parser
163 .parse(parse_view.as_bytes(), Some(&edited_tree))
164 .ok_or(ParseError::Cancelled)?;
165 if let Some(error) = first_error(tree.root_node()) {
166 return Err(ParseError::InvalidSyntax(Span::new(
167 error.start_byte().min(source.len()),
168 error.end_byte().min(source.len()),
169 )));
170 }
171 let syntax = Lowerer::new(&source, aliases).source_file(tree.root_node())?;
172 let changed_ranges = edited_tree
173 .changed_ranges(&tree)
174 .map(|range| {
175 Span::new(
176 range.start_byte.min(source.len()),
177 range.end_byte.min(source.len()),
178 )
179 })
180 .collect();
181
182 self.source = source;
183 self.parse_view = parse_view;
184 self.tree = tree;
185 self.syntax = syntax;
186 self.diagnostics = diagnostics;
187 self.changed_ranges = changed_ranges;
188 Ok(())
189 }
190
191 pub fn source(&self) -> &str {
193 &self.source
194 }
195
196 pub fn syntax(&self) -> &SourceFile {
198 &self.syntax
199 }
200
201 pub fn diagnostics(&self) -> &[LexError] {
203 &self.diagnostics
204 }
205
206 pub fn changed_ranges(&self) -> &[Span] {
208 &self.changed_ranges
209 }
210
211 pub fn into_syntax(self) -> SourceFile {
213 self.syntax
214 }
215}
216
217struct ParsedTree {
218 parse_view: String,
219 tree: tree_sitter::Tree,
220 syntax: SourceFile,
221 diagnostics: Vec<LexError>,
222}
223
224fn parse_recovered_tree(
225 parser: &mut tree_sitter::Parser,
226 source: &str,
227 old_tree: Option<&tree_sitter::Tree>,
228) -> Result<ParsedTree, ParseError> {
229 let (view, aliases, diagnostics) = renamed_source_recovering(source)?;
230 let parse_view = view.into_owned();
231 let tree = parser
232 .parse(parse_view.as_bytes(), old_tree)
233 .ok_or(ParseError::Cancelled)?;
234 if let Some(error) = first_error(tree.root_node()) {
235 return Err(ParseError::InvalidSyntax(Span::new(
236 error.start_byte().min(source.len()),
237 error.end_byte().min(source.len()),
238 )));
239 }
240 let syntax = Lowerer::new(source, aliases).source_file(tree.root_node())?;
241 Ok(ParsedTree {
242 parse_view,
243 tree,
244 syntax,
245 diagnostics,
246 })
247}
248
249fn input_edit_between(old: &str, new: &str) -> tree_sitter::InputEdit {
250 let mut start = old
251 .as_bytes()
252 .iter()
253 .zip(new.as_bytes())
254 .take_while(|(old, new)| old == new)
255 .count();
256 while !old.is_char_boundary(start) || !new.is_char_boundary(start) {
257 start -= 1;
258 }
259
260 let available_suffix = old.len().min(new.len()).saturating_sub(start);
261 let mut suffix = old
262 .as_bytes()
263 .iter()
264 .rev()
265 .zip(new.as_bytes().iter().rev())
266 .take(available_suffix)
267 .take_while(|(old, new)| old == new)
268 .count();
269 while !old.is_char_boundary(old.len() - suffix) || !new.is_char_boundary(new.len() - suffix) {
270 suffix -= 1;
271 }
272
273 let old_end = old.len() - suffix;
274 let new_end = new.len() - suffix;
275 tree_sitter::InputEdit {
276 start_byte: start,
277 old_end_byte: old_end,
278 new_end_byte: new_end,
279 start_position: point_at(old, start),
280 old_end_position: point_at(old, old_end),
281 new_end_position: point_at(new, new_end),
282 }
283}
284
285fn point_at(source: &str, offset: usize) -> tree_sitter::Point {
286 let before = &source[..offset];
287 let row = before.bytes().filter(|byte| *byte == b'\n').count();
288 let column = before
289 .as_bytes()
290 .iter()
291 .rposition(|byte| *byte == b'\n')
292 .map_or(before.len(), |newline| before.len() - newline - 1);
293 tree_sitter::Point { row, column }
294}
295
296impl TreeSitterParser {
297 pub fn new() -> Result<Self, ParseError> {
304 let mut parser = tree_sitter::Parser::new();
305 parser
306 .set_language(&tree_sitter_macaulay2::language())
307 .map_err(ParseError::Language)?;
308 Ok(Self { parser })
309 }
310
311 fn parse_source(&mut self, source: &str) -> Result<SourceFile, ParseError> {
312 let (renamed, aliases) = renamed_source(source)?;
313 let tree = self
314 .parser
315 .parse(renamed.as_bytes(), None)
316 .ok_or(ParseError::Cancelled)?;
317 if let Some(error) = first_error(tree.root_node()) {
318 return Err(ParseError::InvalidSyntax(
319 TreeSitterNode::new(error, source.as_bytes()).span(),
320 ));
321 }
322 Lowerer::new(source, aliases).source_file(tree.root_node())
323 }
324
325 pub fn parse_recovering(
335 &mut self,
336 source: &str,
337 ) -> Result<Recovered<SourceFile, LexError>, ParseError> {
338 let (renamed, aliases, diagnostics) = renamed_source_recovering(source)?;
339 let tree = self
340 .parser
341 .parse(renamed.as_bytes(), None)
342 .ok_or(ParseError::Cancelled)?;
343 if let Some(error) = first_error(tree.root_node()) {
344 return Err(ParseError::InvalidSyntax(Span::new(
345 error.start_byte().min(source.len()),
346 error.end_byte().min(source.len()),
347 )));
348 }
349 let syntax = Lowerer::new(source, aliases).source_file(tree.root_node())?;
350 Ok(Recovered::new(syntax, diagnostics))
351 }
352}
353
354impl Parser for TreeSitterParser {
355 type Error = ParseError;
356
357 fn parse_stream(&mut self, tokens: TokenStream) -> Result<SourceFile, Self::Error> {
358 let source = tokens.to_string();
359 self.parse_source(&source)
360 }
361}
362
363pub fn parse_file(source: &str) -> Result<SourceFile, ParseError> {
369 let mut parser = TreeSitterParser::new()?;
370 parser.parse_source(source)
371}
372
373pub fn parse_file_recovering(source: &str) -> Result<Recovered<SourceFile, LexError>, ParseError> {
380 TreeSitterParser::new()?.parse_recovering(source)
381}
382
383pub fn parse_tokens(tokens: &TokenStream) -> Result<SourceFile, ParseError> {
390 parse_file(&tokens.to_string())
391}
392
393fn first_error(root: tree_sitter::Node<'_>) -> Option<tree_sitter::Node<'_>> {
394 let mut pending = vec![root];
395 while let Some(node) = pending.pop() {
396 if node.is_error() || node.is_missing() {
397 return Some(node);
398 }
399 pending.extend((0..node.child_count()).rev().filter_map(|index| {
400 node.child(u32::try_from(index).expect("Tree-sitter child count fits u32"))
401 }));
402 }
403 None
404}
405
406struct Lowerer<'source> {
407 source: &'source [u8],
408 source_span: Span,
409 aliases: Vec<CoreAlias>,
410}
411
412impl<'source> Lowerer<'source> {
413 fn new(source: &'source str, aliases: Vec<CoreAlias>) -> Self {
414 Self {
415 source: source.as_bytes(),
416 source_span: Span::source(source),
417 aliases,
418 }
419 }
420
421 fn source_file(&self, root: tree_sitter::Node<'_>) -> Result<SourceFile, ParseError> {
422 let mut cells = Vec::new();
423 let raw_cells = self.semantic_children(root);
424 for (index, child) in raw_cells.iter().copied().enumerate() {
425 match child.kind() {
426 "cell" | "muted" => {
427 let next = raw_cells.get(index + 1).copied();
428 cells.push(self.cell(child, self.eoc_offset(child, next))?);
429 }
430 kind => return Err(self.unsupported(kind, child)),
431 }
432 }
433 Ok(SourceFile::new(
434 cells,
435 Eof::new("", Span::from_offset(self.source.len())),
436 ))
437 }
438
439 fn cell(&self, node: tree_sitter::Node<'_>, eoc_offset: usize) -> Result<Cell, ParseError> {
440 let (content, semicolon) = if node.kind() == "muted" {
441 let semicolon = self.required_kind(node, ";")?;
442 (
443 self.expr_pack(self.children(node))?,
444 Some(self.reconstruct(semicolon)?),
445 )
446 } else {
447 let child = self.only_semantic_child(node)?;
448 let pack = if child.kind() == "naked_sequence" {
449 self.expr_pack(self.children(child))?
450 } else {
451 ExprPack::new(Punctuated::from_single(Component::Expr(Box::new(
452 self.expr(child)?,
453 ))))
454 };
455 (pack, None)
456 };
457 Ok(Cell::new(
458 content,
459 semicolon,
460 Eoc::new("", Span::from_offset(eoc_offset)),
461 ))
462 }
463
464 fn eoc_offset(
465 &self,
466 node: tree_sitter::Node<'_>,
467 next: Option<tree_sitter::Node<'_>>,
468 ) -> usize {
469 if node.kind() == "muted" {
470 return node.end_byte().min(self.source.len());
471 }
472 let start = node.end_byte().min(self.source.len());
473 let end = next
474 .map_or(self.source.len(), |next| next.start_byte())
475 .min(self.source.len());
476 self.source[start..end]
477 .iter()
478 .position(|byte| *byte == b'\n')
479 .map_or(end, |relative| start + relative + 1)
480 }
481
482 fn expr_pack(&self, nodes: Vec<tree_sitter::Node<'_>>) -> Result<ExprPack, ParseError> {
483 let pack_span = nodes
484 .iter()
485 .fold(Span::detached(), |span, node| span.join(self.span(*node)));
486 let mut values = Vec::new();
487 let mut commas = Vec::new();
488 for node in nodes.into_iter().filter(|node| !node.is_extra()) {
489 match node.kind() {
490 "," => commas.push(self.reconstruct::<Token![,]>(node)?),
491 "empty_component" => values.push(Component::Empty(Empty::new("", self.span(node)))),
492 ";" | "(" | ")" | "[" | "]" | "{" | "}" | "<|" | "|>" | "muted" => {}
493 _ if node.is_named() => values.push(Component::Expr(Box::new(self.expr(node)?))),
494 _ => {}
495 }
496 }
497 let mut values = values.into_iter();
498 let Some(first) = values.next() else {
499 return Err(self.unsupported_span("empty expression pack", pack_span));
500 };
501 let value_count = values.len() + 1;
502 let comma_count = commas.len();
503 if value_count != comma_count + 1 {
504 return Err(self.unsupported_span("invalid expression pack", pack_span));
505 }
506 let rest = commas
507 .into_iter()
508 .zip(values)
509 .collect::<Vec<(Token![,], Component)>>();
510 Ok(ExprPack::new(Punctuated::new(first, rest)))
511 }
512
513 fn expr(&self, node: tree_sitter::Node<'_>) -> Result<Expr, ParseError> {
514 match node.kind() {
515 "symbol" => Ok(self.reconstruct::<Symbol>(node)?.into()),
516 "integer_literal" if self.text(node).contains('p') => {
517 Ok(FloatLiteral::new(self.text(node), self.span(node)).into())
518 }
519 "integer_literal" => Ok(self.reconstruct::<IntegerLiteral>(node)?.into()),
520 "float_literal" => Ok(self.reconstruct::<FloatLiteral>(node)?.into()),
521 "string_literal" => self.string_literal(node),
522 "raw_string_literal" => self.raw_string_literal(node),
523 "array" | "list" | "angle_bar_list" | "sequence" | "parenthesized_expression" => {
524 self.collection(node)
525 }
526 "binary_expression" => self.binary_expr(node),
527 "prefix_expression" => self.prefix_expr(node),
528 "postfix_expression" => self.postfix_expr(node),
529 "lambda_expression" => self.lambda_expression(node),
530 "assignment"
531 | "local_assignment"
532 | "binary_assignment"
533 | "prefix_assignment"
534 | "postfix_assignment"
535 | "binary_installation"
536 | "prefix_installation"
537 | "postfix_installation"
538 | "structured_binding"
539 | "local_structured_binding" => self.assignment(node),
540 "evaluated_assignment" => Ok(EvaluatedAssignment::new(
541 self.expr(self.required_field(node, "left")?)?,
542 self.reconstruct(self.required_field(node, "operator")?)?,
543 self.expr(self.required_field(node, "right")?)?,
544 )
545 .into()),
546 "option" => Ok(OptionExpression::new(
547 self.expr(self.required_field(node, "left")?)?,
548 self.reconstruct(self.required_field(node, "operator")?)?,
549 self.expr(self.required_field(node, "right")?)?,
550 )
551 .into()),
552 "if_statement" => self.if_statement(node),
553 "for_loop" => self.for_loop(node),
554 "while_loop" => self.while_loop(node),
555 "try_statement" => self.try_statement(node),
556 "quote_expression" => self.quote_expression(node),
557 "new_statement" => self.new_statement(node),
558 "break_statement" => Ok(BreakExpr::new(
559 self.reconstruct(self.required_kind(node, "break")?)?,
560 self.first_expression_child(node)
561 .map(|child| self.expr(child))
562 .transpose()?,
563 )
564 .into()),
565 "continue_statement" => Ok(ContinueExpr::new(
566 self.reconstruct(self.required_kind(node, "continue")?)?,
567 self.first_expression_child(node)
568 .map(|child| self.expr(child))
569 .transpose()?,
570 )
571 .into()),
572 "return_statement" => Ok(ReturnExpr::new(
573 self.reconstruct(self.required_kind(node, "return")?)?,
574 self.first_expression_child(node)
575 .map(|child| self.expr(child))
576 .transpose()?,
577 )
578 .into()),
579 "catch_statement" => Ok(Catch::new(
580 self.reconstruct(self.required_kind(node, "catch")?)?,
581 self.expr(self.required_expression_child(node)?)?,
582 )
583 .into()),
584 "throw_statement" => Ok(Throw::new(
585 self.reconstruct(self.required_kind(node, "throw")?)?,
586 self.expr(self.required_expression_child(node)?)?,
587 )
588 .into()),
589 "trap_statement" => Ok(Trap::new(
590 self.reconstruct(self.required_kind(node, "trap")?)?,
591 self.expr(self.required_expression_child(node)?)?,
592 )
593 .into()),
594 "debug_clause" => self.debug_clause(node),
595 kind => Err(self.unsupported(kind, node)),
596 }
597 }
598
599 fn collection(&self, node: tree_sitter::Node<'_>) -> Result<Expr, ParseError> {
600 let spans = self.delimiter_spans(node)?;
601 let statements = self
602 .semantic_children(node)
603 .into_iter()
604 .filter(|child| child.kind() == "muted")
605 .map(|child| self.statement(child))
606 .collect::<Result<Vec<_>, _>>()?;
607
608 if node.kind() == "parenthesized_expression" {
609 let value = self
610 .semantic_children(node)
611 .into_iter()
612 .find(|child| child.kind() != "muted")
613 .map(|child| self.expr(child))
614 .transpose()?;
615 let mut holder = Holder::new(statements, value);
616 holder.delimiter = <Delimiter![()] as DelimiterToken>::new(spans);
617 return Ok(holder.into());
618 }
619
620 let has_elements = self.children(node).into_iter().any(|child| {
621 !child.is_extra()
622 && (child.kind() == ","
623 || child.kind() == "empty_component"
624 || (child.is_named() && child.kind() != "muted"))
625 });
626 let elements = has_elements
627 .then(|| self.expr_pack(self.children(node)))
628 .transpose()?;
629 Ok(match node.kind() {
630 "array" => {
631 let mut value = Array::new(statements, elements);
632 value.delimiter = <Delimiter![[]] as DelimiterToken>::new(spans);
633 value.into()
634 }
635 "list" => {
636 let mut value = List::new(statements, elements);
637 value.delimiter = <Delimiter![{}] as DelimiterToken>::new(spans);
638 value.into()
639 }
640 "angle_bar_list" => {
641 let mut value = AngleBarList::new(statements, elements);
642 value.delimiter = <Delimiter![<| |>] as DelimiterToken>::new(spans);
643 value.into()
644 }
645 "sequence" => {
646 let mut value = Sequence::new(statements, elements);
647 value.delimiter = <Delimiter![()] as DelimiterToken>::new(spans);
648 value.into()
649 }
650 kind => return Err(self.unsupported(kind, node)),
651 })
652 }
653
654 fn statement(&self, node: tree_sitter::Node<'_>) -> Result<Statement, ParseError> {
655 Ok(Statement::new(
656 self.expr_pack(self.children(node))?,
657 self.reconstruct(self.required_kind(node, ";")?)?,
658 ))
659 }
660
661 fn string_literal(&self, node: tree_sitter::Node<'_>) -> Result<Expr, ParseError> {
662 let elements = self
663 .children(node)
664 .into_iter()
665 .filter(|child| child.kind() != "\"")
666 .filter(|child| !child.is_extra())
667 .map(|child| match child.kind() {
668 "escape_sequence" => self.reconstruct(child).map(StringElement::EscapeSequence),
669 "string_content" => self.reconstruct(child).map(StringElement::StringContent),
670 _ => Ok(StringElement::StringContent(StringContent::new(
671 self.text(child),
672 self.span(child),
673 ))),
674 })
675 .collect::<Result<Vec<_>, ParseError>>()?;
676 Ok(StringLiteral::new(elements, self.span(node)).into())
677 }
678
679 fn raw_string_literal(&self, node: tree_sitter::Node<'_>) -> Result<Expr, ParseError> {
680 let elements = self
681 .children(node)
682 .into_iter()
683 .filter(|child| child.kind() != "///")
684 .filter(|child| !child.is_extra())
685 .map(|child| match child.kind() {
686 "escape_sequence" => self
687 .reconstruct(child)
688 .map(RawStringElement::EscapeSequence),
689 "raw_string_content" => self
690 .reconstruct(child)
691 .map(RawStringElement::RawStringContent),
692 kind => Err(self.unsupported(kind, child)),
693 })
694 .collect::<Result<Vec<_>, ParseError>>()?;
695 Ok(RawStringLiteral::new(elements, self.span(node)).into())
696 }
697
698 fn binary_expr(&self, node: tree_sitter::Node<'_>) -> Result<Expr, ParseError> {
699 let left = self.expr(self.required_field(node, "left")?)?;
700 let operator = self.required_field(node, "operator")?;
701 let right = self.expr(self.required_field(node, "right")?)?;
702 if operator.kind() == "SPACE" {
703 Ok(AdjacentExpr::new(left, Adj::new("", self.span(operator)), right).into())
704 } else {
705 Ok(BinaryExpr::new(left, self.reconstruct(operator)?, right).into())
706 }
707 }
708
709 fn prefix_expr(&self, node: tree_sitter::Node<'_>) -> Result<Expr, ParseError> {
710 Ok(PrefixExpr::new(
711 self.reconstruct(self.required_field(node, "operator")?)?,
712 self.expr(self.required_field(node, "operand")?)?,
713 )
714 .into())
715 }
716
717 fn postfix_expr(&self, node: tree_sitter::Node<'_>) -> Result<Expr, ParseError> {
718 Ok(PostfixExpr::new(
719 self.expr(self.required_field(node, "operand")?)?,
720 self.reconstruct(self.required_field(node, "operator")?)?,
721 )
722 .into())
723 }
724
725 fn lambda_expression(&self, node: tree_sitter::Node<'_>) -> Result<Expr, ParseError> {
726 let parameter_expr = self.expr(self.required_field(node, "parameters")?)?;
727 let parameters = lambda_parameters(parameter_expr)
728 .ok_or_else(|| self.unsupported("lambda parameters", node))?;
729 Ok(LambdaExpression::new(
730 parameters,
731 self.reconstruct(self.required_field(node, "operator")?)?,
732 self.expr(self.required_field(node, "body")?)?,
733 )
734 .into())
735 }
736
737 fn assignment(&self, node: tree_sitter::Node<'_>) -> Result<Expr, ParseError> {
738 let right = self.expr(self.required_field(node, "right")?)?;
739 Ok(match node.kind() {
740 "assignment" => GlobalBinding::new(
741 self.reconstruct(self.required_field(node, "left")?)?,
742 self.reconstruct(self.required_field(node, "operator")?)?,
743 right,
744 )
745 .into(),
746 "local_assignment" => LocalBinding::new(
747 self.reconstruct(self.required_field(node, "left")?)?,
748 self.reconstruct(self.required_field(node, "operator")?)?,
749 right,
750 )
751 .into(),
752 "binary_assignment" | "prefix_assignment" | "postfix_assignment" => {
753 let Expr::OperatorExpr(left) = self.expr(self.required_field(node, "left")?)?
754 else {
755 return Err(self.unsupported("operator assignment target", node));
756 };
757 OperatorAssignment::new(
758 left,
759 self.reconstruct(self.required_field(node, "operator")?)?,
760 right,
761 )
762 .into()
763 }
764 "binary_installation" | "prefix_installation" | "postfix_installation" => {
765 let Expr::OperatorExpr(left) = self.expr(self.required_field(node, "left")?)?
766 else {
767 return Err(self.unsupported("operator installation target", node));
768 };
769 let (typical_value, function) = installation_value(right);
770 match left {
771 OperatorExpr::AdjacentExpr(application) => MethodInstallation::new(
772 *application.left_operand,
773 *application.right_operand,
774 self.reconstruct(self.required_field(node, "operator")?)?,
775 typical_value,
776 function,
777 )
778 .into(),
779 domain => OperatorInstallation::new(
780 domain,
781 self.reconstruct(self.required_field(node, "operator")?)?,
782 typical_value,
783 function,
784 )
785 .into(),
786 }
787 }
788 "structured_binding" | "local_structured_binding" => {
789 let pack_expr = self.expr(self.required_field(node, "binding_pack")?)?;
790 let pack = assignment_pack(pack_expr)
791 .ok_or_else(|| self.unsupported("assignment pack", node))?;
792 if node.kind() == "local_structured_binding" {
793 LocalParallelAssignment::new(
794 pack,
795 self.reconstruct(self.required_field(node, "operator")?)?,
796 right,
797 )
798 .into()
799 } else {
800 GlobalParallelAssignment::new(
801 pack,
802 self.reconstruct(self.required_field(node, "operator")?)?,
803 right,
804 )
805 .into()
806 }
807 }
808 kind => return Err(self.unsupported(kind, node)),
809 })
810 }
811
812 fn then_clause(&self, node: tree_sitter::Node<'_>) -> Result<ThenClause, ParseError> {
813 Ok(ThenClause::new(
814 self.reconstruct(self.required_kind(node, "then")?)?,
815 self.expr(self.required_expression_child(node)?)?,
816 ))
817 }
818
819 fn else_clause(&self, node: tree_sitter::Node<'_>) -> Result<ElseClause, ParseError> {
820 Ok(ElseClause::new(
821 self.reconstruct(self.required_kind(node, "else")?)?,
822 self.expr(self.required_expression_child(node)?)?,
823 ))
824 }
825
826 fn if_statement(&self, node: tree_sitter::Node<'_>) -> Result<Expr, ParseError> {
827 Ok(IfStatement::new(
828 self.reconstruct(self.required_kind(node, "if")?)?,
829 self.expr(self.required_field(node, "condition")?)?,
830 self.then_clause(self.required_kind(node, "then_clause")?)?,
831 self.optional_kind(node, "else_clause")
832 .map(|child| self.else_clause(child))
833 .transpose()?,
834 )
835 .into())
836 }
837
838 fn loop_body(&self, node: tree_sitter::Node<'_>) -> Result<LoopBody, ParseError> {
839 let list_step = self
840 .optional_kind(node, "list")
841 .map(|token| {
842 Ok::<_, ParseError>(ListStep::new(
843 self.reconstruct(token)?,
844 self.expr(self.required_field(node, "listed_value")?)?,
845 ))
846 })
847 .transpose()?;
848 let do_step = self
849 .optional_kind(node, "do")
850 .map(|token| {
851 Ok::<_, ParseError>(DoStep::new(
852 self.reconstruct(token)?,
853 self.expr(self.required_field(node, "ignored_value")?)?,
854 ))
855 })
856 .transpose()?;
857 Ok(LoopBody::new(list_step, do_step))
858 }
859
860 fn for_loop(&self, node: tree_sitter::Node<'_>) -> Result<Expr, ParseError> {
861 let iteration_domain = self
862 .optional_kind(node, "iteration_range")
863 .map(|range| self.iteration_domain(range))
864 .transpose()?;
865 let when_condition = self
866 .optional_kind(node, "when")
867 .map(|token| {
868 Ok::<_, ParseError>(WhenCondition::new(
869 self.reconstruct(token)?,
870 self.expr(self.required_field(node, "filter")?)?,
871 ))
872 })
873 .transpose()?;
874 Ok(ForLoop::new(
875 self.reconstruct(self.required_kind(node, "for")?)?,
876 self.reconstruct(self.required_field(node, "variable")?)?,
877 iteration_domain,
878 when_condition,
879 self.loop_body(self.required_kind(node, "loop_body")?)?,
880 )
881 .into())
882 }
883
884 fn iteration_domain(&self, node: tree_sitter::Node<'_>) -> Result<IterationDomain, ParseError> {
885 if let Some(token) = self.optional_kind(node, "in") {
886 return Ok(IterIn::new(
887 self.reconstruct(token)?,
888 self.expr(self.required_field(node, "iterated_collection")?)?,
889 )
890 .into());
891 }
892 let lower_bound = self
893 .optional_kind(node, "from")
894 .map(|token| {
895 Ok::<_, ParseError>(RangeBoundFrom::new(
896 self.reconstruct(token)?,
897 self.expr(self.required_field(node, "range_start")?)?,
898 ))
899 })
900 .transpose()?;
901 let upper_bound = self
902 .optional_kind(node, "to")
903 .map(|token| {
904 Ok::<_, ParseError>(RangeBoundTo::new(
905 self.reconstruct(token)?,
906 self.expr(self.required_field(node, "range_end")?)?,
907 ))
908 })
909 .transpose()?;
910 Ok(IterRange::new(lower_bound, upper_bound).into())
911 }
912
913 fn while_loop(&self, node: tree_sitter::Node<'_>) -> Result<Expr, ParseError> {
914 Ok(WhileLoop::new(
915 self.reconstruct(self.required_kind(node, "while")?)?,
916 self.expr(self.required_field(node, "condition")?)?,
917 self.loop_body(self.required_kind(node, "loop_body")?)?,
918 )
919 .into())
920 }
921
922 fn new_statement(&self, node: tree_sitter::Node<'_>) -> Result<Expr, ParseError> {
923 let mut installation = None;
924 let class =
925 self.new_statement_element(self.required_field(node, "class")?, &mut installation)?;
926 let parent_class = self
927 .optional_kind(node, "of")
928 .map(|token| {
929 Ok::<_, ParseError>(OfClass::new(
930 self.reconstruct(token)?,
931 self.new_statement_element(
932 self.required_field(node, "parent")?,
933 &mut installation,
934 )?,
935 ))
936 })
937 .transpose()?;
938 let instance = self
939 .optional_kind(node, "from")
940 .map(|token| {
941 Ok::<_, ParseError>(FromInstance::new(
942 self.reconstruct(token)?,
943 self.new_statement_element(
944 self.required_field(node, "instance")?,
945 &mut installation,
946 )?,
947 ))
948 })
949 .transpose()?;
950 let statement = NewStatement::new(
951 self.reconstruct(self.required_kind(node, "new")?)?,
952 class,
953 parent_class,
954 instance,
955 );
956 Ok(match installation {
957 Some((operator, function)) => {
958 NewInstallation::new(statement, operator, function).into()
959 }
960 None => statement.into(),
961 })
962 }
963
964 fn new_statement_element(
965 &self,
966 node: tree_sitter::Node<'_>,
967 installation: &mut Option<(Token![:=], Expr)>,
968 ) -> Result<Expr, ParseError> {
969 match node.kind() {
970 "assignment" => return Err(self.unsupported("`new` assignment with `=`", node)),
971 "local_assignment" => {}
972 _ => return self.expr(node),
973 }
974 *installation = Some((
975 self.reconstruct(self.required_field(node, "operator")?)?,
976 self.expr(self.required_field(node, "right")?)?,
977 ));
978 self.expr(self.required_field(node, "left")?)
979 }
980
981 fn try_statement(&self, node: tree_sitter::Node<'_>) -> Result<Expr, ParseError> {
982 let value = self
983 .semantic_children(node)
984 .into_iter()
985 .find(|child| {
986 child.kind() != "then_clause"
987 && child.kind() != "else_clause"
988 && child.kind() != "except_clause"
989 })
990 .ok_or_else(|| self.unsupported("try value", node))?;
991 let on_success = self
992 .optional_kind(node, "then_clause")
993 .map(|child| self.then_clause(child))
994 .transpose()?;
995 let fallback = self
996 .child_by_field(node, "fallback")
997 .map(|child| match child.kind() {
998 "else_clause" => self.else_clause(child).map(TryFallback::ElseClause),
999 "except_clause" => self.except_do(child).map(TryFallback::ExceptDo),
1000 kind => Err(self.unsupported(kind, child)),
1001 })
1002 .transpose()?;
1003 Ok(TryStatement::new(
1004 self.reconstruct(self.required_kind(node, "try")?)?,
1005 self.expr(value)?,
1006 on_success,
1007 fallback,
1008 )
1009 .into())
1010 }
1011
1012 fn except_do(&self, node: tree_sitter::Node<'_>) -> Result<ExceptDo, ParseError> {
1013 Ok(ExceptDo::new(
1014 self.reconstruct(self.required_kind(node, "except")?)?,
1015 self.reconstruct(self.required_field(node, "exception")?)?,
1016 self.reconstruct(self.required_kind(node, "do")?)?,
1017 self.expr(self.required_expression_child(node)?)?,
1018 ))
1019 }
1020
1021 fn quote_expression(&self, node: tree_sitter::Node<'_>) -> Result<Expr, ParseError> {
1022 let token = self
1023 .children(node)
1024 .into_iter()
1025 .find(|child| {
1026 matches!(
1027 child.kind(),
1028 "symbol" | "local" | "global" | "threadVariable" | "threadLocal"
1029 ) && self.child_by_field(node, "token") != Some(*child)
1030 })
1031 .ok_or_else(|| self.unsupported("quote specifier", node))?;
1032 let specifier = match token.kind() {
1033 "symbol" => QuoteSpecifier::Symbol(self.reconstruct(token)?),
1034 "local" => QuoteSpecifier::Local(self.reconstruct(token)?),
1035 "global" => QuoteSpecifier::Global(self.reconstruct(token)?),
1036 "threadVariable" => QuoteSpecifier::ThreadVariable(self.reconstruct(token)?),
1037 "threadLocal" => QuoteSpecifier::ThreadLocal(self.reconstruct(token)?),
1038 kind => return Err(self.unsupported(kind, token)),
1039 };
1040 let quoted = self.required_field(node, "token")?;
1041 Ok(
1042 QuoteExpression::new(specifier, Symbol::new(self.text(quoted), self.span(quoted)))
1043 .into(),
1044 )
1045 }
1046
1047 fn debug_clause(&self, node: tree_sitter::Node<'_>) -> Result<Expr, ParseError> {
1048 let keyword = self.required_field(node, "keyword")?;
1049 let value = self
1050 .first_expression_child(node)
1051 .map(|child| self.expr(child))
1052 .transpose()?;
1053 Ok(match keyword.kind() {
1054 "elapsedTime" => ProfilingExpr::new(
1055 ProfilingModifier::ElapsedTime(self.reconstruct(keyword)?),
1056 value.ok_or_else(|| self.unsupported("profiling operand", node))?,
1057 )
1058 .into(),
1059 "elapsedTiming" => ProfilingExpr::new(
1060 ProfilingModifier::ElapsedTiming(self.reconstruct(keyword)?),
1061 value.ok_or_else(|| self.unsupported("profiling operand", node))?,
1062 )
1063 .into(),
1064 "profile" => ProfilingExpr::new(
1065 ProfilingModifier::Profile(self.reconstruct(keyword)?),
1066 value.ok_or_else(|| self.unsupported("profiling operand", node))?,
1067 )
1068 .into(),
1069 "time" => ProfilingExpr::new(
1070 ProfilingModifier::Time(self.reconstruct(keyword)?),
1071 value.ok_or_else(|| self.unsupported("profiling operand", node))?,
1072 )
1073 .into(),
1074 "timing" => ProfilingExpr::new(
1075 ProfilingModifier::Timing(self.reconstruct(keyword)?),
1076 value.ok_or_else(|| self.unsupported("profiling operand", node))?,
1077 )
1078 .into(),
1079 "TEST" => DebugExpr::new(DebugKeyword::Test(self.reconstruct(keyword)?), value).into(),
1080 "step" => DebugExpr::new(DebugKeyword::Step(self.reconstruct(keyword)?), value).into(),
1081 "finish" => {
1082 DebugExpr::new(DebugKeyword::Finish(self.reconstruct(keyword)?), value).into()
1083 }
1084 "shield" => {
1085 DebugExpr::new(DebugKeyword::Shield(self.reconstruct(keyword)?), value).into()
1086 }
1087 "breakpoint" => {
1088 DebugExpr::new(DebugKeyword::Breakpoint(self.reconstruct(keyword)?), value).into()
1089 }
1090 kind => return Err(self.unsupported(kind, keyword)),
1091 })
1092 }
1093
1094 fn reconstruct<T>(&self, node: tree_sitter::Node<'_>) -> Result<T, ParseError>
1095 where
1096 for<'tree> T: Reconstruct<TreeSitterNode<'tree, 'source>>,
1097 {
1098 T::reconstruct(TreeSitterNode::with_span(
1099 node,
1100 self.source,
1101 self.span(node),
1102 ))
1103 .map_err(Into::into)
1104 }
1105
1106 fn delimiter_spans(&self, node: tree_sitter::Node<'_>) -> Result<DoubleSpan, ParseError> {
1107 let kind = match node.kind() {
1108 "parenthesized_expression" | "sequence" => DelimiterKind::Parenthesis,
1109 "array" => DelimiterKind::Bracket,
1110 "list" => DelimiterKind::Brace,
1111 "angle_bar_list" => DelimiterKind::AngleBar,
1112 other => return Err(self.unsupported(other, node)),
1113 };
1114 let opening = self.span(self.required_kind(node, kind.opening())?);
1115 let closing = self.required_kind(node, kind.closing())?;
1116 let closing = if closing.start_byte() >= self.source.len() {
1117 Span::from_offset(self.source.len())
1118 } else {
1119 self.span(closing)
1120 };
1121 Ok(DoubleSpan::new(opening, closing))
1122 }
1123
1124 fn children<'tree>(&self, node: tree_sitter::Node<'tree>) -> Vec<tree_sitter::Node<'tree>> {
1125 (0..node.child_count())
1126 .filter_map(|index| node.child(u32::try_from(index).expect("child count fits u32")))
1127 .collect()
1128 }
1129
1130 fn semantic_children<'tree>(
1131 &self,
1132 node: tree_sitter::Node<'tree>,
1133 ) -> Vec<tree_sitter::Node<'tree>> {
1134 self.children(node)
1135 .into_iter()
1136 .filter(|child| child.is_named() && !child.is_extra())
1137 .collect()
1138 }
1139
1140 fn only_semantic_child<'tree>(
1141 &self,
1142 node: tree_sitter::Node<'tree>,
1143 ) -> Result<tree_sitter::Node<'tree>, ParseError> {
1144 let children = self.semantic_children(node);
1145 match children.as_slice() {
1146 [child] => Ok(*child),
1147 _ => Err(self.unsupported("cell contents", node)),
1148 }
1149 }
1150
1151 fn first_expression_child<'tree>(
1152 &self,
1153 node: tree_sitter::Node<'tree>,
1154 ) -> Option<tree_sitter::Node<'tree>> {
1155 self.semantic_children(node).into_iter().find(|child| {
1156 !matches!(
1157 child.kind(),
1158 "then_clause" | "else_clause" | "except_clause" | "iteration_range" | "loop_body"
1159 )
1160 })
1161 }
1162
1163 fn required_expression_child<'tree>(
1164 &self,
1165 node: tree_sitter::Node<'tree>,
1166 ) -> Result<tree_sitter::Node<'tree>, ParseError> {
1167 self.first_expression_child(node)
1168 .ok_or_else(|| self.unsupported("expression child", node))
1169 }
1170
1171 fn child_by_field<'tree>(
1172 &self,
1173 node: tree_sitter::Node<'tree>,
1174 field: &str,
1175 ) -> Option<tree_sitter::Node<'tree>> {
1176 node.child_by_field_name(field)
1177 }
1178
1179 fn required_field<'tree>(
1180 &self,
1181 node: tree_sitter::Node<'tree>,
1182 field: &str,
1183 ) -> Result<tree_sitter::Node<'tree>, ParseError> {
1184 self.child_by_field(node, field)
1185 .ok_or_else(|| self.unsupported(field, node))
1186 }
1187
1188 fn optional_kind<'tree>(
1189 &self,
1190 node: tree_sitter::Node<'tree>,
1191 kind: &str,
1192 ) -> Option<tree_sitter::Node<'tree>> {
1193 self.children(node)
1194 .into_iter()
1195 .find(|child| !child.is_extra() && child.kind() == kind)
1196 }
1197
1198 fn required_kind<'tree>(
1199 &self,
1200 node: tree_sitter::Node<'tree>,
1201 kind: &str,
1202 ) -> Result<tree_sitter::Node<'tree>, ParseError> {
1203 self.optional_kind(node, kind)
1204 .ok_or_else(|| self.unsupported(kind, node))
1205 }
1206
1207 fn text(&self, node: tree_sitter::Node<'_>) -> Cow<'_, str> {
1208 let range = self
1209 .span(node)
1210 .bounds()
1211 .map_or_else(|| node.byte_range(), |(start, end)| start..end);
1212 String::from_utf8_lossy(&self.source[range])
1213 }
1214
1215 fn span(&self, node: tree_sitter::Node<'_>) -> Span {
1216 let range = node.byte_range();
1217 self.aliases
1218 .iter()
1219 .find(|alias| alias.bare == range)
1220 .map_or_else(
1221 || {
1222 self.source_span.subspan(
1223 node.start_byte().min(self.source.len()),
1224 node.end_byte().min(self.source.len()),
1225 )
1226 },
1227 |alias| self.source_span.subspan(alias.full.start, alias.full.end),
1228 )
1229 }
1230
1231 fn unsupported(&self, kind: impl Into<String>, node: tree_sitter::Node<'_>) -> ParseError {
1232 self.unsupported_span(kind, self.span(node))
1233 }
1234
1235 fn unsupported_span(&self, kind: impl Into<String>, span: Span) -> ParseError {
1236 ParseError::UnsupportedNode {
1237 kind: kind.into(),
1238 span,
1239 }
1240 }
1241}
1242
1243#[derive(Clone)]
1244struct CoreAlias {
1245 full: Range<usize>,
1246 bare: Range<usize>,
1247}
1248
1249fn renamed_source(source: &str) -> Result<(Cow<'_, str>, Vec<CoreAlias>), LexError> {
1250 let tokens = lex_str(source)?;
1251 let mut aliases = Vec::new();
1252 collect_core_aliases(&tokens, &mut aliases);
1253 if aliases.is_empty() {
1254 return Ok((Cow::Borrowed(source), aliases));
1255 }
1256
1257 let mut renamed = source.as_bytes().to_vec();
1258 for alias in &aliases {
1259 renamed[alias.full.start..alias.bare.start].fill(b' ');
1260 }
1261 Ok((
1262 Cow::Owned(String::from_utf8(renamed).expect("replacing ASCII bytes preserves UTF-8")),
1263 aliases,
1264 ))
1265}
1266
1267type RecoveredSource<'source> = (Cow<'source, str>, Vec<CoreAlias>, Vec<LexError>);
1268
1269fn renamed_source_recovering(source: &str) -> Result<RecoveredSource<'_>, LexError> {
1270 let recovered = lex_str_recovering(source)?;
1271 let (tokens, diagnostics) = recovered.into_parts();
1272 let mut aliases = Vec::new();
1273 collect_core_aliases(&tokens, &mut aliases);
1274 let mut missing = Vec::new();
1275 collect_missing_closers(&tokens, &mut missing);
1276
1277 if aliases.is_empty() && missing.is_empty() {
1278 return Ok((Cow::Borrowed(source), aliases, diagnostics));
1279 }
1280
1281 let mut renamed = source.as_bytes().to_vec();
1282 for alias in &aliases {
1283 renamed[alias.full.start..alias.bare.start].fill(b' ');
1284 }
1285 for kind in missing {
1286 renamed.extend_from_slice(kind.closing().as_bytes());
1287 }
1288 Ok((
1289 Cow::Owned(String::from_utf8(renamed).expect("ASCII recovery preserves UTF-8")),
1290 aliases,
1291 diagnostics,
1292 ))
1293}
1294
1295fn collect_missing_closers(tokens: &TokenStream, missing: &mut Vec<DelimiterKind>) {
1296 for token in tokens.iter() {
1297 let TokenTree::Group(group) = token else {
1298 continue;
1299 };
1300 collect_missing_closers(group.stream(), missing);
1301 if !group.delimiter().is_closed() {
1302 missing.push(group.delim_kind());
1303 }
1304 }
1305}
1306
1307fn collect_core_aliases(tokens: &TokenStream, aliases: &mut Vec<CoreAlias>) {
1308 for token in tokens.iter() {
1309 match token {
1310 TokenTree::Group(group) => collect_core_aliases(group.stream(), aliases),
1311 TokenTree::Ident(identifier) => {
1312 let spelling = identifier.text();
1313 let bare = crate::lexer::canonical_word_spelling(spelling);
1314 if bare == spelling {
1315 continue;
1316 }
1317 let Some((start, end)) = identifier.span().bounds() else {
1318 continue;
1319 };
1320 aliases.push(CoreAlias {
1321 full: start..end,
1322 bare: end - bare.len()..end,
1323 });
1324 }
1325 TokenTree::Eoc(_)
1326 | TokenTree::Literal(_)
1327 | TokenTree::Punct(_)
1328 | TokenTree::Trivia(_) => {}
1329 }
1330 }
1331}
1332
1333#[derive(Clone)]
1334pub struct TreeSitterNode<'tree, 'source> {
1336 node: tree_sitter::Node<'tree>,
1337 source: &'source [u8],
1338 span: Option<Span>,
1339}
1340
1341impl<'tree, 'source> TreeSitterNode<'tree, 'source> {
1342 pub fn new(node: tree_sitter::Node<'tree>, source: &'source [u8]) -> Self {
1344 Self {
1345 node,
1346 source,
1347 span: None,
1348 }
1349 }
1350
1351 fn with_span(node: tree_sitter::Node<'tree>, source: &'source [u8], span: Span) -> Self {
1352 Self {
1353 node,
1354 source,
1355 span: Some(span),
1356 }
1357 }
1358}
1359
1360impl ExternalCstNode for TreeSitterNode<'_, '_> {
1361 type Children<'syntax>
1362 = IntoIter<ExternalCstChild<Self>>
1363 where
1364 Self: 'syntax;
1365
1366 fn identity(&self) -> CSTNodeClassLabel<'_> {
1367 CSTNodeClassLabel::new(self.node.kind(), self.node.is_named())
1368 }
1369
1370 fn children(&self) -> Self::Children<'_> {
1371 let parent = self.node;
1372 (0..parent.child_count())
1373 .filter_map(|index| {
1374 let index = u32::try_from(index).expect("Tree-sitter child count fits u32");
1375 parent.child(index).map(|node| ExternalCstChild {
1376 field: parent.field_name_for_child(index),
1377 node: Self::new(node, self.source),
1378 })
1379 })
1380 .collect::<Vec<_>>()
1381 .into_iter()
1382 }
1383
1384 fn text(&self) -> Cow<'_, str> {
1385 let range = self
1386 .span
1387 .as_ref()
1388 .and_then(Span::bounds)
1389 .map_or_else(|| self.node.byte_range(), |(start, end)| start..end);
1390 String::from_utf8_lossy(&self.source[range])
1391 }
1392
1393 fn is_extra(&self) -> bool {
1394 self.node.is_extra()
1395 }
1396}
1397
1398impl Spanned for TreeSitterNode<'_, '_> {
1399 fn span(&self) -> Span {
1400 self.span
1401 .clone()
1402 .unwrap_or_else(|| Span::new(self.node.start_byte(), self.node.end_byte()))
1403 }
1404}