diff --git a/.gitignore b/.gitignore
index 4fe20d8ca811ca883188b6ecedac129e0a334af2..6818f62453125eeb3ef3e13ebff45d9387f76d0b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,6 +5,8 @@ larceny-bin
 **/*.scm~
 *.class
 *.out
+*.dot
+*.dot.pdf
 
 # Test and measurment directories, files and output
 test
diff --git a/fabfile.py b/fabfile.py
index c95b4d55e591286f7e2f5edb669cbf5a279f0a12..120b2fec2fdf015aa01851c6dc7c811e9ac0801f 100644
--- a/fabfile.py
+++ b/fabfile.py
@@ -6,6 +6,7 @@ import properties, utils, install, sockets
 import ilp_test as test
 import ilp_measurement as measure
 import ilp_check as check
+import mkdot
 import os
 from fabric.api import local, task, get, hosts, run
 
diff --git a/mkdot.py b/mkdot.py
new file mode 100644
index 0000000000000000000000000000000000000000..9909323eec9ad96c1050ef0fabc2f9a8177eaf31
--- /dev/null
+++ b/mkdot.py
@@ -0,0 +1,52 @@
+from utils import local_quiet
+try:
+	from fabric.api import task
+except ImportError:
+	from fabric_workaround import task
+
+header = 'digraph G {\nnode [shape = "record"]\n'
+footer = '\n}'
+
+@task(default=True)
+def convert(f, output=None):
+	if output is None:
+		output = f+".dot"
+	with open(f) as fd:
+		lines = fd.readlines()
+	with open(output, 'w') as fd:
+		fd.write(header)
+		for line in [l.strip() for l in lines if l.strip().startswith('(ast-rule')]:
+			rule = line[line.index('(ast-rule \'')+11:line.rindex(')')]
+			# inheritance-arrows are "arrowhead = empty"
+			print rule
+			lhand, rhand = rule.split('->')
+			superclass   = lhand[lhand.index(':')+1:] if ':' in lhand else None
+			if superclass:
+				lhand = lhand[:lhand.index(':')]
+			children     = rhand.split('-') if rhand.strip() else []
+			terminals    = filter(lambda x: x.islower(), children)
+			nonterminals = filter(lambda x: not x.islower(), children)
+			# define the node of the left hand side
+			fd.write('{0} [label = "{{{0} | {1}}}"]\n'.format(lhand, '|'.join(terminals)))
+			# add inheritance
+			if superclass:
+				fd.write('{0} -> {1} [arrowhead = "empty"]\n'.format(lhand, superclass))
+			# add nonterminal children
+			for child in nonterminals:
+				print ' child:', child
+				options = ''
+				# handle contexts
+				if '<' in child:
+					child, context = child.split('<')
+					options = 'label = "{0}"'.format(context)
+				# handle lists
+				if child.endswith('*'):
+					child = child[:-1]
+					if options:
+						# it had a context
+						options = 'headlabel = "{0}", label = "{1}"'.format('*', context)
+					else:
+						options = 'headlabel = "*"'
+				fd.write('{0} -> {1}[{2}]\n'.format(lhand, child, options))
+		fd.write(footer)
+	local_quiet('dot {0} -Tpdf > {0}.pdf'.format(output))