regast-syntax 0.1.0

Lossless syntax tree for the regast regular expression engine
Documentation
use std::{convert::Infallible, fmt::Write};

use super::kind_name;
use crate::{Cursor, Flow, Pattern, Visitor, visit};

impl Pattern {
    #[must_use]
    pub fn to_dot(&self) -> String {
        match visit(self, Dot::default()) {
            Ok(output) => output,
            Err(error) => match error {},
        }
    }
}

struct Dot {
    output: String,
}

impl Default for Dot {
    fn default() -> Self {
        Self {
            output: String::from("digraph ast {\n  node [shape=box];\n"),
        }
    }
}

impl Visitor for Dot {
    type Output = String;
    type Err = Infallible;

    fn enter(&mut self, node: Cursor<'_>) -> Result<Flow, Self::Err> {
        let label = format!("{}\\n{}", kind_name(node.kind()), escape_dot(node.text()));
        writeln!(self.output, "  n{} [label=\"{}\"];", node.id().0, label)
            .expect("writing to String cannot fail");
        for child in node.children() {
            writeln!(self.output, "  n{} -> n{};", node.id().0, child.id().0)
                .expect("writing to String cannot fail");
        }
        Ok(Flow::Continue)
    }

    fn finish(mut self) -> Result<Self::Output, Self::Err> {
        self.output.push_str("}\n");
        Ok(self.output)
    }
}

fn escape_dot(text: &str) -> String {
    text.replace('\\', "\\\\")
        .replace('"', "\\\"")
        .replace('\n', "\\n")
}