def test_edge_traversal_order(self): machine = StateMachine(states=[ State(START_STATE, Edge('', 'a')), State('a', [Edge('a', 'a'), Edge('', FINAL_STATE)]), State(FINAL_STATE) ]) start_record = gen_test_state_record(START_STATE, 0, 0) a_record = gen_test_state_record('a', 0, 0) end_record = gen_test_state_record(FINAL_STATE, 0, 0) state_records = [start_record, a_record] result = (True, state_records, 0) self.assertEqual(machine.accepts_partial('aab'), result) start_record = gen_test_state_record(START_STATE, 0, 0) a_record = gen_test_state_record('a', 0, 1) a_record_2 = gen_test_state_record('a', 1, 1) state_records = [start_record, a_record, a_record_2] result = (True, state_records, 1) self.assertEqual(machine.accepts_partial('aab'), result) start_record = gen_test_state_record(START_STATE, 0, 0) a_record = gen_test_state_record('a', 0, 1) a_record_2 = gen_test_state_record('a', 1, 2) a_record_3 = gen_test_state_record('a', 2, 2) state_records = [start_record, a_record, a_record_2, a_record_3] result = (True, state_records, 2) self.assertEqual(machine.accepts_partial('aab'), result) self.assertEqual(machine.accepts_partial('aab'), (False, None, -1))
def test_sub_machines(self): machine = StateMachine(id_='a', states=[ State(START_STATE, Edge('', 'b')), State('b', Edge('a', FINAL_STATE), is_automata=True), State(FINAL_STATE, Edge('', START_STATE)) ]) submachine_b = StateMachine(id_='b', states=[ State(START_STATE, Edge('b', FINAL_STATE)), State(FINAL_STATE, Edge('', START_STATE)) ]) machine.register_automata(submachine_b) start_record = StateRecord('a', START_STATE, 0, 0) nested_start_record = StateRecord('b', START_STATE, 0, 1) submachine_record = StateRecord('a', 'b_internal', 0, 1, [nested_start_record]) b_record = StateRecord('a', 'b', 1, 2) state_records = [start_record, submachine_record, b_record] result = (True, state_records, 2) self.assertEqual(machine.accepts_partial('ba'), result)
def test_continuation_works(self): machine = StateMachine(states=[ State(START_STATE, Edge('a', FINAL_STATE)), State(FINAL_STATE, Edge('', START_STATE)) ]) start_record = gen_test_state_record(START_STATE, 0, 1) state_records = [start_record] result = (True, state_records, 1) self.assertEqual(machine.accepts_partial('aaa'), result) end_record = gen_test_state_record(FINAL_STATE, 1, 1) start_record = gen_test_state_record(START_STATE, 0, 1) start_record2 = gen_test_state_record(START_STATE, 1, 2) state_records = [start_record, end_record, start_record2] result = (True, state_records, 2) self.assertEqual(machine.accepts_partial('aaa'), result) start_record = gen_test_state_record(START_STATE, 0, 1) end_record = gen_test_state_record(FINAL_STATE, 1, 1) start_record2 = gen_test_state_record(START_STATE, 1, 2) end_record2 = gen_test_state_record(FINAL_STATE, 2, 2) start_record3 = gen_test_state_record(START_STATE, 2, 3) state_records = [ start_record, end_record, start_record2, end_record2, start_record3 ] result = (True, state_records, 3) self.assertEqual(machine.accepts_partial('aaa'), result) self.assertEqual(machine.accepts_partial('aaa'), (False, None, -1))
def test_continuation_with_internal_repetition(self): machine = StateMachine(states=[ State(START_STATE, Edge('', 'a')), State('a', [Edge('a', 'a'), Edge('', FINAL_STATE)]), State(FINAL_STATE) ]) start_record = gen_test_state_record(START_STATE, 0, 0) a_record = gen_test_state_record('a', 0, 0) state_records = [start_record, a_record] result = (True, state_records, 0) self.assertEqual(machine.accepts_partial('aab'), result) start_record = gen_test_state_record(START_STATE, 0, 0) a_record = gen_test_state_record('a', 0, 1) a_record_2 = gen_test_state_record('a', 1, 1) state_records = [start_record, a_record, a_record_2] result = (True, state_records, 1) self.assertEqual(machine.accepts_partial('aab'), result) start_record = gen_test_state_record(START_STATE, 0, 0) a_record = gen_test_state_record('a', 0, 1) a_record_2 = gen_test_state_record('a', 1, 2) a_record_3 = gen_test_state_record('a', 2, 2) state_records = [start_record, a_record, a_record_2, a_record_3] result = (True, state_records, 2) self.assertEqual(machine.accepts_partial('aab'), result) self.assertEqual(machine.accepts_partial('aab'), (False, None, -1))
def test_trivial_case(self): grammar = 'rulename = abc "def"\nabc = "abc"' rulename = 'rulename' edge = Edge('abc', 'abc') edge2 = Edge('def', 'def') final_edge = Edge('', FINAL_STATE) state = State('abc', edge2, is_automata=True) state2 = State('def', final_edge) start_state = State(START_STATE, edge) final_state = State(FINAL_STATE) states = [start_state, state, state2, final_state] expected = StateMachine(rulename, states) rulename = 'abc' sub_edge = Edge('abc', 'abc') sub_final_edge = Edge('', FINAL_STATE) sub_state = State('abc', sub_final_edge) sub_start_state = State(START_STATE, sub_edge) sub_final_state = State(FINAL_STATE) states = [sub_start_state, sub_state, sub_final_state] submachine = StateMachine(rulename, states) expected.register_automata(submachine) actual = choices_parser.parse_from_string(grammar) logger.debug(f'Actual: {actual}') logger.debug(f'Expected: {expected}') assert_state_machines_equal(actual, expected)
def test_N_plus_repetition(self): in_edge = Edge('a', 'state_a') in_state = State('state_a') edge = Edge('a', 'state_a') edge2 = Edge('a', 'state_a_2') edge3 = Edge('a', 'state_a_3') edge3e = Edge('', 'state_a_3') state = State('state_a', [edge2]) state2 = State('state_a_2', [edge3]) state3 = State('state_a_3', [edge3]) in_edges = [in_edge] new_end_states = [in_state] new_states = [in_state] repetition = (3, float('inf')) is_optional = False in_edges_out = [edge] new_end_states_out = [state3] new_states_out = [state, state2, state3] expected = [in_edges_out, new_end_states_out, new_states_out] actual = repetition_applicator.apply_repetition( in_edges, new_end_states, new_states, repetition, is_optional) logger.debug( f'Actual result:\nin_edges: {actual[0]}\nnew_end_states: {actual[1]}\nnew_states: {actual[2]}' ) logger.debug(f'start_edges') self.assertTrue(edges_equal(actual[0], expected[0])) logger.debug(f'end_states') assert_states_equal(actual[1], expected[1]) logger.debug(f'states') assert_states_equal(actual[2], expected[2])
def test_no_repetition(self): edge_a = Edge('a', 'state_a') edge_b = Edge('b', 'state_b') state_a = State('state_a') state_b = State('state_b') edge_out_a = Edge('a', 'state_a') edge_out_b = Edge('b', 'state_b') state_out_a = State('state_a') state_out_b = State('state_b') in_edges = [edge_a, edge_b] new_end_states = [state_a, state_b] new_states = [state_a, state_b] repetition = None is_optional = False in_edges_out = [edge_out_a, edge_out_b] new_end_states_out = [state_out_a, state_out_b] new_states_out = [state_out_a, state_out_b] expected = [in_edges_out, new_end_states_out, new_states_out] actual = repetition_applicator.apply_repetition( in_edges, new_end_states, new_states, repetition, is_optional) logger.debug( f'Actual result:\nin_edges: {actual[0]}\nnew_end_states: {actual[1]}\nnew_states: {actual[2]}' ) logger.debug(f'start_edges') self.assertTrue(edges_equal(actual[0], expected[0])) logger.debug(f'end_states') assert_states_equal(actual[1], expected[1]) logger.debug(f'states') assert_states_equal(actual[2], expected[2])
def test_N_repetition(self): edge = Edge('a', 'state_a') state = State('state_a') edge_out = Edge('a', 'state_a') edge_2_out = Edge('a', 'state_a_2') state_out = State('state_a', [edge_2_out]) state_2_out = State('state_a_2') in_edges = [edge] new_end_states = [state] new_states = [state] repetition = (2, 2) is_optional = False in_edges_out = [edge_out] new_end_states_out = [state_2_out] new_states_out = [state_out, state_2_out] expected = [in_edges_out, new_end_states_out, new_states_out] actual = repetition_applicator.apply_repetition( in_edges, new_end_states, new_states, repetition, is_optional) logger.debug( f'Actual result:\nin_edges: {actual[0]}\nnew_end_states: {actual[1]}\nnew_states: {actual[2]}' ) logger.debug(f'start_edges') self.assertTrue(edges_equal(actual[0], expected[0])) logger.debug(f'end_states') assert_states_equal(actual[1], expected[1]) logger.debug(f'states') assert_states_equal(actual[2], expected[2])
def test_accepts_repeated_symbols(self): machine = StateMachine(states=[ State(START_STATE, Edge('a', FINAL_STATE)), State(FINAL_STATE, Edge('', START_STATE)) ]) self.assertTrue(machine.accepts('a')[0]) machine.reset() self.assertTrue(machine.accepts('aa')[0]) machine.reset() self.assertTrue(machine.accepts('aaa')[0])
def test_accepts_both_optional_paths(self): machine = StateMachine(states=[ State(START_STATE, [Edge('a', 'b'), Edge('a', 'c')]), State('b', Edge('b', FINAL_STATE)), State('c', Edge('c', FINAL_STATE)), State(FINAL_STATE) ]) self.assertTrue(machine.accepts('ab')[0]) machine.reset() self.assertTrue(machine.accepts('ac')[0])
def test_parenthized_alternative_repeated_alternative_tokens_case(self): rulename = 'rulename' elements = 'abc / 2*("def" / "ghi")' edge = Edge('abc', 'abc') edge2 = Edge('def', 'def') edge3 = Edge('ghi', 'ghi') edge2_2 = Edge('def', 'def_2') edge3_2 = Edge('ghi', 'ghi_2') edge2_2 = Edge('def', 'def_2') edge2_e = Edge('def', 'def_2') edge3_2 = Edge('ghi', 'ghi_2') final_edge = Edge('', FINAL_STATE) state = State('abc', final_edge, is_automata=True) state2 = State('def', [edge2_2, edge3_2]) state3 = State('ghi', [edge2_2, edge3_2]) state2_2 = State('def_2', [edge2_2, edge3_2, final_edge]) state3_2 = State('ghi_2', [edge2_2, edge3_2, final_edge]) start_state = State(START_STATE, [edge, edge2, edge3]) final_state = State(FINAL_STATE) states = [ start_state, state, state2, state3, state2_2, state3_2, final_state ] expected = StateMachine(rulename, states) actual = choices_parser.parse_elements(rulename, elements) assert_state_machines_equal(actual, expected)
def test_N_minus_repetition(self): edge_a = Edge('a', 'state_a') edge_b = Edge('b', 'state_b') state_a = State('state_a') state_b = State('state_b') edge_out_a = Edge('a', 'state_a') edge_out_b = Edge('b', 'state_b') edge_out_a_2 = Edge('a', 'state_a_2') edge_out_b_2 = Edge('b', 'state_b_2') edge_out_a_3 = Edge('a', 'state_a_3') edge_out_a_3_e = Edge('', 'state_a_3') edge_out_b_3 = Edge('b', 'state_b_3') edge_out_b_3_e = Edge('', 'state_b_3') state_out_a = State( 'state_a', [edge_out_a_2, edge_out_b_2, edge_out_a_3_e, edge_out_b_3_e]) state_out_b = State( 'state_b', [edge_out_a_2, edge_out_b_2, edge_out_a_3_e, edge_out_b_3_e]) state_out_a_2 = State( 'state_a_2', [edge_out_a_3, edge_out_b_3, edge_out_a_3_e, edge_out_b_3_e]) state_out_b_2 = State( 'state_b_2', [edge_out_a_3, edge_out_b_3, edge_out_a_3_e, edge_out_b_3_e]) state_out_a_3 = State('state_a_3') state_out_b_3 = State('state_b_3') in_edges = [edge_a, edge_b] new_end_states = [state_a, state_b] new_states = [state_a, state_b] repetition = (0, 3) is_optional = False in_edges_out = [edge_out_a, edge_out_b, edge_out_a_3_e, edge_out_b_3_e] new_end_states_out = [state_out_a_3, state_out_b_3] new_states_out = [ state_out_a, state_out_b, state_out_a_2, state_out_b_2, state_out_a_3, state_out_b_3 ] expected = [in_edges_out, new_end_states_out, new_states_out] actual = repetition_applicator.apply_repetition( in_edges, new_end_states, new_states, repetition, is_optional) logger.debug( f'Actual result:\nin_edges: {actual[0]}\nnew_end_states: {actual[1]}\nnew_states: {actual[2]}' ) logger.debug(f'start_edges') self.assertTrue(edges_equal(actual[0], expected[0])) logger.debug(f'end_states') assert_states_equal(actual[1], expected[1]) logger.debug(f'states') assert_states_equal(actual[2], expected[2])
def test_accepts_repeated_alpha(self): machine = StateMachine(states=[ State(START_STATE, Edge('ALPHA', FINAL_STATE, True)), State(FINAL_STATE, Edge('', START_STATE)) ]) self.assertTrue(machine.accepts('a')[0]) machine.reset() self.assertTrue(machine.accepts('ab')[0]) machine.reset() self.assertTrue(machine.accepts('abc')[0]) machine.reset() self.assertFalse(machine.accepts('a2c')[0])
def test_accepts_repeated_digit(self): machine = StateMachine(states=[ State(START_STATE, Edge('DIGIT', FINAL_STATE, True)), State(FINAL_STATE, Edge('', START_STATE)) ]) self.assertTrue(machine.accepts('1')[0]) machine.reset() self.assertTrue(machine.accepts('12')[0]) machine.reset() self.assertTrue(machine.accepts('123')[0]) machine.reset() self.assertFalse(machine.accepts('1a3')[0])
def test_accepts_optional_symbols(self): machine = StateMachine(states=[ State(START_STATE, [Edge('a', FINAL_STATE), Edge('a', 'b')]), State('b', Edge('b', FINAL_STATE)), State(FINAL_STATE) ]) self.assertTrue(machine.accepts('a')[0]) machine.reset() self.assertTrue(machine.accepts('ab')[0]) machine.reset() self.assertFalse(machine.accepts('b')[0])
def test_trivial_case(self): rulename = 'rulename' elements = 'abc' edge = Edge('abc', 'abc') final_edge = Edge('', FINAL_STATE) state = State('abc', final_edge, is_automata=True) start_state = State(START_STATE, edge) final_state = State(FINAL_STATE) states = [start_state, state, final_state] expected = StateMachine(rulename, states) actual = choices_parser.parse_elements(rulename, elements) assert_state_machines_equal(actual, expected)
def test_parenthized_alternative_repeated_alternative_tokens_case(self): elements = ['abc', '/', ['2*', ['"def"', '/', '"ghi"']]] edge = Edge('abc', 'abc') edge2 = Edge('def', 'def') edge3 = Edge('ghi', 'ghi') edge2_2 = Edge('def', 'def_2') edge3_2 = Edge('ghi', 'ghi_2') edge2_2 = Edge('def', 'def_2') edge2_e = Edge('def', 'def_2') edge3_2 = Edge('ghi', 'ghi_2') state = State('abc', is_automata=True) state2 = State('def', [edge2_2, edge3_2]) state3 = State('ghi', [edge2_2, edge3_2]) state2_2 = State('def_2', [edge2_2, edge3_2]) state3_2 = State('ghi_2', [edge2_2, edge3_2]) start_edges = [edge, edge2, edge3] end_states = [state, state2_2, state3_2] states = [state, state2, state3, state2_2, state3_2] expected = (start_edges, end_states, states) actual = choices_parser.recursive_parse_elements(elements) logger.debug( f'Actual result:\nin_edges: {actual[0]}\nnew_end_states: {actual[1]}\nnew_states: {actual[2]}' ) logger.debug(f'start_edges') self.assertTrue(edges_equal(actual[0], expected[0])) logger.debug(f'end_states') assert_states_equal(actual[1], expected[1]) logger.debug(f'states') assert_states_equal(actual[2], expected[2])
def test_accepts_N_star_repeated_symbols(self): machine = StateMachine(states=[ State(START_STATE, Edge('a', 'a1')), State('a1', Edge('a', 'a2')), State('a2', [Edge('a', FINAL_STATE), Edge('a', 'a2')]), State(FINAL_STATE), ]) self.assertFalse(machine.accepts('a')[0]) machine.reset() self.assertFalse(machine.accepts('aa')[0]) machine.reset() self.assertTrue(machine.accepts('aaa')[0]) machine.reset() self.assertTrue(machine.accepts('aaaa')[0])
def test_two_alternative_tokens_case(self): rulename = 'rulename' elements = 'abc / "def"' edge = Edge('abc', 'abc') edge2 = Edge('def', 'def') final_edge = Edge('', FINAL_STATE) state = State('abc', final_edge, is_automata=True) state2 = State('def', final_edge) start_state = State(START_STATE, [edge, edge2]) final_state = State(FINAL_STATE) states = [start_state, state, state2, final_state] expected = StateMachine(rulename, states) actual = choices_parser.parse_elements(rulename, elements) assert_state_machines_equal(actual, expected)
def test_identical_parenthetized_token_case(self): rulename = 'rulename' elements = 'abc (abc)' edge = Edge('abc', 'abc') edge2 = Edge('abc', 'abc_#2') final_edge = Edge('', FINAL_STATE) state = State('abc', edge2, is_automata=True) state2 = State('abc_#2', final_edge, is_automata=True) start_state = State(START_STATE, edge) final_state = State(FINAL_STATE) states = [start_state, state, state2, final_state] expected = StateMachine(rulename, states) actual = choices_parser.parse_elements(rulename, elements) assert_state_machines_equal(actual, expected)
def test_clone(self): original_state = State( 'a', [Edge('a', 'a_state'), Edge('b', 'b_state')], is_automata=True) cloned_state = original_state.clone() self.assertTrue(cloned_state.id == 'a') self.assertTrue(cloned_state.is_automata == True) self.assertTrue(cloned_state.edges[0].input == 'a') self.assertTrue(cloned_state.edges[0].dest == 'a_state') self.assertTrue(cloned_state.edges[1].input == 'b') self.assertTrue(cloned_state.edges[1].dest == 'b_state') cloned_state.edges[0].input = 'aaaaaaaaaaaaaaa' self.assertTrue(original_state.edges[0].input == 'a')
def test_starting_parenthized_tokens_case(self): rulename = 'rulename' elements = '(abc "def") "ghi"' edge = Edge('abc', 'abc') edge2 = Edge('def', 'def') edge3 = Edge('ghi', 'ghi') final_edge = Edge('', FINAL_STATE) state = State('abc', edge2, is_automata=True) state2 = State('def', edge3) state3 = State('ghi', final_edge) start_state = State(START_STATE, edge) final_state = State(FINAL_STATE) states = [start_state, state, state2, state3, final_state] expected = StateMachine(rulename, states) actual = choices_parser.parse_elements(rulename, elements) assert_state_machines_equal(actual, expected)
def test_N_repeated_token_case(self): rulename = 'rulename' elements = 'abc 2"def"' edge = Edge('abc', 'abc') edge2 = Edge('def', 'def') edge2_2 = Edge('def', 'def_2') final_edge = Edge('', FINAL_STATE) state = State('abc', edge2, is_automata=True) state2 = State('def', edge2_2) state2_2 = State('def_2', final_edge) start_state = State(START_STATE, edge) final_state = State(FINAL_STATE) states = [start_state, state, state2, state2_2, final_state] expected = StateMachine(rulename, states) actual = choices_parser.parse_elements(rulename, elements) assert_state_machines_equal(actual, expected)
def test_accepts_repeated_char(self): machine = StateMachine(states=[ State(START_STATE, Edge('CHAR', FINAL_STATE, True)), State(FINAL_STATE, Edge('', START_STATE)) ]) self.assertTrue(machine.accepts('a')[0]) machine.reset() self.assertTrue(machine.accepts('ab')[0]) machine.reset() self.assertTrue(machine.accepts('abc')[0]) machine.reset() self.assertTrue(machine.accepts('1')[0]) machine.reset() self.assertTrue(machine.accepts('12')[0]) machine.reset() self.assertTrue(machine.accepts('123')[0]) machine.reset() self.assertTrue(machine.accepts('1a3')[0]) machine.reset() self.assertTrue(machine.accepts('a2c')[0])
def test_trivial_case(self): elements = ['abc'] edge = Edge('abc', 'abc') state = State('abc', is_automata=True) start_edges = [edge] end_states = [state] states = [state] expected = (start_edges, end_states, states) actual = choices_parser.recursive_parse_elements(elements) self.assertTrue(edges_equal(actual[0], expected[0])) assert_states_equal(actual[1], expected[1]) assert_states_equal(actual[2], expected[2])
def test_two_alternative_tokens_case(self): elements = ['abc', '/', '"def"'] edge = Edge('abc', 'abc') edge2 = Edge('def', 'def') state = State('abc', is_automata=True) state2 = State('def') start_edges = [edge, edge2] end_states = [state, state2] states = [state, state2] expected = (start_edges, end_states, states) actual = choices_parser.recursive_parse_elements(elements) logger.debug( f'Actual result:\nin_edges: {actual[0]}\nnew_end_states: {actual[1]}\nnew_states: {actual[2]}' ) logger.debug(f'start_edges') self.assertTrue(edges_equal(actual[0], expected[0])) logger.debug(f'end_states') assert_states_equal(actual[1], expected[1]) logger.debug(f'states') assert_states_equal(actual[2], expected[2])
def test_identical_parenthetized_token_case(self): elements = ['abc', ['abc']] edge = Edge('abc', 'abc') edge2 = Edge('abc', 'abc_#2') state = State('abc', edge2, is_automata=True) state2 = State('abc_#2', is_automata=True) start_edges = [edge] end_states = [state2] states = [state, state2] expected = (start_edges, end_states, states) actual = choices_parser.recursive_parse_elements(elements) logger.debug( f'Actual result:\nin_edges: {actual[0]}\nnew_end_states: {actual[1]}\nnew_states: {actual[2]}' ) logger.debug(f'start_edges') self.assertTrue(edges_equal(actual[0], expected[0])) logger.debug(f'end_states') assert_states_equal(actual[1], expected[1]) logger.debug(f'states') assert_states_equal(actual[2], expected[2])
def test_double_nested_sub_machines(self): machine = StateMachine(id_='c', states=[ State(START_STATE, Edge('', 'b')), State('b', Edge('c', FINAL_STATE), is_automata=True), State(FINAL_STATE) ]) submachine_b = StateMachine(id_='b', states=[ State(START_STATE, Edge('', 'a')), State('a', Edge('b', FINAL_STATE), is_automata=True), State(FINAL_STATE) ]) submachine_a = StateMachine(id_='a', states=[ State(START_STATE, Edge('a', FINAL_STATE)), State(FINAL_STATE) ]) submachine_b.register_automata(submachine_a) machine.register_automata(submachine_b) start_record = StateRecord('c', START_STATE, 0, 0) b_start_record = StateRecord('b', START_STATE, 0, 0) a_record = StateRecord('a', START_STATE, 0, 1) b_machine_record = StateRecord('b', 'a_internal', 0, 1, [a_record]) b_record = StateRecord('b', 'a', 1, 2) c_machine_record = StateRecord( 'c', 'b_internal', 0, 2, [b_start_record, b_machine_record, b_record]) c_record = StateRecord('c', 'b', 2, 3) state_records = [start_record, c_machine_record, c_record] result = (True, state_records, 3) self.assertEqual(machine.accepts_partial('abc'), result)
def test_accepts_single_digit(self): machine = StateMachine(states=[ State(START_STATE, Edge('DIGIT', FINAL_STATE, True)), State(FINAL_STATE) ]) self.assertTrue(machine.accepts('1')[0]) machine.reset() self.assertTrue(machine.accepts('2')[0]) machine.reset() self.assertTrue(machine.accepts('3')[0]) machine.reset() self.assertFalse(machine.accepts('A')[0]) machine.reset() self.assertFalse(machine.accepts('a')[0])
def test_accepts_single_alpha(self): machine = StateMachine(states=[ State(START_STATE, Edge('ALPHA', FINAL_STATE, True)), State(FINAL_STATE) ]) self.assertTrue(machine.accepts('a')[0]) machine.reset() self.assertTrue(machine.accepts('A')[0]) machine.reset() self.assertTrue(machine.accepts('z')[0]) machine.reset() self.assertTrue(machine.accepts('Z')[0]) machine.reset() self.assertFalse(machine.accepts('0')[0])