Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .style.yapf
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[style]
based_on_style=google
column_limit=79
155 changes: 68 additions & 87 deletions dot_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,22 +11,16 @@
from __future__ import print_function
import sys

from pyparsing import (
nestedExpr, Literal, CaselessLiteral,
Word, OneOrMore,
Forward,
Group, Optional, Combine,
restOfLine, cStyleComment, nums, alphanums,
printables,
ParseException, ParseResults, CharsNotIn,
QuotedString)
from pyparsing import (nestedExpr, Literal, CaselessLiteral, Word, OneOrMore,
Forward, Group, Optional, Combine, restOfLine,
cStyleComment, nums, alphanums, printables,
ParseException, ParseResults, CharsNotIn, QuotedString)

import pydot

__author__ = ['Michael Krause', 'Ero Carrera']
__license__ = 'MIT'


PY3 = sys.version_info >= (3, 0, 0)
if PY3:
str_type = str
Expand All @@ -42,8 +36,8 @@ def __init__(self, toks):

while i < len(toks):
attrname = toks[i]
if i+2 < len(toks) and toks[i+1] == '=':
attrvalue = toks[i+2]
if i + 2 < len(toks) and toks[i + 1] == '=':
attrvalue = toks[i + 2]
i += 3
else:
attrvalue = None
Expand All @@ -62,8 +56,8 @@ def __init__(self, default_type, attrs):
self.attrs = attrs

def __repr__(self):
return "%s(%s, %r)" % (self.__class__.__name__,
self.default_type, self.attrs)
return "%s(%s, %r)" % (self.__class__.__name__, self.default_type,
self.attrs)


top_graphs = list()
Expand All @@ -76,8 +70,7 @@ def push_top_graph_stmt(str, loc, toks):
for element in toks:

if (isinstance(element, (ParseResults, tuple, list)) and
len(element) == 1 and
isinstance(element[0], str_type)):
len(element) == 1 and isinstance(element[0], str_type)):

element = element[0]

Expand Down Expand Up @@ -149,9 +142,9 @@ def update_parent_graph_hierarchy(g, parent_graph=None, level=0):

if key_name == 'edges' and len(key) == 2:
for idx, vertex in enumerate(obj['points']):
if isinstance(vertex,
(pydot.Graph,
pydot.Subgraph, pydot.Cluster)):
if isinstance(
vertex,
(pydot.Graph, pydot.Subgraph, pydot.Cluster)):
vertex.set_parent_graph(parent_graph)
if isinstance(vertex, pydot.frozendict):
if vertex['parent_graph'] is g:
Expand All @@ -168,8 +161,11 @@ def add_defaults(element, defaults):
d[key] = value


