regast_syntax/print/
dot.rs1use 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}