analyse.go 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. //Copyright 2013 GoGraphviz Authors
  2. //
  3. //Licensed under the Apache License, Version 2.0 (the "License");
  4. //you may not use this file except in compliance with the License.
  5. //You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. //Unless required by applicable law or agreed to in writing, software
  10. //distributed under the License is distributed on an "AS IS" BASIS,
  11. //WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. //See the License for the specific language governing permissions and
  13. //limitations under the License.
  14. package gographviz
  15. import (
  16. "github.com/awalterschulze/gographviz/ast"
  17. )
  18. // NewAnalysedGraph creates a Graph structure by analysing an Abstract Syntax Tree representing a parsed graph.
  19. func NewAnalysedGraph(graph *ast.Graph) (*Graph, error) {
  20. g := NewGraph()
  21. if err := Analyse(graph, g); err != nil {
  22. return nil, err
  23. }
  24. return g, nil
  25. }
  26. // Analyse analyses an Abstract Syntax Tree representing a parsed graph into a newly created graph structure Interface.
  27. func Analyse(graph *ast.Graph, g Interface) error {
  28. gerr := newErrCatcher(g)
  29. graph.Walk(&graphVisitor{gerr})
  30. return gerr.getError()
  31. }
  32. type nilVisitor struct {
  33. }
  34. func (w *nilVisitor) Visit(v ast.Elem) ast.Visitor {
  35. return w
  36. }
  37. type graphVisitor struct {
  38. g errInterface
  39. }
  40. func (w *graphVisitor) Visit(v ast.Elem) ast.Visitor {
  41. graph, ok := v.(*ast.Graph)
  42. if !ok {
  43. return w
  44. }
  45. w.g.SetStrict(graph.Strict)
  46. w.g.SetDir(graph.Type == ast.DIGRAPH)
  47. graphName := graph.ID.String()
  48. w.g.SetName(graphName)
  49. return newStmtVisitor(w.g, graphName, nil, nil)
  50. }
  51. func newStmtVisitor(g errInterface, graphName string, nodeAttrs, edgeAttrs map[string]string) *stmtVisitor {
  52. nodeAttrs = ammend(make(map[string]string), nodeAttrs)
  53. edgeAttrs = ammend(make(map[string]string), edgeAttrs)
  54. return &stmtVisitor{g, graphName, nodeAttrs, edgeAttrs, make(map[string]string), make(map[string]struct{})}
  55. }
  56. type stmtVisitor struct {
  57. g errInterface
  58. graphName string
  59. currentNodeAttrs map[string]string
  60. currentEdgeAttrs map[string]string
  61. currentGraphAttrs map[string]string
  62. createdNodes map[string]struct{}
  63. }
  64. func (w *stmtVisitor) Visit(v ast.Elem) ast.Visitor {
  65. switch s := v.(type) {
  66. case ast.NodeStmt:
  67. return w.nodeStmt(s)
  68. case ast.EdgeStmt:
  69. return w.edgeStmt(s)
  70. case ast.NodeAttrs:
  71. return w.nodeAttrs(s)
  72. case ast.EdgeAttrs:
  73. return w.edgeAttrs(s)
  74. case ast.GraphAttrs:
  75. return w.graphAttrs(s)
  76. case *ast.SubGraph:
  77. return w.subGraph(s)
  78. case *ast.Attr:
  79. return w.attr(s)
  80. case ast.AttrList:
  81. return &nilVisitor{}
  82. default:
  83. //fmt.Fprintf(os.Stderr, "unknown stmt %T\n", v)
  84. }
  85. return w
  86. }
  87. func ammend(attrs map[string]string, add map[string]string) map[string]string {
  88. for key, value := range add {
  89. if _, ok := attrs[key]; !ok {
  90. attrs[key] = value
  91. }
  92. }
  93. return attrs
  94. }
  95. func overwrite(attrs map[string]string, overwrite map[string]string) map[string]string {
  96. for key, value := range overwrite {
  97. attrs[key] = value
  98. }
  99. return attrs
  100. }
  101. func (w *stmtVisitor) addNodeFromEdge(nodeID string) {
  102. if _, ok := w.createdNodes[nodeID]; !ok {
  103. w.createdNodes[nodeID] = struct{}{}
  104. w.g.AddNode(w.graphName, nodeID, w.currentNodeAttrs)
  105. }
  106. }
  107. func (w *stmtVisitor) nodeStmt(stmt ast.NodeStmt) ast.Visitor {
  108. nodeID := stmt.NodeID.String()
  109. var defaultAttrs map[string]string
  110. if _, ok := w.createdNodes[nodeID]; !ok {
  111. defaultAttrs = w.currentNodeAttrs
  112. w.createdNodes[nodeID] = struct{}{}
  113. }
  114. // else the defaults were already inherited
  115. attrs := ammend(stmt.Attrs.GetMap(), defaultAttrs)
  116. w.g.AddNode(w.graphName, nodeID, attrs)
  117. return &nilVisitor{}
  118. }
  119. func (w *stmtVisitor) edgeStmt(stmt ast.EdgeStmt) ast.Visitor {
  120. attrs := stmt.Attrs.GetMap()
  121. attrs = ammend(attrs, w.currentEdgeAttrs)
  122. src := stmt.Source.GetID()
  123. srcName := src.String()
  124. if stmt.Source.IsNode() {
  125. w.addNodeFromEdge(srcName)
  126. }
  127. srcPort := stmt.Source.GetPort()
  128. for i := range stmt.EdgeRHS {
  129. directed := bool(stmt.EdgeRHS[i].Op)
  130. dst := stmt.EdgeRHS[i].Destination.GetID()
  131. dstName := dst.String()
  132. if stmt.EdgeRHS[i].Destination.IsNode() {
  133. w.addNodeFromEdge(dstName)
  134. }
  135. dstPort := stmt.EdgeRHS[i].Destination.GetPort()
  136. w.g.AddPortEdge(srcName, srcPort.String(), dstName, dstPort.String(), directed, attrs)
  137. src = dst
  138. srcPort = dstPort
  139. srcName = dstName
  140. }
  141. return w
  142. }
  143. func (w *stmtVisitor) nodeAttrs(stmt ast.NodeAttrs) ast.Visitor {
  144. w.currentNodeAttrs = overwrite(w.currentNodeAttrs, ast.AttrList(stmt).GetMap())
  145. return &nilVisitor{}
  146. }
  147. func (w *stmtVisitor) edgeAttrs(stmt ast.EdgeAttrs) ast.Visitor {
  148. w.currentEdgeAttrs = overwrite(w.currentEdgeAttrs, ast.AttrList(stmt).GetMap())
  149. return &nilVisitor{}
  150. }
  151. func (w *stmtVisitor) graphAttrs(stmt ast.GraphAttrs) ast.Visitor {
  152. attrs := ast.AttrList(stmt).GetMap()
  153. for key, value := range attrs {
  154. w.g.AddAttr(w.graphName, key, value)
  155. }
  156. w.currentGraphAttrs = overwrite(w.currentGraphAttrs, attrs)
  157. return &nilVisitor{}
  158. }
  159. func (w *stmtVisitor) subGraph(stmt *ast.SubGraph) ast.Visitor {
  160. subGraphName := stmt.ID.String()
  161. w.g.AddSubGraph(w.graphName, subGraphName, w.currentGraphAttrs)
  162. return newStmtVisitor(w.g, subGraphName, w.currentNodeAttrs, w.currentEdgeAttrs)
  163. }
  164. func (w *stmtVisitor) attr(stmt *ast.Attr) ast.Visitor {
  165. w.g.AddAttr(w.graphName, stmt.Field.String(), stmt.Value.String())
  166. return w
  167. }