using compiler class GraphDsl : DslPlugin { new make(Compiler c) : super(c) {} override Expr compile(DslExpr expr) { nodes := Str[,] edges := Str[][,] expr.src.splitLines.map { it.trim}.exclude { it->size == 0 }.each |l, i| { m := r.matcher(l) if(!m.find) throw err("Invalid line $l", Loc(expr.srcLoc.file, expr.srcLoc.line + i)) first := m.group(1) last := m.group(2) nodes.add(first).add(last) edges.add([first, last]) } nodes = nodes.unique loc := expr.loc return makeObj(graphType, [nodeList(nodes, loc), edgeList(edges, loc)], loc) } private CType graphType() { ns.resolveType("graphs::Graph") } private CType nodeType() { ns.resolveType("graphs::Node") } private CType edgeType() { ns.resolveType("graphs::Edge") } private Expr nodeList(Str[] nodes, Loc loc) { ListLiteralExpr.makeFor(loc, ListType(nodeType), nodes.map |n| { makeNode(n, loc) }) } private Expr edgeList(Str[][] edges, Loc loc) { ListLiteralExpr.makeFor(loc, ListType(edgeType), edges.map |e| { makeEdge(e.first, e.last, loc ) }) } private Expr makeObj(CType type, Expr[] args, Loc loc, Str cname := "make") { CallExpr.makeWithMethod(loc, StaticTargetExpr.make(loc, type), type.method(cname), args) } private Expr makeNode(Str name, Loc loc) { makeObj(nodeType, [LiteralExpr.makeStr(loc, ns, name)], loc) } private Expr makeEdge(Str from, Str to, Loc loc) { makeObj(edgeType, [makeNode(from, loc), makeNode(to, loc)], loc) } private static const Regex r := Regex<|(\w+)\s*->\s*(\w+)|> }