Пример #1
0
def or_else(*parsers, **kwargs):
    """
    Applies parsers one by one. At least one parsers must be successful to return Success
    """
    label = kwargs.get('label', None)
    if label is None:
        label = '[' + ''.join([p.label for p in parsers]) + ']'

    if len(parsers) == 1:
        return bp.LParser(parsers[0], label)

    if len(parsers) == 2:

        def internal(txt):
            res1 = parsers[0](txt)
            if res1.isSuccess:
                return res1

            res2 = parsers[1](txt)
            if res2.isSuccess:
                return res2

            return res.Failure('error')

        return bp.LParser(internal, label)

    parser_new = or_else(parsers[0], parsers[1])
    new_parsers = [parser_new] + list(parsers[2:])
    return or_else(*new_parsers, label=label)
Пример #2
0
def and_then(*parsers, **kwargs):
    """
    Applies parsers one by one. All parsers must be successful to return Success
    """
    label = kwargs.get('label', None)
    if label is None:
        label = ''.join([p.label for p in parsers])

    if len(parsers) == 1:
        return bp.LParser(parsers[0], label)

    if len(parsers) == 2:

        def internal(txt):
            res1 = parsers[0](txt)
            if res1.isFailure:
                return res1
            char1, remaining1 = res1.value

            res2 = parsers[1](remaining1)
            if isinstance(res2, res.Failure):
                return res2
            char2, remaining2 = res2.value

            return res.Success((char1 + char2, remaining2))

        return bp.LParser(internal, label)

    parser_new = and_then(parsers[0], parsers[1])
    new_parsers = [parser_new] + list(parsers[2:])
    return and_then(*new_parsers, label=label)
Пример #3
0
 def test_CorrectlyHandlesDifferentNumberOfArguments(self):
     # Arrange
     txt1 = 'lorem ipsum dolor sit amet'
     txt2 = 'ipsum dolor sit amet'
     txt3 = 'dolor sit amet'
     txt4 = 'sit amet'
     parser_l = bpr.LParser('l')
     parser_o = bpr.LParser('i')
     parser_r = bpr.LParser('d')
     parser_e = bpr.LParser('s')
     parser = cmb.or_else(parser_l, parser_o, parser_r, parser_e)
     # Act
     result1 = parser(txt1)
     result2 = parser(txt2)
     result3 = parser(txt3)
     result4 = parser(txt4)
     expected1 = res.Success(('l', 'orem ipsum dolor sit amet'))
     expected2 = res.Success(('i', 'psum dolor sit amet'))
     expected3 = res.Success(('d', 'olor sit amet'))
     expected4 = res.Success(('s', 'it amet'))
     # Assert
     self.assertEqual(result1, expected1)
     self.assertEqual(result2, expected2)
     self.assertEqual(result3, expected3)
     self.assertEqual(result4, expected4)
Пример #4
0
 def test_CorrectlyHandlesDifferentNumberOfArguments(self):
     # Arrange
     txt = 'aabbacccadd1234'
     parser_a = bpr.LParser('a')
     parser_b = bpr.LParser('b')
     parser_c = bpr.LParser('c')
     parser_d = bpr.LParser('d')
     # Act
     parser1 = cmb.many1(parser_a)
     parser2 = cmb.many1(parser_a, parser_b)
     parser3 = cmb.many1(parser_a, parser_b, parser_c)
     parser4 = cmb.many1(parser_a, parser_b, parser_c, parser_d)
     result1 = parser1(txt)
     result2 = parser2(txt)
     result3 = parser3(txt)
     result4 = parser4(txt)
     expected1 = res.Success(('aa', 'bbacccadd1234'))
     expected2 = res.Success(('aabba', 'cccadd1234'))
     expected3 = res.Success(('aabbaccca', 'dd1234'))
     expected4 = res.Success(('aabbacccadd', '1234'))
     # Assert
     self.assertEqual(result1, expected1)
     self.assertEqual(result2, expected2)
     self.assertEqual(result3, expected3)
     self.assertEqual(result4, expected4)
Пример #5
0
    def test_CorrectlyHandlesDifferentNumberOfArguments(self):
        # Arrange
        txt = 'lorem ipsum'
        parser_l = bpr.LParser('l')
        parser_o = bpr.LParser('o')
        parser_r = bpr.LParser('r')
        parser_e = bpr.LParser('e')

        parser1 = cmb.and_then(parser_l)
        parser2 = cmb.and_then(parser_l, parser_o)
        parser3 = cmb.and_then(parser_l, parser_o, parser_r)
        parser4 = cmb.and_then(parser_l, parser_o, parser_r, parser_e)
        # Act
        result1 = parser1(txt)
        result2 = parser2(txt)
        result3 = parser3(txt)
        result4 = parser4(txt)
        expected1 = res.Success(('l', 'orem ipsum'))
        expected2 = res.Success(('lo', 'rem ipsum'))
        expected3 = res.Success(('lor', 'em ipsum'))
        expected4 = res.Success(('lore', 'm ipsum'))
        # Assert
        self.assertEqual(result1, expected1)
        self.assertEqual(result2, expected2)
        self.assertEqual(result3, expected3)
        self.assertEqual(result4, expected4)
