178 lines
3.8 KiB
Bash
178 lines
3.8 KiB
Bash
SIMPLE_DOT=$(cat <<'EOF'
|
|
BEGIN {
|
|
edge = "->"
|
|
properties_separator = ";"
|
|
open_blocks = "{"
|
|
close_blocks = "}"
|
|
hyperedge_property = "_he"
|
|
uuid_command = "uuidgen"
|
|
|
|
blocks = 0
|
|
processed_line = 0
|
|
|
|
# Print the graph header.
|
|
#print "digraph {"
|
|
}
|
|
|
|
# Firstly, we process blocks.
|
|
NF == 1 && $1 == open_blocks {
|
|
# open block
|
|
blocks++
|
|
}
|
|
|
|
NF == 1 && $1 == "}" {
|
|
# close block
|
|
blocks--
|
|
}
|
|
|
|
# Secondly, we process "special rules".
|
|
## Nodes.
|
|
NF > 1 && $2 != edge {
|
|
printf ($1 "\t")
|
|
label = get_label($0)
|
|
get_properties($0, properties)
|
|
properties_str = generate_properties(label, properties)
|
|
if (length(properties_str)) {
|
|
print properties_str
|
|
}
|
|
|
|
processed_line = 1
|
|
}
|
|
|
|
## Edges.
|
|
NF > 3 && $2 == edge {
|
|
printf ($1 FS $2 FS $3)
|
|
label = get_label($0)
|
|
get_properties($0, properties)
|
|
properties_str = generate_properties(label, properties)
|
|
if (length(properties_str)) {
|
|
printf "\t"
|
|
print properties_str
|
|
}
|
|
|
|
processed_line = 1
|
|
}
|
|
|
|
# Thirdly, we do general treatment for every line.
|
|
{
|
|
if (!processed_line) {
|
|
print $0
|
|
}
|
|
processed_line = 0
|
|
}
|
|
|
|
END {
|
|
# Print the closing curly brace.
|
|
print "}"
|
|
}
|
|
|
|
function get_label(_line, _field, _out, _split, _len) {
|
|
_field = 2
|
|
if ($2 == edge) {
|
|
_field = 4
|
|
}
|
|
|
|
# Special case: there isn't label, but there are properties.
|
|
_len = split($(_field), _split, properties_separator)
|
|
if ((_len > 1) && !_split[1]) {
|
|
# There is a properties_separator in the field, and no label.
|
|
return
|
|
}
|
|
|
|
for (_field; _field <= NF; _field++) {
|
|
_len = split($(_field), _split, properties_separator)
|
|
if (_len > 1) {
|
|
_out = !(_out) ? _split[1] : (_out FS _split[1])
|
|
return _out
|
|
} else {
|
|
_out = !(_out) ? $(_field) : (_out FS $(_field))
|
|
}
|
|
}
|
|
return _out
|
|
}
|
|
|
|
function get_properties(_line, _split, _field, _len, _uuid) {
|
|
delete _split
|
|
_len = split(_line, _split, properties_separator)
|
|
if (!_len) {
|
|
return
|
|
}
|
|
|
|
for (_field = 2; _field <= _len; _field++) {
|
|
if (_split[_field] == hyperedge_property) {
|
|
uuid_command | getline _uuid
|
|
_split[_field] = hyperedge_property "=\"" _uuid "\""
|
|
close(uuid_command)
|
|
}
|
|
_split[_field - 1] = _split[_field]
|
|
}
|
|
delete _split[_len]
|
|
return
|
|
}
|
|
|
|
function generate_properties(_label, _properties, _out, _len, _type_label) {
|
|
_type_label = "label"
|
|
for (p in _properties) {
|
|
if (match(hyperedge_property, _properties[p])) {
|
|
_type_label = "xlabel"
|
|
}
|
|
}
|
|
if (_label) {
|
|
_out = (_type_label "=\"" _label "\"")
|
|
}
|
|
|
|
_len = length(_properties)
|
|
for (i = 1; i <= _len; i++) {
|
|
_out = !(_out) ? _properties[1] : (_out "," _properties[i])
|
|
}
|
|
|
|
return (!(_out) ? "" : ("[" _out "]"))
|
|
}
|
|
EOF
|
|
)
|
|
|
|
HYPERGRAPH_PROCESSOR=$(cat <<'EOF'
|
|
// An attempt to reproduce what was reported in https://gitlab.com/graphviz/graphviz/-/issues/1911#note_473279838
|
|
|
|
E [ _he ] {
|
|
// Creates the node representing the hyper-edge, if it already doesn't exist.
|
|
node_t hyperedge = isNode($G, $._he);
|
|
if (!hyperedge) {
|
|
hyperedge = node($G, $._he);
|
|
hyperedge.shape = "point";
|
|
hyperedge.fillcolor = "red";
|
|
if ($.label) {
|
|
/*
|
|
hyperedge.label = $.label;
|
|
hyperedge.shape = "none";
|
|
*/
|
|
hyperedge.xlabel = $.label;
|
|
}
|
|
}
|
|
|
|
// Creates the edges to and from hyperedge, if it already doesn't exist.
|
|
if (!isEdge_sg($G, $.tail, hyperedge, "")) {
|
|
edge_t new_out = edge_sg($G, $.tail, hyperedge, "");
|
|
new_out.arrowhead = "none";
|
|
}
|
|
if(!isEdge_sg($G, hyperedge, $.head, "")) {
|
|
edge_t new_in = edge_sg($G, hyperedge, $.head, "");
|
|
}
|
|
|
|
// Removes the current edge (with attribute "_he") because edges to "hyperedge" are added.
|
|
delete($G, $);
|
|
}
|
|
EOF
|
|
)
|
|
|
|
# Process the input files and produce a SVG.
|
|
cat <(echo "digraph {") ~/src/scripts/concept-style.dot <(awk -f <(echo "${SIMPLE_DOT}") $*) |
|
|
gvpr -c -f <(echo "${HYPERGRAPH_PROCESSOR}") |
|
|
dot -Tsvg
|
|
|
|
## DEAD-CODE
|
|
## awk -f ~/tmp/graphviz/concept.awk $* |
|
|
## gvpr -c -f ~/tmp/graphviz/hypergraph.gvpr |
|
|
## xsel -ib
|
|
|