def add_elements(g, toks, defaults_graph=None,
defaults_node=None, defaults_edge=None):
def add_elements(g,
toks,
defaults_graph=None,
defaults_node=None,
defaults_edge=None):
if defaults_graph is None:
defaults_graph = {}
if defaults_node is None:
Expand Down Expand Up @@ -197,8 +193,8 @@ def add_elements(g, toks, defaults_graph=None,
elif isinstance(element, ParseResults):

for e in element:
add_elements(g, [e], defaults_graph,
defaults_node, defaults_edge)
add_elements(g, [e], defaults_graph, defaults_node,
defaults_edge)

elif isinstance(element, DefaultStatement):

Expand All @@ -219,9 +215,8 @@ def add_elements(g, toks, defaults_graph=None,
defaults_edge.update(element.attrs)

else:
raise ValueError(
'Unknown DefaultStatement: {s}'.format(
s=element.default_type))
raise ValueError('Unknown DefaultStatement: {s}'.format(
s=element.default_type))

elif isinstance(element, P_AttrList):

Expand Down Expand Up @@ -268,8 +263,7 @@ def push_default_stmt(str, loc, toks):
if default_type in ['graph', 'node', 'edge']:
return DefaultStatement(default_type, attrs)
else:
raise ValueError(
'Unknown default statement: {s}'.format(s=toks))
raise ValueError('Unknown default statement: {s}'.format(s=toks))


def push_attr_list(str, loc, toks):
Expand All @@ -290,7 +284,7 @@ def get_port(node):
def do_node_ports(node):
node_port = ''
if len(node) > 1:
node_port = ''.join([str(a)+str(b) for a, b in node[1]])
node_port = ''.join([str(a) + str(b) for a, b in node[1]])

return node_port

Expand All @@ -311,16 +305,17 @@ def push_edge_stmt(str, loc, toks):

if isinstance(toks[2][0], ParseResults):

n_next_list = [[n.get_name(), ] for n in toks[2][0]]
n_next_list = [[
n.get_name(),
] for n in toks[2][0]]
for n_next in [n for n in n_next_list]:
n_next_port = do_node_ports(n_next)
e.append(pydot.Edge(n_prev, n_next[0]+n_next_port, **attrs))
e.append(pydot.Edge(n_prev, n_next[0] + n_next_port, **attrs))

elif isinstance(toks[2][0], pydot.Graph):

e.append(pydot.Edge(n_prev,
pydot.frozendict(toks[2][0].obj_dict),
**attrs))
e.append(
pydot.Edge(n_prev, pydot.frozendict(toks[2][0].obj_dict), **attrs))

elif isinstance(toks[2][0], pydot.Node):

Expand All @@ -343,13 +338,12 @@ def push_edge_stmt(str, loc, toks):
continue

n_next_port = do_node_ports(n_next)
e.append(pydot.Edge(n_prev, n_next[0]+n_next_port, **attrs))
e.append(pydot.Edge(n_prev, n_next[0] + n_next_port, **attrs))

n_prev = n_next[0]+n_next_port
n_prev = n_next[0] + n_next_port
else:
raise Exception(
'Edge target {r} with type {s} unsupported.'.format(
r=toks[2][0], s=type(toks[2][0])))
raise Exception('Edge target {r} with type {s} unsupported.'.format(
r=toks[2][0], s=type(toks[2][0])))

return e

Expand Down Expand Up @@ -405,9 +399,10 @@ def graph_definition():
# token definitions
identifier = Word(alphanums + "_.").setName("identifier")

double_quoted_string = QuotedString(
'"', multiline=True, unquoteResults=False, escChar='\\'
)
double_quoted_string = QuotedString('"',
multiline=True,
unquoteResults=False,
escChar='\\')

noncomma = "".join([c for c in printables if c != ","])
alphastring_ = OneOrMore(CharsNotIn(noncomma + ' '))
Expand All @@ -418,83 +413,69 @@ def parse_html(s, loc, toks):
opener = '<'
closer = '>'
html_text = nestedExpr(
opener, closer, (CharsNotIn(opener + closer))
).setParseAction(parse_html).leaveWhitespace()
opener, closer,
(CharsNotIn(opener +
closer))).setParseAction(parse_html).leaveWhitespace()

ID = (identifier | html_text | double_quoted_string |
alphastring_).setName("ID")

float_number = Combine(
Optional(minus) +
OneOrMore(Word(nums + "."))
).setName("float_number")
float_number = Combine(Optional(minus) +
OneOrMore(Word(nums +
"."))).setName("float_number")

righthand_id = (float_number | ID).setName("righthand_id")

port_angle = (at + ID).setName("port_angle")

port_location = (
OneOrMore(Group(colon + ID)) |
Group(colon + lparen + ID + comma + ID + rparen)
).setName("port_location")
port_location = (OneOrMore(Group(colon + ID)) |
Group(colon + lparen + ID + comma + ID +
rparen)).setName("port_location")

port = (
Group(port_location + Optional(port_angle)) |
Group(port_angle + Optional(port_location))
).setName("port")
port = (Group(port_location + Optional(port_angle)) |
Group(port_angle + Optional(port_location))).setName("port")

node_id = (ID + Optional(port))
a_list = OneOrMore(
ID +
Optional(equals + righthand_id) +
Optional(comma.suppress())
).setName("a_list")

attr_list = OneOrMore(
lbrack.suppress() +
Optional(a_list) +
rbrack.suppress()
).setName("attr_list")
a_list = OneOrMore(ID + Optional(equals + righthand_id) +
Optional(comma.suppress())).setName("a_list")

attr_list = OneOrMore(lbrack.suppress() + Optional(a_list) +
rbrack.suppress()).setName("attr_list")

attr_stmt = (Group(graph_ | node_ | edge_) +
attr_list).setName("attr_stmt")

edgeop = (Literal("--") | Literal("->")).setName("edgeop")

stmt_list = Forward()
graph_stmt = Group(
lbrace.suppress() +
Optional(stmt_list) +
rbrace.suppress() +
Optional(semi.suppress())
).setName("graph_stmt")
graph_stmt = Group(lbrace.suppress() + Optional(stmt_list) +
rbrace.suppress() +
Optional(semi.suppress())).setName("graph_stmt")

edge_point = Forward()

edgeRHS = OneOrMore(edgeop + edge_point)
edge_stmt = edge_point + edgeRHS + Optional(attr_list)

subgraph = Group(
subgraph_ + Optional(ID) + graph_stmt).setName("subgraph")
subgraph = Group(subgraph_ + Optional(ID) +
graph_stmt).setName("subgraph")

edge_point << Group(
subgraph | graph_stmt | node_id).setName('edge_point')
edge_point << Group(subgraph | graph_stmt |
node_id).setName('edge_point')

node_stmt = (
node_id + Optional(attr_list) +
Optional(semi.suppress())).setName("node_stmt")
node_stmt = (node_id + Optional(attr_list) +
Optional(semi.suppress())).setName("node_stmt")

assignment = (ID + equals + righthand_id).setName("assignment")
stmt = (assignment | edge_stmt | attr_stmt |
subgraph | graph_stmt | node_stmt).setName("stmt")
stmt = (assignment | edge_stmt | attr_stmt | subgraph | graph_stmt |
node_stmt).setName("stmt")
stmt_list << OneOrMore(stmt + Optional(semi.suppress()))

graphparser = OneOrMore(
(Optional(strict_) + Group((graph_ | digraph_)) +
Optional(ID) + graph_stmt).setResultsName("graph"))
graphparser = OneOrMore((Optional(strict_) + Group(
(graph_ | digraph_)) + Optional(ID) +
graph_stmt).setResultsName("graph"))

singleLineComment = Group(
"//" + restOfLine) | Group("#" + restOfLine)
singleLineComment = Group("//" + restOfLine) | Group("#" + restOfLine)

# actions

Expand Down
Loading