Add more flexibility in how whitespace is specified.
[gazelle.git] / tests / test_intfa.lua
blob62d43ccf745927c151df7f2690e66d5feb63d165
1 --[[--------------------------------------------------------------------
3 Gazelle: a system for building fast, reusable parsers
5 tests/test_intfa.lua
7 Routines that test the generation of IntFAs.
9 Copyright (c) 2008 Joshua Haberman. See LICENSE for details.
11 --------------------------------------------------------------------]]--
13 require "luaunit"
14 require "bootstrap/rtn"
15 require "regex_debug"
16 require "grammar"
17 require "ll"
19 function assert_intfas(grammar_str, ...)
20 local grammar = parse_grammar(CharStream:new(grammar_str))
21 grammar:assign_priorities()
22 grammar:determinize_rtns()
23 grammar:minimize_rtns()
24 compute_lookahead(grammar, k)
25 grammar:generate_intfas()
27 local intfa_strings = {...}
28 if #intfa_strings ~= grammar.master_intfas:count() then
29 error(string.format("Expected to get %d IntFAs but got %d instead",
30 #intfa_strings, #grammar.master_intfas))
31 end
33 for i, intfa_string in pairs(intfa_strings) do
34 local expected_intfa = parse_intfa(intfa_string)
35 local actual_intfa = grammar.master_intfas:element_at(i)
36 if not fa_isequal(expected_intfa, actual_intfa) then
37 local bad = io.open("bad.dot", "w")
38 bad:write("digraph untitled {\n")
39 bad:write(actual_intfa:to_dot(" "))
40 bad:write("}")
41 bad:close()
43 local good = io.open("good.dot", "w")
44 good:write("digraph untitled {\n")
45 good:write(expected_intfa:to_dot(" "))
46 good:write("}")
47 good:close()
49 os.execute("dot -Tpng -o good.png good.dot")
50 os.execute("dot -Tpng -o bad.png bad.dot")
52 error("GLAs were not equal: expected and actual are " ..
53 "in good.png and bad.png, respectively")
54 end
55 end
56 end
58 function parse_intfa(str)
59 local stream = CharStream:new(str)
60 stream:ignore("whitespace")
61 local intfa = fa.RTN:new()
62 local states = {[1]=intfa.start}
63 while not stream:eof() do
64 local statenum = tonumber(stream:consume_pattern("%d+"))
65 local state = states[statenum]
66 if not state then
67 error(string.format("IntFA refers to state %d before it is used as a target",
68 statenum))
69 end
70 while stream:lookahead(1) ~= ";" do
71 stream:consume("-")
72 local term = stream:consume_pattern("%w"):byte()
73 stream:consume("->")
74 local dest_state_num = tonumber(stream:consume_pattern("%d+"))
75 states[dest_state_num] = states[dest_state_num] or fa.IntFAState:new()
76 local dest_state = states[dest_state_num]
77 state:add_transition(term, dest_state)
78 if stream:lookahead(1) == "(" then
79 stream:consume("(")
80 dest_state.final = stream:consume_pattern("%w+")
81 stream:consume(")")
82 end
83 state = dest_state
84 end
85 stream:consume(";")
86 end
88 return intfa
89 end
91 TestSimple = {}
92 function TestSimple:test1()
93 assert_intfas(
95 s -> "X" "Y";
96 ]],
98 1 -X-> 2(X);
99 1 -Y-> 3(Y);
104 LuaUnit:run(unpack(arg))