Пример #6
0
def parse_character(*chars, **kwargs):
    """
    returns parser that match one of the strings given
    """
    label = kwargs.get('label', None)
    if len(chars) == 1 and len(chars[0]) > 1:
        return cmb.or_else(*[bp.LParser(char) for char in chars[0]], label=label)
    return cmb.or_else(*[bp.LParser(char) for char in chars], label=label)
Пример #7
0
 def test_AddingLabel(self):
     # Arrange
     parser1 = bpr.LParser('l')
     parser2 = bpr.LParser('o')
     parser = cmb.rightparser(parser1, parser2, label='Parser: lor')
     parser_default_label = cmb.rightparser(parser1, parser2)
     # Assert
     self.assertEqual(parser.label, 'Parser: lor')
     self.assertEqual(parser_default_label.label, 'lo')
Пример #8
0
 def test_AddingLabel(self):
     # Arrange
     parser1 = bpr.LParser('x')
     parser2 = bpr.LParser(',')
     parser = cmb.sep_by1(parser1, parser2, label='Parser: lor')
     parser_default_label = cmb.sep_by1(parser1, parser2)
     # Assert
     self.assertEqual(parser.label, 'Parser: lor')
     self.assertEqual(parser_default_label.label, 'x[,x]+')
Пример #9
0
 def test_AddingLabel(self):
     # Arrange
     parser1 = bpr.LParser('l')
     parser2 = bpr.LParser('o')
     parser3 = bpr.LParser('r')
     parser = cmb.and_then(parser1, parser2, parser3, label='Parser: lor')
     parser_default_label = cmb.and_then(parser1, parser2, parser3)
     # Assert
     self.assertEqual(parser.label, 'Parser: lor')
     self.assertEqual(parser_default_label.label, 'lor')
Пример #10
0
def parse_float(label='FLOAT'):
    """
    returns parser for floating point number
    """
    sign = cmb.opt(bp.LParser('-'))
    coma = bp.LParser('.')
    e = cmb.or_else(bp.LParser('e'), bp.LParser('E'))
    exponent = cmb.opt(cmb.and_then(e, parse_integer()))
    integer = parse_integer()
    return cmb.and_then(sign, cmb.opt(integer), coma, parse_digits(), exponent, label=label)
Пример #11
0
 def test_NoMatch(self):
     # Arrange
     txt = 'aabbaccca1234'
     parser1 = bpr.LParser('x')
     parser2 = bpr.LParser('y')
     # Act
     parser = cmb.many(parser1, parser2)
     result = parser(txt)
     expected = res.Success(('', 'aabbaccca1234'))
     # Assert
     self.assertEqual(result, expected)
Пример #12
0
 def test_Failure(self):
     # Arrange
     txt = 'aabbaccca1234'
     parser1 = bpr.LParser('x')
     parser2 = bpr.LParser('y')
     # Act
     parser = cmb.many1(parser1, parser2)
     result = parser(txt)
     expected = res.Failure('error')
     # Assert
     self.assertEqual(result, expected)
Пример #13
0
 def test_CorrectlyHandlesDifferentNumberOfArguments_Failure(self):
     # Arrange
     txt = 'Lorem'
     parser_1 = bpr.LParser('1')
     parser_2 = bpr.LParser('2')
     parser_3 = bpr.LParser('3')
     parser = cmb.until(parser_1, parser_2, parser_3)
     # Act
     result = parser(txt)
     expected = res.Failure.unit('No more input')
     # Arrange
     self.assertEqual(result, expected)
Пример #14
0
 def test_SuccessCase(self):
     # Arrange
     txt = 'aabbaccca1234'
     parser1 = bpr.LParser('a')
     parser2 = bpr.LParser('b')
     parser3 = bpr.LParser('c')
     # Act
     parser = cmb.many1(parser1, parser2, parser3)
     result = parser(txt)
     expected = res.Success(('aabbaccca', '1234'))
     # Assert
     self.assertEqual(result, expected)
