///|
pub(all) struct Edge {
from : Int
to : Int
label : String
}
///|
pub(all) struct Node {
id : Int
label : String
}
///|
pub(all) struct Tree {
label : String
children : Array[Tree]
}
///|
pub fn Edge::new(from~ : Int, to~ : Int, label~ : String = "") -> Edge {
{ from, to, label }
}
///|
pub fn Node::new(id~ : Int, label~ : String) -> Node {
{ id, label }
}
///|
pub(all) struct Digraph {
edges : Array[Edge]
nodes : Array[Node]
}
///|
pub impl Show for Digraph with output(self, logger) {
logger.write_string("\ndigraph {\n")
logger.write_string("node [shape = box; style = filled;];\n")
for edge in self.edges {
logger.write_object(edge.from)
logger.write_string("->")
logger.write_object(edge.to)
if not(edge.label.is_blank()) {
logger.write_string("[label=\{edge.label.escape()};]")
}
logger.write_string(";\n")
}
for node in self.nodes {
logger.write_string("\{node.id}[label=\{node.label.escape()};]")
}
logger.write_string("}\n")
}
///|
pub fn Tree::to_digraph(self : Tree) -> Digraph {
let edges = []
let nodes = []
let mut cnt = 0
fn dfs(self : Tree) -> Int {
cnt += 1
let { label, children } = self
match children {
[] => {
nodes.push(Node::new(id=cnt, label~))
cnt
}
_ => {
let from = cnt
for child in children {
let to = dfs(child)
edges.push(Edge::new(from~, to~))
}
nodes.push(Node::new(id=from, label~))
from
}
}
}
dfs(self) |> ignore
Digraph::{ edges, nodes }
}