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
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")
23 index
:write("<li><a href='#rules'>Rules</a></li>\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
))
28 index
:write("</ul>\n")
29 index
:write("<li><a href='#lookahead'>Lookahead</a></li>\n")
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
))
36 index
:write("</ul>\n")
37 index
:write("<li><a href='#lexing'>Lexing</a></li>\n")
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
44 index
:write("</ul>\n")
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()
53 for name
, rtn
in each(grammar
.rtns
) do
54 for state
in each(rtn
:states()) do
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
62 if state
:num_transitions() == 1 then
67 no_gla_breakdown
[lookahead
] = no_gla_breakdown
[lookahead
] or 0
68 no_gla_breakdown
[lookahead
] = no_gla_breakdown
[lookahead
] + 1
70 lookaheads
:add(lookahead
)
74 lookaheads
= lookaheads
:to_array()
75 table.sort(lookaheads
)
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
))
85 for lookahead
in each(lookaheads
) do
86 if with_gla_breakdown
[lookahead
] then
88 if lookahead
== 1 then
90 elseif lookahead
== 2 then
96 if lookahead
== math
.huge
then
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
))
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")
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")
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")
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()))
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")
161 os
.execute(string.format("dot -Tpng -o %s %s", png_file
, dot_file
))
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
))
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")