Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Dot importer #15

Open
clue opened this issue Jun 29, 2015 · 1 comment
Open

Add Dot importer #15

clue opened this issue Jun 29, 2015 · 1 comment

Comments

@clue
Copy link
Member

clue commented Jun 29, 2015

This library currently focuses on exporting a Graph instance into a format that GraphViz can read in order to produce a resulting graph image, i.e. export via the Dot language.

However, we currently have no means to import from a Dot language definition into a Graph instance, i.e. import via Dot language.

This is non-trivial, but I suppose all building blocks are ready. We can probably focus on the 80% use case and exclude some of the advanced features like sub-graphs and graph clusters.

Any volunteers? :)

@Gounlaf
Copy link

Gounlaf commented Feb 12, 2020

dumb "implementation" for my need

{
  "require": {
    "php": ">=7.3",
    "farafiri/php-parsing-tool": "^2.0",
    "graphp/graphviz": "^0.2.2"
  }
}
// based on https://graphviz.gitlab.io/_pages/doc/info/lang.html
// not sure about ID definition =/

$grammar = <<<DOT_GRAMMAR
graph :=> 'strict'? ('graph'|'digraph') ID? '{' stmt_list '}'.
ID :=> /"(.*?)"|([-]?(.[0-9]+|[0-9]+(.[0-9]*)?))|([a-zA-Z\200-\377_][0-9a-zA-Z\200-\377_]*)/.
stmt_list :=> (stmt ';'? stmt_list)?.
stmt :=> node_stmt
    :=> edge_stmt
    :=> attr_stmt
    :=> ID '=' ID
    :=> subgraph.
attr_stmt :=> ('graph'|'node'|'edge') attr_list.
attr_list :=> '[' a_list? ']' attr_list?.
a_list :=> ID '=' ID (';' | ',')? a_list?.
edge_stmt :=> (node_id | subgraph) edgeRHS attr_list?.
edgeRHS :=> edgeop (node_id | subgraph) edgeRHS?.
edgeop :=> ('->'|'--').
node_stmt :=> node_id attr_list?.
node_id :=> ID port?.
port :=> ':' ID (':' compass_pt)?
    :=> ':' compass_pt.
subgraph :=> (subgraph ID?)? '{' stmt_list '}'.
compass_pt :=> ('n'|'ne'|'e'|'se'|'s'|'sw'|'w'|'nw'|'c'|'_').
DOT_GRAMMAR;

$parser = new \ParserGenerator\Parser($grammar, ['ignoreWhitespaces' => true]);
$parsed = $parser->parse($smallOne, 'graph');
if (false === $parsed) {
    fwrite(STDERR, $parser->getErrorString($smallOne));
    exit(1);
}

$graph = new \Fhaculty\Graph\Graph();

function cleanValue(\ParserGenerator\SyntaxTreeNode\Base $node) {
    return trim($node->toString(), '"\'');
}

function parseAttributes($stmt, \Fhaculty\Graph\Attribute\AttributeAware $attributeAware) {
    $attrList = $stmt->findFirst('attr_list');
    if ($attrList) {
        foreach ($attrList->findAll('a_list') as $aList) {
            [$attribute, $value] = $aList->findAll('ID');
            $attributeAware->setAttribute('graphviz.' . cleanValue($attribute), cleanValue($value));
        }
    }
}

foreach ($parsed->findAll('stmt') as $stmt) {
    $nodeId = cleanValue($stmt->findFirst('node_id'));
    $left = $graph->createVertex($nodeId, true);

    $edgeRHS = $stmt->findFirst('edgeRHS');

    if ($edgeRHS === null) {
        parseAttributes($stmt, $left);
    } else {
        $rightId = cleanValue($edgeRHS->findFirst('node_id'));
        $right = $graph->createVertex($rightId, true);

        if (cleanValue($edgeRHS->findFirst('edgeop')) === '->') {
            $edge = $left->createEdgeTo($right);
        } else {
            $edge = $left->createEdge($right);
        }

        parseAttributes($stmt, $edge);
    }
}

$graphviz = new Graphp\GraphViz\GraphViz();
var_dump($graphviz->createScript($graph));

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants