예제 #1
0
def test_chain_can_take_3_parsers_as_args(runner):
    p = chain(
        literal('a'),
        literal('b'),
        literal('c')
    )
    assert runner(p, 'abc').value == 'c'
예제 #2
0
def test_choice_throws_ParsingFailed_when_both_choices_fail(runner):
    p = choice(
        literal('a'),
        literal('b'),
    )
    with pytest.raises(ParsingFailed):
        runner(p, 'c')
예제 #3
0
def test_seperated_by_1000_elements(runner):
    assert runner(
        seperated_by(
            literal('a'),
            literal(',')
        ),
        'a' + ',a' * 999
    ).value == ['a'] * 1000
예제 #4
0
def test_seperated_by_one_element(runner):
    assert runner(
        seperated_by(
            literal('a'),
            literal(',')
        ),
        'a'
    ).value == ['a']
예제 #5
0
def test_enclosed_by(runner):
    assert runner(
        enclosed_by(
            literal('a'),
            literal('"')
        ),
        '"a"'
    ).value == 'a'
예제 #6
0
def test_seperated_by_five_elemts(runner):
    assert runner(
        seperated_by(
            literal('a'),
            literal(',')
        ),
        'a,a,a,a,a'
    ).value == ['a', 'a', 'a', 'a', 'a']
예제 #7
0
def test_seperated_by_empty(runner):
    assert runner(
        seperated_by(
            literal('a'),
            literal(',')
        ),
        ''
    ).value == []
예제 #8
0
def test_choices(runner):
    assert runner(
        choices(
            literal('a'),
            literal('b'),
            literal('c')
        ),
        'b'
    ).value == 'b'
예제 #9
0
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)
예제 #10
0
def test_we_can_chain_many_with_something_else(runner):
    p = many(
        literal('a')
    )
    p = bind(
        p,
        lambda _: literal('b'),
    )
    assert runner(p, 'aaaab').value == 'b'
예제 #11
0
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]
예제 #12
0
def test_bind_can_chain_3_literal_parsers(runner, a, b, c):
    p = literal(a)
    p = bind(
        p,
        lambda x: literal(b),
    )
    p = bind(
        p,
        lambda x: literal(c),
    )
    assert runner(p, a + b + c).value == c
예제 #13
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')
예제 #14
0
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'
예제 #15
0
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
예제 #16
0
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
예제 #17
0
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'
예제 #18
0
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]
예제 #19
0
def test_stack_performance_with_many_choices(
    benchmark,
    input_string,
    runner,
):
    parser = many(
        choices(
            literal('a'),
            literal('b'),
            literal('c'),
            literal('d'),
        ))
    benchmark(
        runner,
        parser,
        input_string,
    )
예제 #20
0
def test_that_fmap_does_not_change_error_messages(runner):
    parser = literal('a')
    with pytest.raises(ParsingFailed) as error_message_without_fmap:
        runner(parser, 'b')
    with pytest.raises(ParsingFailed) as error_message_with_fmap:
        runner(fmap(lambda char: char + 1, parser), 'b')
    assert (
        str(error_message_without_fmap.value) ==
        str(error_message_with_fmap.value)
    )
예제 #21
0
def test_simple_failing_parser_after_n_newlines_has_linenumber_n1_in_error(
        n,
        runner,
):
    p = chain(
        literal('\n' * n),
        fail('error')
    )
    with pytest.raises(ParsingFailed) as err:
        runner(p, ('\n' * n) + 'x')
    assert display_location(line=n + 1, column=0) in str(err.value)
예제 #22
0
from parsemon import ParsingFailed, literal, run_parser, until
from parsemon.stream import CharacterStream, StringStream


@pytest.fixture(params=(
    CharacterStream,
    StringStream,
))
def runner(request):
    def fixture(*args, **kwargs):
        return run_parser(*args, stream_implementation=request.param, **kwargs)

    return fixture


main_parser = literal('a')
delimiter = literal('b')


def test_until_failes_if_parser_fails_and_delimiter_parser_fails(runner):
    with pytest.raises(ParsingFailed):
        runner(until(main_parser, delimiter), 'not_matching_string')


def test_until_returns_empty_tuple_when_only_delimiter_is_found(runner):
    assert runner(until(main_parser, delimiter), 'b').value == tuple()


def test_until_consumes_the_delimiter(runner):
    parsing_result = runner(until(main_parser, delimiter), 'b')
    assert not parsing_result.remaining_input
예제 #23
0
 def wrapper(document):
     parser = unit(True)
     for character in document:
         parser = chain(parser, literal(character))
     return parser
예제 #24
0
 def parser():
     for letter in document:
         yield literal(letter)
     return True
예제 #25
0
def test_failure_of_literal_contains_expected_string():
    p = literal('abcde')
    with pytest.raises(ParsingFailed) as err:
        run_parser(p, 'xxxxx')
    assert 'abcde' in str(err.value)
예제 #26
0
def test_literal_parser_throws_ParsingFailed_when_seeing_non_matching_string(
        runner
):
    with pytest.raises(ParsingFailed):
        runner(literal('a'), 'b')
예제 #27
0
def test_bind_can_chain_two_literal_parsers(runner, a, b):
    parser = bind(
        literal(a),
        lambda x: literal(b),
    )
    assert runner(parser, a + b).value == b
예제 #28
0
def test_that_or_operator_works_as_expected(runner):
    assert runner(whitespace | literal('a'), ' ').value == ' '
    assert runner(whitespace | literal('a'), 'a').value == 'a'
예제 #29
0
def test_fmap_can_map_1000_times(runner):
    parser = literal('a')
    for i in range(0, 1000):
        parser = fmap(lambda x: 'b', parser)
    assert runner(parser, 'a').value == 'b'
예제 #30
0
def test_fmap_can_replace_parsing_result(runner):
    parser = fmap(
        lambda x: 'b',
        literal('a')
    )
    assert runner(parser, 'a').value == 'b'