Пример #15
0
 def test_WhenFirstLettersAreIncorrect_ReturnFailure(self):
     # Arrange
     txt = 'lorem ipsum'
     parser1 = bpr.LParser('l')
     parser2 = bpr.LParser('x')
     parser3 = bpr.LParser('r')
     parser = cmb.and_then(parser1, parser2, parser3)
     # Act
     result = parser(txt)
     expected = res.Failure('error')
     # Assert
     self.assertEqual(result, expected)
Пример #16
0
 def test_WhenFirstLettersAreCorrect_ReturnSuccess(self):
     # Arrange
     txt = 'lorem ipsum'
     parser1 = bpr.LParser('l')
     parser2 = bpr.LParser('o')
     parser3 = bpr.LParser('r')
     parser = cmb.and_then(parser1, parser2, parser3)
     # Act
     result = parser(txt)
     expected = res.Success(('lor', 'em ipsum'))
     # Assert
     self.assertEqual(result, expected)
Пример #17
0
 def test_FailureCase(self):
     # Arrange
     txt = 'Lorem'
     parser1 = bpr.LParser('l')
     parser2 = bpr.LParser('x')
     parser3 = bpr.LParser('i')
     # Act
     parser = cmb.or_else(parser1, parser2, parser3)
     result = parser(txt)
     expected = res.Failure('error')
     # Assert
     self.assertEqual(result, expected)
Пример #18
0
 def test_ParserParseEverything_ReturnsSuccess(self):
     # Arrange
     txt = 'aabbaccca'
     parser_a = bpr.LParser('a')
     parser_b = bpr.LParser('b')
     parser_c = bpr.LParser('c')
     parser_d = bpr.LParser('d')
     # Act
     parser = cmb.many1(parser_a, parser_b, parser_c, parser_d)
     result = parser(txt)
     expected = res.Success(('aabbaccca', ''))
     # Assert
     self.assertEqual(result, expected)
Пример #19
0
def sep_by1(item, sep, **kwargs):
    """
    parses one or more occurrences of a parser with a separator
    """
    label = kwargs.get('label', None)
    if label is None:
        label = item.label + '[' + sep.label + item.label + ']+'

    sep_items = sep_by(item, sep)
    parser = and_then(item, sep, sep_items)

    def internal(txt):
        if txt == "":
            return res.Failure.unit('error')
        fst_res = item(txt)
        if fst_res.isFailure:
            return res.Failure('error')
        parsed, remaining = fst_res.value
        snd_res = sep(remaining)
        if snd_res.isFailure:
            return res.Success((parsed, remaining))

        result = parser(txt)
        if result.isSuccess:
            parsed, remaining = result.value
            return res.Success.unit((parsed, remaining))
        return res.Failure('error')

    return bp.LParser(internal, label)
Пример #20
0
def sep_by(item, sep, **kwargs):
    """
    parses zero or more occurrences of a parser with a separator
    """
    label = kwargs.get('label', None)
    if label is None:
        label = item.label + '[' + sep.label + item.label + ']+'

    sep_item = and_then(sep, item)
    sep_items = many(sep_item)

    def internal(txt):
        if txt == "":
            return res.Success.unit(('', ''))
        ret = ''
        fst_element = item(txt)
        if fst_element.isSuccess:
            parsed, remaining = fst_element.value
            rest_of_elements = sep_items(remaining)
            if rest_of_elements.isSuccess:
                parsed_rest, remaining = rest_of_elements.value
                return res.Success.unit((parsed + parsed_rest, remaining))
        return res.Failure('error')

    return bp.LParser(internal, label)
Пример #21
0
def betweenparsers(lparser, mparser, rparser, **kwargs):
    """
    Matches left parsers then mid one and finally right one, return result of middle parser
    """
    label = kwargs.get('label', None)
    if label is None:
        label = lparser.label + mparser.label + rparser.label

    def internal(txt):
        fst_result = lparser(txt)
        if fst_result.isFailure:
            return res.Failure.unit("error")
        _, remaining = fst_result.value
        snd_result = mparser(remaining)
        if snd_result.isFailure:
            return res.Failure.unit("error")
        parsed, remaining = snd_result.value
        trd_result = rparser(remaining)
        _, remaining = trd_result.value
        if trd_result.isFailure:
            return res.Failure.unit("error")

        return res.Success.unit((parsed, remaining))

    return bp.LParser(internal, label)
Пример #22
0
def until(*parsers, **kwargs):
    """
    matches zero or one occurrence of the specified parsers.
    """
    parser = or_else(*parsers)
    label = kwargs.get('label', None)
    if label is None:
        label = '(.*?)[' + ''.join([p.label for p in parsers]) + ']'

    def internal(input_txt):
        ret = ""
        txt = input_txt
        anyp = parse_any()
        checker = parser(txt)
        while checker.isFailure:
            parsed, txt = anyp(txt).value
            ret = ret + parsed
            checker = parser(txt)
            if txt == "":
                break
        if checker.isSuccess:
            return res.Success.unit((ret, txt))
        return res.Failure("No more input")

    return bp.LParser(internal, label)
