packages feed

hydra-0.15.0: src/main/haskell/Hydra/Sources/Graphviz/Dot.hs

module Hydra.Sources.Graphviz.Dot where

-- Standard imports for type-level sources outside of the kernel
import           Hydra.Kernel
import           Hydra.Dsl.Annotations
import           Hydra.Dsl.Bootstrap
import           Hydra.Dsl.Types                 ((>:))
import qualified Hydra.Dsl.Types                 as T
import qualified Hydra.Sources.Kernel.Types.Core as Core
import qualified Data.List                       as L
import qualified Data.Map                        as M
import qualified Data.Set                        as S
import qualified Data.Maybe                      as Y


ns :: Namespace
ns = Namespace "hydra.graphviz.dot"

define :: String -> Type -> Binding
define = defineType ns

dot :: String -> Type
dot = typeref ns

module_ :: Module
module_ = Module {
            moduleNamespace = ns,
            moduleDefinitions = (map toTypeDef definitions),
            moduleTermDependencies = [],
            moduleTypeDependencies = [Core.ns],
            moduleDescription = Just ("A model from the Graphviz DOT graph description language."
      ++ " Based on the grammar at https://graphviz.org/doc/info/lang.html")}
  where
    definitions = [
      id_,
      graph_,
      stmt,
      equalityPair,
      attrStmt,
      attrType,
      attrList,
      edgeStmt,
      nodeOrSubgraph,
      nodeStmt,
      nodeId,
      port,
      subgraph,
      subgraphId,
      compassPt]

id_ :: Binding
id_ = define "Id" $ T.wrap T.string

--graph	:	[ strict ] (graph | digraph) [ ID ] '{' stmt_list '}'
graph_ :: Binding
graph_ = define "Graph" $
  T.record [
    "strict">: T.boolean,
    "directed">: T.boolean,
    "id">: T.maybe $ dot "Id",
    "statements">: T.list $ dot "Stmt"]

--stmt_list	:	[ stmt [ ';' ] stmt_list ]
--stmt	:	node_stmt
--      |	edge_stmt
--      |	attr_stmt
--      |	ID '=' ID
--      |	subgraph
stmt :: Binding
stmt = define "Stmt" $
  T.union [
    "node">: dot "NodeStmt",
    "edge">: dot "EdgeStmt",
    "attr">: dot "AttrStmt",
    "equals">: dot "EqualityPair",
    "subgraph">: dot "Subgraph"]

equalityPair :: Binding
equalityPair = define "EqualityPair" $
  T.record [
    "left">: dot "Id",
    "right">: dot "Id"]

--attr_stmt	:	(graph | node | edge) attr_list
--attr_list	:	'[' [ a_list ] ']' [ attr_list ]
--a_list	:	ID '=' ID [ (';' | ',') ] [ a_list ]
attrStmt :: Binding
attrStmt = define "AttrStmt" $
  T.record [
    "type">: dot "AttrType",
    "attributes">: dot "AttrList"]

attrType :: Binding
attrType = define "AttrType" $
  T.enum ["graph", "node", "edge"]

attrList :: Binding
attrList = define "AttrList" $
  T.wrap $ nonemptyList $ nonemptyList $ dot "EqualityPair"

--edge_stmt	:	(node_id | subgraph) edgeRHS [ attr_list ]
--edgeRHS	:	edgeop (node_id | subgraph) [ edgeRHS ]
edgeStmt :: Binding
edgeStmt = define "EdgeStmt" $
  T.record [
    "left">: dot "NodeOrSubgraph",
    "right">: nonemptyList $ dot "NodeOrSubgraph",
    "attributes">: T.maybe $ dot "AttrList"]

nodeOrSubgraph :: Binding
nodeOrSubgraph = define "NodeOrSubgraph" $
  T.union [
    "node">: dot "NodeId",
    "subgraph">: dot "Subgraph"]

--node_stmt	:	node_id [ attr_list ]
nodeStmt :: Binding
nodeStmt = define "NodeStmt" $
  T.record [
    "id">: dot "NodeId",
    "attributes">: T.maybe $ dot "AttrList"]

--node_id	:	ID [ port ]
nodeId :: Binding
nodeId = define "NodeId" $
  T.record [
    "id">: dot "Id",
    "port">: T.maybe $ dot "Port"]

--port	:	':' ID [ ':' compass_pt ]
--      |	':' compass_pt
port :: Binding
port = define "Port" $
  T.record [
    "id">: T.maybe $ dot "Id",
    "position">: T.maybe $ dot "CompassPt"]

--subgraph	:	[ subgraph [ ID ] ] '{' stmt_list '}'
subgraph :: Binding
subgraph = define "Subgraph" $
  T.record [
    "subgraphId">: T.maybe $ dot "SubgraphId",
    "statements">: T.list $ dot "Stmt"]

subgraphId :: Binding
subgraphId = define "SubgraphId" $
  T.wrap $ T.maybe $ dot "Id"

--compass_pt	:	(n | ne | e | se | s | sw | w | nw | c | _)
compassPt :: Binding
compassPt = define "CompassPt" $
  T.enum ["n", "ne", "e", "se", "s", "sw", "w", "nw", "c", "none"]