Add more flexibility in how whitespace is specified.
[gazelle.git] / docs / gzl-rtn-graph
blob4e6c75695204533e0b5fa0181fb794ab53da8a9b
1 #!/usr/bin/env lua
2 --[[--------------------------------------------------------------------
4   Gazelle: a system for building fast, reusable parsers
6   gzl-rtn-graph
8   A script for generating graphics for the manual.  It parses Gazelle
9   language excerpts in manual.txt and emits pngs using graphviz.
11   Copyright (c) 2007-2008 Joshua Haberman.  See LICENSE for details.
13 --------------------------------------------------------------------]]--
15 require "bootstrap/rtn"
16 require "fa_algorithms"
18 function escape(str)
19   return str:gsub("[\"\\]", "\\%1")
20 end
22 grammar = parse_grammar(CharStream:new(io.stdin:read("*a")))
23 if grammar.rtns:count() ~= 1 then
24   error("This filter can only deal with grammars that have a single nonterminal")
25 end
26 for _nonterm, _rtn in grammar.rtns:each() do
27   nonterm = _nonterm
28   rtn = _rtn
29 end
31 rtn = hopcroft_minimize(nfa_to_dfa(rtn))
33 outfile = io.popen("dot -Tpng -o " .. arg[1], "w")
35 outfile:write("digraph untitled {\n")
36 outfile:write("rankdir=LR;\n")
37 outfile:write("fontsize=10;\n")
38 for state in each(rtn:states()) do
39   peripheries = 1
40   extra_label = ""
41   if state.final then peripheries = 2 end
42   if rtn.start == state then extra_label = "Start" end
43   outfile:write(string.format('  "%s" [label="%s" peripheries=%d]\n', tostring(state), extra_label, peripheries))
44   for edge_val, target_state in state:transitions() do
45     if fa.is_nonterm(edge_val) then
46       outfile:write(string.format('  "%s" -> "%s" [label="<%s>"]\n', tostring(state), tostring(target_state), escape(edge_val.name)))
47     else
48       if grammar.attributes.regex_text[edge_val] then
49         edge_val = "/" .. grammar.attributes.regex_text[edge_val] .. "/"
50       end
51       outfile:write(string.format('  "%s" -> "%s" [label="%s"]\n', tostring(state), tostring(target_state), escape(edge_val)))
52     end
53   end
54 end
55 outfile:write("}\n")
56 outfile:close()
58 print(" ")