package main import ( "bufio" "fmt" "os" "strconv" "strings" ) type Node struct { Name string Children []*Node } func ParseTree(s string) *Node { // Split string into name and children parts var name string var childrenStr string if idx := strings.Index(s, "<"); idx >= 0 { if idx+1 < len(s)-1 { name = strings.TrimSpace(s[:idx]) childrenStr = s[idx+1 : len(s)-1] } else { name = strings.TrimSpace(s[:len(s)-2]) } } else { name = strings.TrimSpace(s) } // Create new node node := &Node{Name: name} // Parse children if childrenStr != "" { b := 0 last_child := 0 for i, symb := range childrenStr { if symb == '<' { b += 1 } else if symb == '>' { b -= 1 if b == 0 { childNode := ParseTree(childrenStr[last_child : i+1]) node.Children = append(node.Children, childNode) last_child = i + 2 } } else if symb == ',' && b == 0 { if last_child < i { childNode := ParseTree(childrenStr[last_child:i]) node.Children = append(node.Children, childNode) last_child = i + 1 } } } if last_child < len(childrenStr) { childNode := ParseTree(childrenStr[last_child:]) node.Children = append(node.Children, childNode) } } return node } func ToGraphviz(node *Node) string { var sb strings.Builder sb.WriteString("digraph {\n") // Recursive function to add nodes and edges to string builder var traverse func(n *Node) traverse = func(n *Node) { // Add node to Graphviz string sb.WriteString(fmt.Sprintf(" \"%p\" [label=%s];\n", n, strconv.Quote(n.Name))) // Traverse children and add edges for _, child := range n.Children { sb.WriteString(fmt.Sprintf(" \"%p\" -> \"%p\";\n", n, child)) traverse(child) } } traverse(node) sb.WriteString("}") return sb.String() } func main() { // Read all data from stdin scanner := bufio.NewScanner(os.Stdin) var typeStr string for scanner.Scan() { typeStr += scanner.Text() + "\n" } // Apply the formatter function to the input string root := ParseTree(typeStr) graph := ToGraphviz(root) // Print the result fmt.Println(graph) }