eure 0.1.9

Eure core library
Documentation
use eure_tree::{prelude::*, tree::LineNumbers};

use crate::tree::{WriteError, get_error_position_from_error};

pub struct InspectVisitor<'f, 't> {
    input: &'t str,
    line_numbers: LineNumbers<'t>,
    indent: usize,
    f: &'f mut dyn std::fmt::Write,
}

impl<'f, 't> InspectVisitor<'f, 't> {
    pub fn new(input: &'t str, f: &'f mut dyn std::fmt::Write) -> Self {
        Self {
            input,
            line_numbers: LineNumbers::new(input),
            f,
            indent: 0,
        }
    }
}

impl<F: CstFacade> CstVisitor<F> for InspectVisitor<'_, '_> {
    type Error = WriteError;
    fn then_construct_error(
        &mut self,
        node_data: Option<CstNode>,
        parent: CstNodeId,
        kind: NodeKind,
        error: CstConstructError,
        tree: &F,
    ) -> Result<(), Self::Error> {
        if let Some((line, column)) =
            get_error_position_from_error(&self.line_numbers, &node_data, &error)
        {
            eprintln!("Syntax error at line {line}, column {column}: {error}");
        } else {
            eprintln!("Syntax error: {error}");
        }
        self.recover_error(node_data, parent, kind, tree)
    }
    fn visit_terminal(
        &mut self,
        _id: CstNodeId,
        kind: TerminalKind,
        data: TerminalData,
        tree: &F,
    ) -> Result<(), Self::Error> {
        match data {
            TerminalData::Input(input_span) => writeln!(
                self.f,
                "{}{} ({:?})",
                " ".repeat(self.indent),
                &self.input[input_span.start as usize..input_span.end as usize]
                    .replace("\n", "\\n")
                    .replace("\t", "\\t")
                    .replace(" ", "_"),
                kind,
            )?,
            TerminalData::Dynamic(token_id) => writeln!(
                self.f,
                "{}{:?} ({:?})",
                " ".repeat(self.indent),
                tree.dynamic_token(token_id)
                    .ok_or(WriteError::DynamicTokenNotFound { id: token_id })?,
                kind
            )?,
        }
        Ok(())
    }
    fn visit_non_terminal(
        &mut self,
        _id: CstNodeId,
        kind: NonTerminalKind,
        _data: NonTerminalData,
        _tree: &F,
    ) -> Result<(), Self::Error> {
        writeln!(self.f, "{}{:?}", " ".repeat(self.indent), kind)?;
        self.indent += 2;
        Ok(())
    }
    fn visit_non_terminal_close(
        &mut self,
        _id: CstNodeId,
        _kind: NonTerminalKind,
        _data: NonTerminalData,
        _tree: &F,
    ) -> Result<(), Self::Error> {
        self.indent -= 2;
        Ok(())
    }
}