A great deal of work on lookahead. Many more test cases, and lots of fixes.
[gazelle.git] / sketches / dump_to_html.lua
blob5fb8f7db66b06f7c9b28c4d4778b0c53b034009b
2 function dump_to_html(src_file, grammar, dir)
3 os.execute("mkdir -p " .. dir)
5 local glas = OrderedSet:new()
7 for name, rtn in each(grammar.rtns) do
8 for state in each(rtn:states()) do
9 if state.gla then
10 glas:add(state.gla)
11 end
12 end
13 end
15 local index = io.open(dir .. "/index.html", "w")
16 local title = string.format("Gazelle Grammar Dump: %s", src_file)
17 index:write("<!DOCTYPE html>\n")
18 index:write("<html>\n")
19 index:write(string.format("<head><title>%s</title></head>\n", title))
20 index:write("<body>\n")
21 index:write("<h1>" .. title .. "</h1>\n")
22 index:write("<ul>\n")
23 index:write("<li><a href='#rules'>Rules</a></li>\n")
24 index:write("<ul>\n")
25 for name, rtn in each(grammar.rtns) do
26 index:write(string.format("<li><a href='#rule_%s'>%s</a></li>", name, name))
27 end
28 index:write("</ul>\n")
29 index:write("<li><a href='#lookahead'>Lookahead</a></li>\n")
30 index:write("<ul>\n")
31 local gla_num = 1
32 for gla in each(glas) do
33 index:write(string.format("<li><a href='#gla_%d'>GLA %d</a></li>", gla_num, gla_num))
34 gla_num = gla_num + 1
35 end
36 index:write("</ul>\n")
37 index:write("<li><a href='#lexing'>Lexing</a></li>\n")
38 index:write("<ul>\n")
39 local intfa_num = 1
40 for intfa in each(grammar.master_intfas) do
41 index:write(string.format("<li><a href='#intfa_%d'>IntFA %d</a></li>", intfa_num, intfa_num))
42 intfa_num = intfa_num + 1
43 end
44 index:write("</ul>\n")
45 index:write("</ul>")
47 index:write("<h2><a name='rules'>Rules</a></h2>\n")
48 index:write("<p>The states in the grammar are:</p>")
49 local no_gla_breakdown = {}
50 local with_gla_breakdown = {}
51 local lookaheads = Set:new()
52 local total = 0
53 for name, rtn in each(grammar.rtns) do
54 for state in each(rtn:states()) do
55 total = total + 1
56 local lookahead
57 if state.gla then
58 lookahead = state.gla.longest_path
59 with_gla_breakdown[lookahead] = with_gla_breakdown[lookahead] or 0
60 with_gla_breakdown[lookahead] = with_gla_breakdown[lookahead] + 1
61 else
62 if state:num_transitions() == 1 then
63 lookahead = 0
64 else
65 lookahead = 1
66 end
67 no_gla_breakdown[lookahead] = no_gla_breakdown[lookahead] or 0
68 no_gla_breakdown[lookahead] = no_gla_breakdown[lookahead] + 1
69 end
70 lookaheads:add(lookahead)
71 end
72 end
74 lookaheads = lookaheads:to_array()
75 table.sort(lookaheads)
77 index:write("<ul>")
78 for lookahead in each(lookaheads) do
79 if no_gla_breakdown[lookahead] then
80 index:write(string.format("<li>%0.1f%% LL(%d) (%d/%d states)</li>\n",
81 no_gla_breakdown[lookahead] / total * 100, lookahead,
82 no_gla_breakdown[lookahead], total))
83 end
84 end
85 for lookahead in each(lookaheads) do
86 if with_gla_breakdown[lookahead] then
87 local color
88 if lookahead == 1 then
89 color = "#6495ed"
90 elseif lookahead == 2 then
91 color = "#ffd700"
92 else
93 color = "#b22222"
94 end
95 local lookahead_str
96 if lookahead == math.huge then
97 lookahead_str = "*"
98 else
99 lookahead_str = tostring(lookahead)
101 index:write(string.format("<li>%0.1f%% LL(%s) with GLA (%d/%d states): \n" ..
102 "indicated with <span style='background-color: %s'>color</span> below</li>\n",
103 with_gla_breakdown[lookahead] / total * 100, lookahead_str,
104 with_gla_breakdown[lookahead], total, color))
107 index:write("</ul>")
109 index:write("<table border='1'>\n")
111 for name, rtn in each(grammar.rtns) do
112 local rtn_file = io.open(string.format("%s/%s.dot", dir, name), "w")
113 rtn_file:write("digraph untitled {\n")
114 rtn_file:write(rtn:to_dot(" ", "", grammar.master_intfas, glas))
115 rtn_file:write("}\n")
116 rtn_file:close()
117 os.execute(string.format("dot -Tpng -o %s/%s.png %s/%s.dot", dir, name, dir, name))
118 index:write(" <tr><td rowspan='2'>")
119 index:write(string.format("<a name='rule_%s'>%s</td>", name, name))
120 index:write(string.format(" <td><pre>%s</pre></td></tr>\n", rtn.text))
121 index:write(string.format(" <tr><td><img src='%s.png'></td></tr>\n", name))
123 index:write("</table>\n")
125 index:write("<h2><a name='lookahead'>Lookahead</a></h2>\n")
126 local gla_num = 1
127 for gla in each(glas) do
128 local dot_file = string.format("%s/gla-%d.dot", dir, gla_num)
129 local png_file = string.format("%s/gla-%d.png", dir, gla_num)
130 local png_file_no_dir = string.format("gla-%d.png", gla_num)
132 local gla_file = io.open(dot_file, "w")
133 gla_file:write("digraph untitled {\n")
134 gla_file:write(" rankdir=\"LR\";\n")
135 gla_file:write(gla:to_dot(" "))
136 gla_file:write("}\n")
137 gla_file:close()
138 os.execute(string.format("dot -Tpng -o %s %s", png_file, dot_file))
139 index:write(string.format("<h3><a name='gla_%d'>GLA %d</a></h3>", gla_num, gla_num))
140 index:write(string.format("<img src='%s'>", png_file_no_dir))
141 index:write("<br>\n")
142 gla_num = gla_num + 1
145 index:write("<h2><a name='lexing'>Lexing</a></h2>\n")
146 index:write(string.format("<p>The grammar's lexer has %d IntFAs, which follow:</p>", grammar.master_intfas:count()))
147 local intfa_num = 1
148 local have_imagemagick = os.execute("mogrify > /dev/null 2> /dev/null") == 0
149 for intfa in each(grammar.master_intfas) do
150 local dot_file = string.format("%s/intfa-%d.dot", dir, intfa_num)
151 local png_file = string.format("%s/intfa-%d.png", dir, intfa_num)
152 local png_file_no_dir = string.format("intfa-%d.png", intfa_num)
153 local png_thumb_file = string.format("%s/intfa-%d-thumb.png", dir, intfa_num)
154 local png_thumb_file_no_dir = string.format("intfa-%d-thumb.png", intfa_num)
156 local intfa_file = io.open(dot_file, "w")
157 intfa_file:write("digraph untitled {\n")
158 intfa_file:write(intfa:to_dot(" "))
159 intfa_file:write("}\n")
160 intfa_file:close()
161 os.execute(string.format("dot -Tpng -o %s %s", png_file, dot_file))
162 local w = 800
163 if have_imagemagick then
164 local img_info = io.popen(string.format("identify %s", png_file)):read("*a")
165 w, h = string.match(img_info, "[^ ]+ [^ ]+ (%d+)x(%d+)")
166 w = math.floor(w * 0.7)
167 h = math.floor(h * 0.7)
168 os.execute(string.format("convert %s -scale %dx%d %s", png_file, w, h, png_thumb_file))
169 else
170 os.execute(string.format("cp %s %s", png_file, png_thumb_file))
172 index:write(string.format("<h3><a name='intfa_%d'>IntFA %d</a></h3>", intfa_num, intfa_num))
173 index:write(string.format("<a href='%s'><img style='max-width: %dpx;' src='%s'></a>", png_file_no_dir, w, png_thumb_file_no_dir))
174 index:write("<br>\n")
175 intfa_num = intfa_num + 1
178 index:write("</body>\n")
179 index:write("</html>\n")