def test_concat_merges_two_states_to_one(self): a_table = {0: [("char: a", 1)], 1: []} a_nfa = table_to_nfa(a_table, 0, 1) b_table = {2: [("char: b", 3)], 3: []} b_nfa = table_to_nfa(b_table, 2, 3) concat_graph = TC.concat(a_nfa, b_nfa) actual_table = nfa_to_table(concat_graph.start) expected_states = len(a_table.keys()) + len(b_table.keys()) - 1 self.assertEqual(len(actual_table.keys()), expected_states)
def test_concat_adds_single_epsilon(self): # state 2 is removed by concat, when it is merged with state 1 expected = {0: [("char: a", 1)], 1: [("char: b", 3)], 3: []} a_nfa = table_to_nfa({0: [("char: a", 1)], 1: []}, 0, 1) b_nfa = table_to_nfa({2: [("char: b", 3)], 3: []}, 2, 3) concat_graph = TC.concat(a_nfa, b_nfa) actual = nfa_to_table(concat_graph.start) self.assertEqual(expected, actual)
def test_union_adds_2_states(self): expected = { 0: [("char: a", 1)], 1: [("epsilon", 5)], 2: [("char: b", 3)], 3: [("epsilon", 5)], 4: [("epsilon", 0), ("epsilon", 2)], 5: [] } a_nfa = table_to_nfa({0: [("char: a", 1)], 1: []}, 0, 1) b_nfa = table_to_nfa({2: [("char: b", 3)], 3: []}, 2, 3) id_alloc = CounterStub(4) result_nfa = TC.union(a_nfa, b_nfa, id_alloc) result = nfa_to_table(result_nfa.start) self.assertEqual(expected, result)
def test_overlap_doesnt_affect_dfa_sim(self): # Table for: 'abc|bcde' table = { 14: [("epsilon", 0), ("epsilon", 6)], 6: [("char: b", 7)], 7: [("char: c", 9)], 9: [("char: d", 11)], 11: [("char: e", 13)], 13: [("epsilon", 15)], 15: [], 0: [("char: a", 1)], 1: [("char: b", 3)], 3: [("char: c", 5)], 5: [("epsilon", 15)] } nfa = table_to_nfa(table, 14, 15) runner = DFASimulator(nfa) runner.advance_state('a') match_end = runner.check_match() self.assertIsNone(match_end) self.assertListEqual( [iter.node.id for iter in runner.dfa.get_substates()], [1]) runner.advance_state('b') runner.advance_state('c') match_end = runner.check_match() self.assertEqual(match_end, 3) runner.advance_state('d') match_end = runner.check_match() self.assertIsNone(match_end)
def test_single_char_failure(self): # match agains the pattern: 'a' table = {0: [("char: a", 1)], 1: []} start_state = 0 end_state = 1 nfa = table_to_nfa(table, start_state, end_state) runner = DFASimulator(nfa) runner.advance_state('b') match = runner.check_match() self.assertIsNone(match)
def test_single_char_match(self): table = {0: [("char: a", 1)], 1: []} start_state = 0 end_state = 1 nfa = table_to_nfa(table, start_state, end_state) runner = DFASimulator(nfa) runner.advance_state('a') match_end = runner.check_match() self.assertEqual(match_end, 1)
def test_kstar(self): # represents : "a" nfa = table_to_nfa({0: [("char: a", 1)], 1: []}, 0, 1) expected = { 0: [("char: a", 1)], 1: [("epsilon", 0), ("epsilon", 3)], 2: [("epsilon", 0), ("epsilon", 3)], 3: [] } id_alloc = CounterStub(2) result_nfa = TC.kstar(nfa, id_alloc) actual = nfa_to_table(result_nfa.start) self.assertEqual(expected, actual)
def test(self): # The following table describes the pattern: 'a(b|c)' table1 = { 0: [("char: a", 1)], 1: [("epsilon", 6)], 6: [("epsilon", 2), ("epsilon", 4)], 4: [("char: c", 5)], 5: [("epsilon", 7)], 7: [], 2: [("char: b", 3)], 3: [("epsilon", 7)] } nfa = util.table_to_nfa(table1, 0, 7) table2 = util.nfa_to_table(nfa.start) self.assertEqual(table1, table2)