def test_literal_choice_can_parse_both_possibilities(runner, a, b): # we must order the two strings because of the possibility that a # can be a prefix of b or the other way around p = choice( try_parser(literal(a)), literal(b), ) if len(a) > len(b) else choice( try_parser(literal(b)), literal(a), ) assert runner(p, a).value == a assert runner(p, b).value == b
def test_failure_of_choice_of_3_literals_should_contain_all_3_literal(): p = choice( literal('first'), choice( literal('second'), literal('third') ) ) with pytest.raises(ParsingFailed) as err: run_parser(p, 'xxxxxxxxxxxxxxxx') error_message = str(err.value) assert 'first' in error_message assert 'second' in error_message assert 'third' in error_message
def test_that_error_message_order_is_preserved_with_3_choices(): p = choice( literal('first'), choice( literal('second'), literal('third'), ) ) with pytest.raises(ParsingFailed) as err: run_parser(p, 'xxxxxxxxxxxxxx') error_message = str(err.value) assert 'second' in error_message.split('first')[1] assert 'third' in error_message.split('first')[1] assert 'first' in error_message.split('second')[0] assert 'third' in error_message.split('second')[1]
def test_choice_throws_ParsingFailed_when_both_choices_fail(runner): p = choice( literal('a'), literal('b'), ) with pytest.raises(ParsingFailed): runner(p, 'c')
def test_failure_of_choice_of_2_literals_should_contain_both_literals(): p = choice( literal('first_literal'), literal('second_literal'), ) with pytest.raises(ParsingFailed) as err: run_parser(p, 'xxxxxxxxxxxxxxxxxxx') assert 'first_literal' in str(err.value) assert 'second_literal' in str(err.value)
def test_that_error_message_respects_ordering_of_failing_choices(): p = choice( literal('first'), literal('second'), ) with pytest.raises(ParsingFailed) as err: run_parser(p, 'xxxxxxxxxxxxxx') error_message = str(err.value) assert 'second' in error_message.split('first')[1] assert 'first' in error_message.split('second')[0]
def test_choice_should_not_retry_if_the_parser_after_choice_fails(runner): p = choice( literal('a'), # this should match the incomming input literal('aa'), ) p = chain( p, literal('b') ) with pytest.raises(ParsingFailed): runner(p, 'aab')
def test_choice_can_be_chained_1000_times(runner): c = choice( literal('a'), literal('b'), ) p = unit('') for i in range(0, 1000): p = bind( p, lambda x: c, ) assert runner(p, 'a' * 999 + 'b').value == 'b'
def test_if_a_choice_failes_in_the_middle_of_chain_it_retries_other_option( runner ): p = choice( try_parser(chain( literal('a'), literal('a') )), chain( literal('a'), literal('b'), ) ) assert runner(p, 'ab').value == 'b'