gonum.org/v1/gonum@v0.14.0/graph/formats/dot/ast/ast.go (about) 1 // This file is dual licensed under CC0 and The Gonum License. 2 // 3 // Copyright ©2017 The Gonum Authors. All rights reserved. 4 // Use of this source code is governed by a BSD-style 5 // license that can be found in the LICENSE file. 6 // 7 // Copyright ©2017 Robin Eklind. 8 // This file is made available under a Creative Commons CC0 1.0 9 // Universal Public Domain Dedication. 10 11 package ast 12 13 import ( 14 "bytes" 15 "fmt" 16 ) 17 18 // === [ File ] ================================================================ 19 20 // A File represents a DOT file. 21 // 22 // Examples. 23 // 24 // digraph G { 25 // A -> B 26 // } 27 // graph H { 28 // C - D 29 // } 30 type File struct { 31 // Graphs. 32 Graphs []*Graph 33 } 34 35 // String returns the string representation of the file. 36 func (f *File) String() string { 37 buf := new(bytes.Buffer) 38 for i, graph := range f.Graphs { 39 if i != 0 { 40 buf.WriteString("\n") 41 } 42 buf.WriteString(graph.String()) 43 } 44 return buf.String() 45 } 46 47 // === [ Graphs ] ============================================================== 48 49 // A Graph represents a directed or an undirected graph. 50 // 51 // Examples. 52 // 53 // digraph G { 54 // A -> {B C} 55 // B -> C 56 // } 57 type Graph struct { 58 // Strict graph; multi-edges forbidden. 59 Strict bool 60 // Directed graph. 61 Directed bool 62 // Graph ID; or empty if anonymous. 63 ID string 64 // Graph statements. 65 Stmts []Stmt 66 } 67 68 // String returns the string representation of the graph. 69 func (g *Graph) String() string { 70 buf := new(bytes.Buffer) 71 if g.Strict { 72 buf.WriteString("strict ") 73 } 74 if g.Directed { 75 buf.WriteString("digraph ") 76 } else { 77 buf.WriteString("graph ") 78 } 79 if len(g.ID) > 0 { 80 fmt.Fprintf(buf, "%s ", g.ID) 81 } 82 buf.WriteString("{\n") 83 for _, stmt := range g.Stmts { 84 fmt.Fprintf(buf, "\t%s\n", stmt) 85 } 86 buf.WriteString("}") 87 return buf.String() 88 } 89 90 // === [ Statements ] ========================================================== 91 92 // A Stmt represents a statement, and has one of the following underlying types. 93 // 94 // *NodeStmt 95 // *EdgeStmt 96 // *AttrStmt 97 // *Attr 98 // *Subgraph 99 type Stmt interface { 100 fmt.Stringer 101 // isStmt ensures that only statements can be assigned to the Stmt interface. 102 isStmt() 103 } 104 105 // --- [ Node statement ] ------------------------------------------------------ 106 107 // A NodeStmt represents a node statement. 108 // 109 // Examples. 110 // 111 // A [color=blue] 112 type NodeStmt struct { 113 // Node. 114 Node *Node 115 // Node attributes. 116 Attrs []*Attr 117 } 118 119 // String returns the string representation of the node statement. 120 func (e *NodeStmt) String() string { 121 buf := new(bytes.Buffer) 122 buf.WriteString(e.Node.String()) 123 if len(e.Attrs) > 0 { 124 buf.WriteString(" [") 125 for i, attr := range e.Attrs { 126 if i != 0 { 127 buf.WriteString(" ") 128 } 129 buf.WriteString(attr.String()) 130 } 131 buf.WriteString("]") 132 } 133 return buf.String() 134 } 135 136 // --- [ Edge statement ] ------------------------------------------------------ 137 138 // An EdgeStmt represents an edge statement. 139 // 140 // Examples. 141 // 142 // A -> B 143 // A -> {B C} 144 // A -> B -> C 145 type EdgeStmt struct { 146 // Source vertex. 147 From Vertex 148 // Outgoing edge. 149 To *Edge 150 // Edge attributes. 151 Attrs []*Attr 152 } 153 154 // String returns the string representation of the edge statement. 155 func (e *EdgeStmt) String() string { 156 buf := new(bytes.Buffer) 157 fmt.Fprintf(buf, "%s %s", e.From, e.To) 158 if len(e.Attrs) > 0 { 159 buf.WriteString(" [") 160 for i, attr := range e.Attrs { 161 if i != 0 { 162 buf.WriteString(" ") 163 } 164 buf.WriteString(attr.String()) 165 } 166 buf.WriteString("]") 167 } 168 return buf.String() 169 } 170 171 // An Edge represents an edge between two vertices. 172 type Edge struct { 173 // Directed edge. 174 Directed bool 175 // Destination vertex. 176 Vertex Vertex 177 // Outgoing edge; or nil if none. 178 To *Edge 179 } 180 181 // String returns the string representation of the edge. 182 func (e *Edge) String() string { 183 op := "--" 184 if e.Directed { 185 op = "->" 186 } 187 if e.To != nil { 188 return fmt.Sprintf("%s %s %s", op, e.Vertex, e.To) 189 } 190 return fmt.Sprintf("%s %s", op, e.Vertex) 191 } 192 193 // --- [ Attribute statement ] ------------------------------------------------- 194 195 // An AttrStmt represents an attribute statement. 196 // 197 // Examples. 198 // 199 // graph [rankdir=LR] 200 // node [color=blue fillcolor=red] 201 // edge [minlen=1] 202 type AttrStmt struct { 203 // Graph component kind to which the attributes are assigned. 204 Kind Kind 205 // Attributes. 206 Attrs []*Attr 207 } 208 209 // String returns the string representation of the attribute statement. 210 func (a *AttrStmt) String() string { 211 buf := new(bytes.Buffer) 212 fmt.Fprintf(buf, "%s [", a.Kind) 213 for i, attr := range a.Attrs { 214 if i != 0 { 215 buf.WriteString(" ") 216 } 217 buf.WriteString(attr.String()) 218 } 219 buf.WriteString("]") 220 return buf.String() 221 } 222 223 // Kind specifies the set of graph components to which attribute statements may 224 // be assigned. 225 type Kind uint 226 227 // Graph component kinds. 228 const ( 229 GraphKind Kind = iota // graph 230 NodeKind // node 231 EdgeKind // edge 232 ) 233 234 // String returns the string representation of the graph component kind. 235 func (k Kind) String() string { 236 switch k { 237 case GraphKind: 238 return "graph" 239 case NodeKind: 240 return "node" 241 case EdgeKind: 242 return "edge" 243 } 244 panic(fmt.Sprintf("invalid graph component kind (%d)", k)) 245 } 246 247 // --- [ Attribute ] ----------------------------------------------------------- 248 249 // An Attr represents an attribute. 250 // 251 // Examples. 252 // 253 // rank=same 254 type Attr struct { 255 // Attribute key. 256 Key string 257 // Attribute value. 258 Val string 259 } 260 261 // String returns the string representation of the attribute. 262 func (a *Attr) String() string { 263 return fmt.Sprintf("%s=%s", a.Key, a.Val) 264 } 265 266 // --- [ Subgraph ] ------------------------------------------------------------ 267 268 // A Subgraph represents a subgraph vertex. 269 // 270 // Examples. 271 // 272 // subgraph S {A B C} 273 type Subgraph struct { 274 // Subgraph ID; or empty if none. 275 ID string 276 // Subgraph statements. 277 Stmts []Stmt 278 } 279 280 // String returns the string representation of the subgraph. 281 func (s *Subgraph) String() string { 282 buf := new(bytes.Buffer) 283 if len(s.ID) > 0 { 284 fmt.Fprintf(buf, "subgraph %s ", s.ID) 285 } 286 buf.WriteString("{") 287 for i, stmt := range s.Stmts { 288 if i != 0 { 289 buf.WriteString(" ") 290 } 291 buf.WriteString(stmt.String()) 292 } 293 buf.WriteString("}") 294 return buf.String() 295 } 296 297 // isStmt ensures that only statements can be assigned to the Stmt interface. 298 func (*NodeStmt) isStmt() {} 299 func (*EdgeStmt) isStmt() {} 300 func (*AttrStmt) isStmt() {} 301 func (*Attr) isStmt() {} 302 func (*Subgraph) isStmt() {} 303 304 // === [ Vertices ] ============================================================ 305 306 // A Vertex represents a vertex, and has one of the following underlying types. 307 // 308 // *Node 309 // *Subgraph 310 type Vertex interface { 311 fmt.Stringer 312 // isVertex ensures that only vertices can be assigned to the Vertex 313 // interface. 314 isVertex() 315 } 316 317 // --- [ Node identifier ] ----------------------------------------------------- 318 319 // A Node represents a node vertex. 320 // 321 // Examples. 322 // 323 // A 324 // A:nw 325 type Node struct { 326 // Node ID. 327 ID string 328 // Node port; or nil if none. 329 Port *Port 330 } 331 332 // String returns the string representation of the node. 333 func (n *Node) String() string { 334 if n.Port != nil { 335 return fmt.Sprintf("%s%s", n.ID, n.Port) 336 } 337 return n.ID 338 } 339 340 // A Port specifies where on a node an edge should be aimed. 341 type Port struct { 342 // Port ID; or empty if none. 343 ID string 344 // Compass point. 345 CompassPoint CompassPoint 346 } 347 348 // String returns the string representation of the port. 349 func (p *Port) String() string { 350 buf := new(bytes.Buffer) 351 if len(p.ID) > 0 { 352 fmt.Fprintf(buf, ":%s", p.ID) 353 } 354 if p.CompassPoint != CompassPointNone { 355 fmt.Fprintf(buf, ":%s", p.CompassPoint) 356 } 357 return buf.String() 358 } 359 360 // CompassPoint specifies the set of compass points. 361 type CompassPoint uint 362 363 // Compass points. 364 const ( 365 CompassPointNone CompassPoint = iota // 366 CompassPointNorth // n 367 CompassPointNorthEast // ne 368 CompassPointEast // e 369 CompassPointSouthEast // se 370 CompassPointSouth // s 371 CompassPointSouthWest // sw 372 CompassPointWest // w 373 CompassPointNorthWest // nw 374 CompassPointCenter // c 375 CompassPointDefault // _ 376 ) 377 378 // String returns the string representation of the compass point. 379 func (c CompassPoint) String() string { 380 switch c { 381 case CompassPointNone: 382 return "" 383 case CompassPointNorth: 384 return "n" 385 case CompassPointNorthEast: 386 return "ne" 387 case CompassPointEast: 388 return "e" 389 case CompassPointSouthEast: 390 return "se" 391 case CompassPointSouth: 392 return "s" 393 case CompassPointSouthWest: 394 return "sw" 395 case CompassPointWest: 396 return "w" 397 case CompassPointNorthWest: 398 return "nw" 399 case CompassPointCenter: 400 return "c" 401 case CompassPointDefault: 402 return "_" 403 } 404 panic(fmt.Sprintf("invalid compass point (%d)", uint(c))) 405 } 406 407 // isVertex ensures that only vertices can be assigned to the Vertex interface. 408 func (*Node) isVertex() {} 409 func (*Subgraph) isVertex() {}