Skip to main content

regast_syntax/print/
dot.rs

1use std::{convert::Infallible, fmt::Write};
2
3use super::kind_name;
4use crate::{Cursor, Flow, Pattern, Visitor, visit};
5
6impl Pattern {
7    #[must_use]
8    pub fn to_dot(&self) -> String {
9        match visit(self, Dot::default()) {
10            Ok(output) => output,
11            Err(error) => match error {},
12        }
13    }
14}
15
16struct Dot {
17    output: String,
18}
19
20impl Default for Dot {
21    fn default() -> Self {
22        Self {
23            output: String::from("digraph ast {\n  node [shape=box];\n"),
24        }
25    }
26}
27
28impl Visitor for Dot {
29    type Output = String;
30    type Err = Infallible;
31
32    fn enter(&mut self, node: Cursor<'_>) -> Result<Flow, Self::Err> {
33        let label = format!("{}\\n{}", kind_name(node.kind()), escape_dot(node.text()));
34        writeln!(self.output, "  n{} [label=\"{}\"];", node.id().0, label)
35            .expect("writing to String cannot fail");
36        for child in node.children() {
37            writeln!(self.output, "  n{} -> n{};", node.id().0, child.id().0)
38                .expect("writing to String cannot fail");
39        }
40        Ok(Flow::Continue)
41    }
42
43    fn finish(mut self) -> Result<Self::Output, Self::Err> {
44        self.output.push_str("}\n");
45        Ok(self.output)
46    }
47}
48
49fn escape_dot(text: &str) -> String {
50    text.replace('\\', "\\\\")
51        .replace('"', "\\\"")
52        .replace('\n', "\\n")
53}