Last active
April 21, 2023 06:41
-
-
Save Krever/75b2bb75eb7c42ab2c19c33c08dc887f to your computer and use it in GitHub Desktop.
Graphviz Dot AST
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
object DotRenderer { | |
def render(graph: Graph): String = { | |
graph match { | |
case DirectedGraph(strict, id, stmtList) => | |
s"${if (strict) "strict " else ""}digraph ${id.getOrElse("")} {${renderStmtList(stmtList)}}" | |
case UndirectedGraph(strict, id, stmtList) => | |
s"${if (strict) "strict " else ""}graph ${id.getOrElse("")} {${renderStmtList(stmtList)}}" | |
} | |
} | |
def renderStmtList(stmtList: List[Stmt]): String = | |
stmtList.map(renderStmt).mkString(";\n") | |
def renderStmt(stmt: Stmt): String = stmt match { | |
case NodeStmt(nodeId, attrList) => | |
s"${renderNodeId(nodeId)}${attrList.map(renderAttrList).getOrElse("")}" | |
case EdgeStmt(from, edgeRHS, attrList) => | |
s"${renderFrom(from)}${edgeRHS.map{case (op, target) => s"${renderEdgeOp(op)}${renderFrom(target)}"}.mkString}${attrList.map(renderAttrList).getOrElse("")}" | |
case AttrStmt(attrType, attrList) => | |
s"${renderAttrType(attrType)}${renderAttrList(attrList)}" | |
case Assignment(id1, id2) => | |
s"$id1=$id2" | |
case SubgraphStmt(subgraph) => | |
renderSubgraph(subgraph) | |
} | |
def renderAttrType(attrType: AttrType): String = attrType match { | |
case GraphAttr => "graph" | |
case NodeAttr => "node" | |
case EdgeAttr => "edge" | |
} | |
def renderAttrList(attrList: AttrList): String = | |
attrList.aList.map { case (k, v) => s"$k=$v" }.mkString("[", ";", "]") | |
def renderEdgeOp(edgeOp: EdgeOp): String = edgeOp match { | |
case DirectedEdgeOp => "->" | |
case UndirectedEdgeOp => "--" | |
} | |
def renderNodeId(nodeId: NodeId): String = | |
s"${nodeId.id}${nodeId.port.map(renderPort).getOrElse("")}" | |
def renderPort(port: Port): String = port match { | |
case PortName(name, compassPt) => s":$name${compassPt.map(cp => s":$cp").getOrElse("")}" | |
case PortCompassPt(compassPt) => s":$compassPt" | |
} | |
def renderCompassPt(compassPt: CompassPt): String = compassPt match { | |
case North => "n" | |
case NorthEast => "ne" | |
case East => "e" | |
case SouthEast => "se" | |
case South => "s" | |
case SouthWest => "sw" | |
case West => "w" | |
case NorthWest => "nw" | |
case Center => "c" | |
case Any => "_" | |
} | |
def renderSubgraph(subgraph: Subgraph): String = | |
s"${if (subgraph.id.isDefined) s"subgraph ${subgraph.id.get}" else ""}{${renderStmtList(subgraph.stmtList)}}" | |
def renderFrom(from: Either[NodeId, Subgraph]): String = | |
from match { | |
case Left(nodeId) => renderNodeId(nodeId) | |
case Right(subgraph) => renderSubgraph(subgraph) | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// This code was generated by ChatGPT from DOT grammar available at https://graphviz.org/doc/info/lang.html | |
sealed trait Graph | |
case class DirectedGraph(strict: Boolean, id: Option[String], stmtList: List[Stmt]) extends Graph | |
case class UndirectedGraph(strict: Boolean, id: Option[String], stmtList: List[Stmt]) extends Graph | |
sealed trait Stmt | |
case class NodeStmt(nodeId: NodeId, attrList: Option[AttrList]) extends Stmt | |
case class EdgeStmt(from: Either[NodeId, Subgraph], edgeRHS: List[(EdgeOp, Either[NodeId, Subgraph])], attrList: Option[AttrList]) extends Stmt | |
case class AttrStmt(attrType: AttrType, attrList: AttrList) extends Stmt | |
case class Assignment(id1: String, id2: String) extends Stmt | |
case class SubgraphStmt(subgraph: Subgraph) extends Stmt | |
sealed trait AttrType | |
case object GraphAttr extends AttrType | |
case object NodeAttr extends AttrType | |
case object EdgeAttr extends AttrType | |
case class AttrList(aList: List[(String, String)]) | |
sealed trait EdgeOp | |
case object DirectedEdgeOp extends EdgeOp | |
case object UndirectedEdgeOp extends EdgeOp | |
case class NodeId(id: String, port: Option[Port]) | |
sealed trait Port | |
case class PortName(name: String, compassPt: Option[CompassPt]) extends Port | |
case class PortCompassPt(compassPt: CompassPt) extends Port | |
sealed trait CompassPt | |
case object North extends CompassPt | |
case object NorthEast extends CompassPt | |
case object East extends CompassPt | |
case object SouthEast extends CompassPt | |
case object South extends CompassPt | |
case object SouthWest extends CompassPt | |
case object West extends CompassPt | |
case object NorthWest extends CompassPt | |
case object Center extends CompassPt | |
case object Any extends CompassPt | |
case class Subgraph(id: Option[String], stmtList: List[Stmt]) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment