2 --dofile("sketches/pp.lua")
4 -- function NFA:dump_dot()
5 -- local str = "digraph untitled {\n"
7 -- local queue = {self.start}
8 -- local next_statenum = 2
9 -- seen[self.start] = 1
10 -- while table.getn(queue) > 0 do
11 -- state = table.remove(queue)
12 -- for char,newstates in pairs(state) do
13 -- if newstates.class == NFAState then newstates = {newstates} end
15 -- for i,newstate in ipairs(newstates) do
17 -- -- if we haven't seen this state before, queue it up
18 -- if seen[newstate] == nil then
19 -- table.insert(queue, newstate)
20 -- seen[newstate] = next_statenum
21 -- next_statenum = next_statenum + 1
24 -- str = str .. string.format(' %d -> %d [label="%s"];\n', seen[state], seen[newstate], char)
28 -- str = str .. string.format(' %d [label="Start"]\n', seen[self.start])
29 -- str = str .. string.format(" %d [peripheries=2]\n", seen[self.final])
36 function fa
.FA
:__tostring()
37 -- local oldmt = getmetatable(self)
38 -- setmetatable(self, nil)
39 -- print("BTW my identity is " .. tostring(self))
40 -- setmetatable(self, oldmt)
41 local str
= "digraph untitled {\n"
42 states
= self
:states():to_array()
43 --table.sort(states, function (a, b) return a.statenum < b.statenum end)
44 for i
,state
in ipairs(states
) do
47 if state
== self
.start
then label
= "Begin" end
48 if state
== self
.final
or state
.final
then
49 if label
~= "" then label
= label
.. "/" end
51 if type(state
.final
) == "table" then
53 print(serialize(state
.final
:to_array()))
54 label
= label
.. str_join(state
.final
:to_array(), "NEWLINE")
56 label
= label
.. state
.final
59 label
= label
.. "Final"
63 if state
.decisions
then
64 for terminal
, stack
in pairs(state
.decisions
) do
65 label
= label
.. "NEWLINE" .. terminal
.. "->"
66 if stack
== Ignore
then
67 label
= label
.. "IGNORE"
69 for stack_member
in each(stack
) do
70 if type(stack_member
) == "table" and stack_member
.class
== fa
.NonTerm
then
71 label
= label
.. stack_member
.name
72 elseif type(stack_member
) == "table" and stack_member
.class
== Ignore
then
73 label
= label
.. "IGNORE"
75 label
= label
.. serialize(stack_member
)
82 label
= label
:gsub("[\"\\]", "\\%1")
83 label
= label
:gsub("NEWLINE", "\\n")
84 str
= str
.. string.format(' "%s" [label="%s", peripheries=%d];\n', tostring(state
), label
, peripheries
)
85 for char
, tostate
, attributes
in state
:transitions() do
89 -- elseif char == "(" then
90 -- print_char = "start capture"
91 -- elseif char == ")" then
92 -- print_char = "end capture"
93 elseif type(char
) == "string" then
95 elseif type(char
) == 'table' and char
.class
== IntSet
then
96 if char
:isunbounded() then char
= char
:invert() end
97 print_char
= char
:toasciistring()
98 elseif type(char
) == 'table' and char
.class
== fa
.NonTerm
then
99 print_char
= char
.name
100 elseif type(char
) == 'table' and char
.class
== fa
.IntFA
then
101 print_char
= "A regex!"
103 print(serialize(char
, 3, true))
104 print_char
= string.char(char
)
106 if attributes
and false then
107 for k
,v
in pairs(attributes
) do
109 local s
= tostring(v
)
110 if type(v
) == "table" then
113 print_char
= print_char
.. string.format("NEWLINE%s: %s", k
, s
)
117 print_char
= print_char
:gsub("[\"\\]", "\\%1")
118 print_char
= print_char
:gsub("NEWLINE", "\\n")
119 str
= str
.. string.format(' "%s" -> "%s" [label="%s"];\n', tostring(state
), tostring(tostate
), print_char
)
126 fa
.IntFA
.__tostring
= fa
.FA
.__tostring
127 fa
.RTN
.__tostring
= fa
.FA
.__tostring