Skip to main content

m2_syn/migration/
treesitter.rs

1//! Tree-sitter parser adapter.
2//!
3//! Tree-sitter nodes remain backend-local. Complete-file parsing lowers the
4//! grammar's concrete nodes directly into the generated typed graph; it never
5//! reparses their source through the native precedence engine.
6//! [`TreeSitterNode`] is also the generic [`ExternalCstNode`] adapter used for
7//! migrating leaves, operators, and tokens with the generated machinery.
8
9use 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)]
27/// A failure while parsing or migrating a Tree-sitter syntax tree.
28pub enum ParseError {
29    /// The renaming hook could not inspect the source token stream.
30    Lex(LexError),
31    /// The raw token stream could not be partitioned into complete cells.
32    Tokenize(CellStreamError),
33    /// The bundled grammar could not be installed in the parser.
34    Language(tree_sitter::LanguageError),
35    /// Tree-sitter returned no tree.
36    Cancelled,
37    /// A requested source edit did not lie on valid boundaries of the buffer.
38    InvalidEdit,
39    /// Tree-sitter produced an error or missing node at this span.
40    InvalidSyntax(Span),
41    /// The untyped Tree-sitter node could not migrate typed syntax.
42    Migrate(MigrateError),
43    /// A valid concrete node has no representation in the typed schema.
44    UnsupportedNode {
45        /// The Tree-sitter node kind that could not be lowered.
46        kind: String,
47        /// The complete node range.
48        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
108/// A reusable Tree-sitter parser and direct typed-CST lowerer.
109pub struct TreeSitterParser {
110    /// The parser.
111    parser: tree_sitter::Parser,
112}
113
114/// An incrementally updated Tree-sitter parse for editor-style source changes.
115///
116/// The parser retains its previous Tree-sitter tree, applies each [`TextEdit`]
117/// to that tree, and supplies it to the next parse. Typed syntax is lowered
118/// afresh from the incrementally produced tree, so every public node and span
119/// describes the current source snapshot. Missing group closers are recoverable
120/// and remain available through [`Self::diagnostics`].
121pub struct RealtimeParser {
122    /// The parser.
123    parser: tree_sitter::Parser,
124    /// The source.
125    source: Arc<Source>,
126    /// The parse view.
127    parse_view: String,
128    /// The tree.
129    tree: tree_sitter::Tree,
130    /// The syntax.
131    syntax: SourceFile,
132    /// The diagnostics.
133    diagnostics: Vec<LexError>,
134    /// The changed ranges.
135    changed_ranges: Vec<Span>,
136}
137
138impl RealtimeParser {
139    /// Creates a retained parse of the initial source snapshot.
140    ///
141    /// # Errors
142    ///
143    /// Returns [`ParseError`] when the grammar cannot parse and lower the
144    /// source, apart from recoverable missing group and string-literal closers.
145    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    /// Applies one source edit and incrementally refreshes the typed syntax.
166    ///
167    /// The update is transactional: a failed edit or parse leaves the previous
168    /// source, tree, syntax, and diagnostics unchanged.
169    ///
170    /// # Errors
171    ///
172    /// Returns [`ParseError::InvalidEdit`] when the edit is outside the current
173    /// UTF-8 buffer, or another [`ParseError`] when the edited source cannot be
174    /// recovered and lowered.
175    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    /// Returns the current source snapshot.
219    pub fn source(&self) -> &str {
220        self.source.text()
221    }
222
223    /// Returns the typed syntax for the current snapshot.
224    pub fn syntax(&self) -> &SourceFile {
225        &self.syntax
226    }
227
228    /// Returns the recoverable diagnostics for the current snapshot.
229    pub fn diagnostics(&self) -> &[LexError] {
230        &self.diagnostics
231    }
232
233    /// Returns structural ranges changed by the most recent incremental parse.
234    pub fn changed_ranges(&self) -> &[Span] {
235        &self.changed_ranges
236    }
237
238    /// Consumes the retained parser and returns its current typed syntax.
239    pub fn into_syntax(self) -> SourceFile {
240        self.syntax
241    }
242}
243
244/// Internal state for ParsedTree.
245struct ParsedTree {
246    /// The parse view.
247    parse_view: String,
248    /// The tree.
249    tree: tree_sitter::Tree,
250    /// The syntax.
251    syntax: SourceFile,
252    /// The diagnostics.
253    diagnostics: Vec<LexError>,
254}
255
256/// Parses recovered tree.
257fn 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
284/// Handles input edit between.
285fn 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
321/// Handles point at.
322fn 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    /// Creates a parser loaded with the bundled Macaulay2 grammar.
335    ///
336    /// # Errors
337    ///
338    /// Returns [`ParseError::Language`] if Tree-sitter rejects the bundled
339    /// language definition.
340    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    /// Parses source in.
349    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    /// Parses incomplete source while retaining syntax inside unclosed groups.
366    ///
367    /// The parsing view is completed only for Tree-sitter; migrated nodes
368    /// retain the original source spans and zero-width missing closers.
369    ///
370    /// # Errors
371    ///
372    /// Returns [`ParseError`] when source has a non-recoverable lexical or
373    /// grammatical failure, parsing is cancelled, or lowering fails.
374    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
408/// Parses source with Tree-sitter and lowers its CST into the typed syntax tree.
409///
410/// # Errors
411///
412/// Returns [`ParseError`] when parsing or typed migration fails.
413pub 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
419/// Parses incomplete source while retaining unclosed groups and string literals.
420///
421/// # Errors
422///
423/// Returns [`ParseError`] for failures other than missing group or
424/// string-literal closers, or when the recovered Tree-sitter CST cannot be
425/// lowered.
426pub fn parse_file_recovering(source: &str) -> Result<Recovered<SourceFile, LexError>, ParseError> {
427    TreeSitterParser::new()?.parse_recovering(source)
428}
429
430/// Parses an emitted M2 token stream into the complete typed source file.
431///
432/// # Errors
433///
434/// Returns [`ParseError`] when the emitted source is invalid or migration
435/// fails.
436pub fn parse_tokens(tokens: &TokenStream) -> Result<SourceFile, ParseError> {
437    let cells = tokens.to_cell_stream()?;
438    TreeSitterParser::new()?.parse_cells(cells)
439}
440
441/// Handles first error.
442fn 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
455/// Internal state for Lowerer.
456struct Lowerer<'source> {
457    /// The source.
458    source: &'source [u8],
459    /// The source span.
460    source_span: Span,
461    /// The aliases.
462    aliases: Vec<CoreAlias>,
463}
464
465/// Internal alternatives for IterationDomain.
466enum IterationDomain {
467    /// The Range alternative.
468    Range(Option<RangeBoundFrom>, Option<RangeBoundTo>),
469    /// The In alternative.
470    In(Token![in], Box<Expr>),
471}
472
473impl<'source> Lowerer<'source> {
474    /// Creates a new value.
475    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    /// Handles source file.
484    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    /// Spans the layout between the physical start and the first significant
506    /// byte, which the beginning-of-file marker owns.
507    fn leading_span(&self) -> Span {
508        let source = self.source_span.source();
509        Span::ranged(Arc::clone(source), source.leading_whitespace())
510    }
511
512    /// Spans the layout between the last significant byte and the physical end.
513    ///
514    /// The end-of-file marker owns this region so that input no cell covers is
515    /// still reconstructed from the typed graph.
516    fn trailing_span(&self) -> Span {
517        let source = self.source_span.source();
518        Span::ranged(Arc::clone(source), source.trailing_whitespace())
519    }
520
521    /// Handles cell.
522    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    /// Handles end-of-cell offset.
546    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    /// Handles expr pack.
556    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    /// Handles packed content.
601    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    /// Handles expr.
621    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    /// Handles collection.
703    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    /// Handles statement.
759    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    /// Handles string literal.
767    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    /// Handles raw string literal.
786    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    /// Handles binary expr.
802    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    /// Handles prefix expr.
850    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    /// Handles postfix expr.
858    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    /// Handles lambda expression.
866    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    /// Handles assignment.
887    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    /// Handles then clause.
955    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    /// Handles else clause.
963    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    /// Handles if statement.
971    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    /// Handles loop body.
984    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    /// Handles for loop.
1007    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    /// Handles iteration domain.
1051    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    /// Handles while loop.
1080    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    /// Handles new statement.
1089    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    /// Handles new statement element.
1139    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    /// Attempts to statement.
1157    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    /// Handles except do.
1188    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    /// Handles quote expression.
1198    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    /// Handles debug clause.
1237    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    /// Handles migrate.
1289    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    /// Handles delimiter spans.
1302    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    /// Handles children.
1320    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    /// Handles semantic children.
1327    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    /// Handles only semantic child.
1338    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    /// Handles first expression child.
1350    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    /// Handles required expression child.
1363    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    /// Handles child by field.
1372    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    /// Handles required field.
1381    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    /// Handles optional kind.
1391    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    /// Handles required kind.
1402    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    /// Returns the source text.
1412    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    /// Returns the source span.
1421    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    /// Handles unsupported.
1438    fn unsupported(&self, kind: impl Into<String>, node: tree_sitter::Node<'_>) -> ParseError {
1439        self.unsupported_span(kind, self.span(node))
1440    }
1441
1442    /// Handles unsupported span.
1443    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)]
1452/// Internal state for CoreAlias.
1453struct CoreAlias {
1454    /// The full.
1455    full: Range<usize>,
1456    /// The bare.
1457    bare: Range<usize>,
1458}
1459
1460/// Handles renamed source.
1461fn 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
1479/// Internal alias for RecoveredSource.
1480type RecoveredSource<'source> = (Cow<'source, str>, Vec<CoreAlias>, Vec<LexError>);
1481
1482/// Handles renamed source recovering.
1483fn 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    // A line comment runs to the end of its line, so appended closers must
1507    // start on a new one to remain syntax.
1508    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
1524/// Reports whether the source ends inside a line comment.
1525fn 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
1534/// Collects missing closers.
1535fn 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
1547/// Collects core aliases.
1548fn 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)]
1572/// A borrowed Tree-sitter node paired with the source bytes it spans.
1573pub struct TreeSitterNode<'tree, 'source> {
1574    /// The node.
1575    node: tree_sitter::Node<'tree>,
1576    /// The source.
1577    source: &'source [u8],
1578    /// The span.
1579    span: Option<Span>,
1580}
1581
1582impl<'tree, 'source> TreeSitterNode<'tree, 'source> {
1583    /// Creates an external migration node.
1584    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    /// Handles with span.
1593    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}