Пример #23
0
 def test_SuccessCase(self):
     # Arrange
     txt1 = 'Lorem'
     txt2 = 'ipsum'
     parser1 = bpr.LParser('L')
     parser2 = bpr.LParser('x')
     parser3 = bpr.LParser('i')
     # Act
     parser = cmb.or_else(parser1, parser2, parser3)
     result1 = parser(txt1)
     result2 = parser(txt2)
     expected1 = res.Success(('L', 'orem'))
     expected2 = res.Success(('i', 'psum'))
     # Assert
     self.assertEqual(result1, expected1)
     self.assertEqual(result2, expected2)
Пример #24
0
    def test_SuccessCase(self):
        # Arrange
        txt1 = 'Lorem1'
        txt2 = 'Lorem#ipsum'
        parser_1 = bpr.LParser('1')
        parser_sharp = bpr.LParser('#')

        # Act
        parser = cmb.until(parser_1, parser_sharp)
        result1 = parser(txt1)
        result2 = parser(txt2)
        expected1 = res.Success(('Lorem', '1'))
        expected2 = res.Success(('Lorem', '#ipsum'))
        # Assert
        self.assertEqual(result1, expected1)
        self.assertEqual(result2, expected2)
Пример #25
0
def parse_string(string, label=None):
    """
    returns parser of a given string
    """
    if not isinstance(string, str):
        raise Exception('Expected string')
    return cmb.and_then(*[bp.LParser(char) for char in string], label=label)
Пример #26
0
 def test_WrongArgumentPassedToConstructor_RaisesException(self):
     # Act
     with self.assertRaises(Exception) as context:
         bp.LParser(123)
     # Assert
     self.assertEqual('Incorrect initialization of parsers',
                      str(context.exception))
Пример #27
0
def many(*parsers, **kwargs):
    """
    matches zero or more occurrences of the specified parsers.
    """
    label = kwargs.get('label', None)
    if label is None:
        label = '(' + ''.join([p.label for p in parsers]) + ')*'

    if len(parsers) == 0:
        raise Exception("Expected parser")
    if len(parsers) == 1:
        parser = parsers[0]
    elif len(parsers) > 1:
        parser = or_else(*parsers)

    def internal(txt):
        fst_res = parser(txt)
        if fst_res.isFailure:
            return res.Success.unit(("", txt))

        parsed1, remaining1 = fst_res.value
        parsed2, remaining2 = internal(remaining1).value
        ret = (parsed1 + parsed2, remaining2)
        return res.Success.unit(ret)

    return bp.LParser(internal, label=label)
Пример #28
0
 def test_CorrectlyHandlesDifferentNumberOfArguments_Success(self):
     # Arrange
     txt1 = '1789'
     txt2 = '789'
     parser_1 = bpr.LParser('1')
     parser_2 = bpr.LParser('2')
     parser_3 = bpr.LParser('3')
     parser_4 = bpr.LParser('4')
     # Act
     parser = cmb.opt(parser_1, parser_2, parser_3, parser_4)
     result1 = parser(txt1)
     result2 = parser(txt2)
     expected1 = res.Success(('1', '789'))
     expected2 = res.Success(('', '789'))
     # Assert
     self.assertEqual(result1, expected1)
     self.assertEqual(result2, expected2)
Пример #29
0
 def test_CorrectlyHandlesDifferentNumberOfArguments_Failure(self):
     # Arrange
     txt1 = '11789'
     txt2 = '123789'
     parser_1 = bpr.LParser('1')
     parser_2 = bpr.LParser('2')
     parser_3 = bpr.LParser('3')
     parser_4 = bpr.LParser('4')
     # Act
     parser = cmb.opt(parser_1, parser_2, parser_3, parser_4)
     result1 = parser(txt1)
     result2 = parser(txt2)
     expected1 = res.Failure('error')
     expected2 = res.Failure('error')
     # Assert
     self.assertEqual(result1, expected1)
     self.assertEqual(result2, expected2)
Пример #30
0
 def test_WhenFirstLetterIsCorrect_ReturnsSuccess(self):
     # Arrange
     txt = 'Lorem ipsum'
     parser = bp.LParser('L')
     # Act
     result = parser(txt)
     expected = res.Success(('L', 'orem ipsum'))
     # Assert
     self.assertEqual(result, expected)