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() {}