|
1 |
| -module GraphIOGMLExt |
| 1 | +module GraphIOParserCombinator |
2 | 2 |
|
3 | 3 | using Graphs
|
4 | 4 | import Graphs: loadgraph, loadgraphs, savegraph
|
5 | 5 |
|
6 |
| -@static if isdefined(Base, :get_extension) |
7 |
| - using GraphIO |
8 |
| - using ParserCombinator |
9 |
| - import GraphIO.GML.GMLFormat |
10 |
| -else # not required for julia >= v1.9 |
11 |
| - using ..GraphIO |
12 |
| - using ..ParserCombinator |
13 |
| - import ..GraphIO.GML.GMLFormat |
| 6 | +using GraphIO |
| 7 | +using ParserCombinator |
| 8 | +import GraphIO.DOT.DOTFormat |
| 9 | +import GraphIO.GML.GMLFormat |
| 10 | + |
| 11 | +function savedot(io::IO, g::AbstractGraph, gname::String="") |
| 12 | + isdir = is_directed(g) |
| 13 | + println(io, (isdir ? "digraph " : "graph ") * gname * " {") |
| 14 | + for i in vertices(g) |
| 15 | + println(io, "\t" * string(i)) |
| 16 | + end |
| 17 | + if isdir |
| 18 | + for u in vertices(g) |
| 19 | + out_nbrs = outneighbors(g, u) |
| 20 | + length(out_nbrs) == 0 && continue |
| 21 | + println(io, "\t" * string(u) * " -> {" * join(out_nbrs, ',') * "}") |
| 22 | + end |
| 23 | + else |
| 24 | + for e in edges(g) |
| 25 | + source = string(src(e)) |
| 26 | + dest = string(dst(e)) |
| 27 | + println(io, "\t" * source * " -- " * dest) |
| 28 | + end |
| 29 | + end |
| 30 | + println(io, "}") |
| 31 | + return 1 |
| 32 | +end |
| 33 | + |
| 34 | +function savedot_mult(io::IO, graphs::Dict) |
| 35 | + ng = 0 |
| 36 | + for (gname, g) in graphs |
| 37 | + ng += savedot(io, g, gname) |
| 38 | + end |
| 39 | + return ng |
| 40 | +end |
| 41 | + |
| 42 | +function _dot_read_one_graph(pg::Parsers.DOT.Graph) |
| 43 | + isdir = pg.directed |
| 44 | + nvg = length(Parsers.DOT.nodes(pg)) |
| 45 | + nodedict = Dict(zip(collect(Parsers.DOT.nodes(pg)), 1:nvg)) |
| 46 | + if isdir |
| 47 | + g = DiGraph(nvg) |
| 48 | + else |
| 49 | + g = Graph(nvg) |
| 50 | + end |
| 51 | + for es in Parsers.DOT.edges(pg) |
| 52 | + s = nodedict[es[1]] |
| 53 | + d = nodedict[es[2]] |
| 54 | + add_edge!(g, s, d) |
| 55 | + end |
| 56 | + return g |
| 57 | +end |
| 58 | + |
| 59 | +function _name(pg::Parsers.DOT.Graph) |
| 60 | + return if pg.id !== nothing |
| 61 | + pg.id.id |
| 62 | + else |
| 63 | + Parsers.DOT.StringID(pg.directed ? "digraph" : "graph") |
| 64 | + end |
| 65 | +end |
| 66 | + |
| 67 | +function loaddot(io::IO, gname::String) |
| 68 | + p = Parsers.DOT.parse_dot(read(io, String)) |
| 69 | + for pg in p |
| 70 | + _name(pg) == gname && return _dot_read_one_graph(pg) |
| 71 | + end |
| 72 | + return error("Graph $gname not found") |
| 73 | +end |
| 74 | + |
| 75 | +function loaddot_mult(io::IO) |
| 76 | + p = Parsers.DOT.parse_dot(read(io, String)) |
| 77 | + graphs = Dict{String,AbstractGraph}() |
| 78 | + |
| 79 | + for pg in p |
| 80 | + graphs[_name(pg)] = _dot_read_one_graph(pg) |
| 81 | + end |
| 82 | + return graphs |
14 | 83 | end
|
15 | 84 |
|
| 85 | +loadgraph(io::IO, gname::String, ::DOTFormat) = loaddot(io, gname) |
| 86 | +loadgraphs(io::IO, ::DOTFormat) = loaddot_mult(io) |
| 87 | +savegraph(io::IO, g::AbstractGraph, gname::String, ::DOTFormat) = savedot(io, g, gname) |
| 88 | +savegraph(io::IO, d::Dict, ::DOTFormat) = savedot_mult(io, d) |
| 89 | + |
16 | 90 | function _gml_read_one_graph(gs, dir)
|
17 | 91 | nodes = [x[:id] for x in gs[:node]]
|
18 | 92 | if dir
|
@@ -54,7 +128,7 @@ function loadgml_mult(io::IO)
|
54 | 128 | end
|
55 | 129 |
|
56 | 130 | """
|
57 |
| - savegml(f, g, gname="graph") |
| 131 | + savegml(f, g, gname="graph") |
58 | 132 |
|
59 | 133 | Write a graph `g` with name `gname` to an IO stream `io` in the
|
60 | 134 | [GML](https://en.wikipedia.org/wiki/Graph_Modelling_Language) format. Return 1.
|
@@ -83,7 +157,7 @@ function savegml(io::IO, g::AbstractGraph, gname::String="")
|
83 | 157 | end
|
84 | 158 |
|
85 | 159 | """
|
86 |
| - savegml_mult(io, graphs) |
| 160 | + savegml_mult(io, graphs) |
87 | 161 | Write a dictionary of (name=>graph) to an IO stream `io` Return number of graphs written.
|
88 | 162 | """
|
89 | 163 | function savegml_mult(io::IO, graphs::Dict)
|
|
0 commit comments