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