pgen2dot.py
1.21 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
"""Draws a dependency graph of non-terminals in a pgen grammar
(pygraphviz required).
Usage: python pgen2dot.py INFILE OUTFILE [ENGINE [OPTION=VAL]...]
"""
import sys, string, os.path
import pygraphviz as gv
import snakes.lang.pgen as pgen
if len(sys.argv) < 3 :
print("Usage: python pgen2dot.py INFILE OUTFILE [ENGINE [OPTION=VAL]...]")
sys.exit(1)
elif len(sys.argv) >= 4 :
engine = sys.argv[3]
else :
engine = "dot"
nodes = set()
edges = set()
def walk (st, lex, rule=None) :
tok, children = st
if tok == pgen.PgenParser.RULE :
rule = children[0][0]
nodes.add(rule)
for child in children[1:] :
walk(child, lex, rule)
elif isinstance(tok, str) and tok.strip() and tok[0] in string.ascii_lowercase :
nodes.add(tok)
if rule is not None :
edges.add((rule, tok))
else :
for child in children :
walk(child, lex, rule)
st, lex = pgen.PgenParser.parse(sys.argv[1])
walk(st, lex)
g = gv.AGraph(directed=True)
g.add_edges_from(edges)
g.graph_attr["overlap"] = "false"
g.graph_attr["splines"] = "true"
for arg in sys.argv[4:] :
key, val = arg.split("=", 1)
g.graph_attr[key] = val
g.draw(sys.argv[2], prog=engine)