예제 #1
0
def _parse_string(source: Source, string_regex=BASIC_STRING, separator='"') -> str:
    source.expect(separator)
    res = []
    while True:
        if not source.consume_regex(string_regex):
            raise DoesNotMatch('Invalid string starting from {text}'
                               .format(text=source._text[:100]))
        res.append(source.last_consumed)

        # start of some escape character
        if not source.consume('\\'):
            break
        # do nothing if new line chars encountered
        # corresponds to \
        if source.consume_regex(NEWLINE_ESCAPE_CHARS_REGEX):
            pass

        # read unicode characters
        elif source.consume_regex(SHORT_UNICODE_REGEX) or source.consume_regex(LONG_UNICODE_REGEX):
            res.append(chr(int(source.last_consumed, 16)))

        else:
            # fail if no escape character follows
            source.expect_regex(ESCAPE_CHARS_REGEX)
            res.append(ESCAPES_MAPPING[source.last_consumed])

    source.expect(separator)
    return ''.join(res)
예제 #2
0
def parse_line_comment(source: Source) -> Comment:
    source.expect('#')
    source.consume_regex(COMMENT_REGEX)
    text = source.last_consumed

    source.expect_regex(re.compile(r'(?P<res>\n|\Z)'))
    return Comment(text)
예제 #3
0
def parse_kv_entry(source: Source) -> KVEntry:
    key = parse_keyword(source)

    source.consume_regex(WHITESPACE_REGEX)
    source.expect('=')
    source.consume_regex(WHITESPACE_REGEX)

    val = parse_value(source)
    return KVEntry(key, val)
예제 #4
0
def _parse_literal_string(source: Source, string_regex=LITERAL_STRING, separator='\'') -> str:
    source.expect(separator)

    is_matched = source.consume_regex(string_regex)
    if not is_matched:
        raise DoesNotMatch()

    parsed_str = source.last_consumed
    source.expect(separator)

    return parsed_str
예제 #5
0
def _parse_inline_table(source: Source) -> InlineTable:
    table = InlineTable()
    source.expect('{')
    if not source.consume('}'):
        source.consume_regex(WHITESPACE_REGEX)
        kv_entry = parse_kv_entry(source)

        if source.last_consumed == '}':
            raise InvalidTomlError('Cannot have nested inline tables.')

        table[kv_entry.key] = kv_entry.val

        while source.consume(','):
            source.consume_regex(WHITESPACE_REGEX)
            kv_entry = parse_kv_entry(source)
            table[kv_entry.key] = kv_entry.val
            source.consume_regex(WHITESPACE_REGEX)

        source.expect('}')

    return table
예제 #6
0
def _parse_array(source: Source) -> List[ValueType]:
    array_type = None  # type: type
    items = []  # type: List[ValueType]
    source.expect('[')

    try:
        while True:
            source.consume_regex(ENCLOSING_WHITESPACE_CHARS)
            parsed_val = parse_value(source)

            if array_type is not None and \
                    not isinstance(parsed_val, array_type):
                raise MixedTypesArray

            if array_type is None:
                array_type = type(parsed_val)

            items.append(parsed_val)

            source.consume_regex(ENCLOSING_WHITESPACE_CHARS)
            source.expect(',')
    except (ExpectationError, DoesNotMatch):
        pass

    source.consume_regex(ENCLOSING_WHITESPACE_CHARS)
    source.expect(']')
    return items
예제 #7
0
 def test_expect_any_text_chunk_false(self):
     text = 'World'
     s = Source(text)
     with self.assertRaises(ExpectationError):
         s.expect('Hello')
예제 #8
0
 def test_expect_any_text_chunk_true(self):
     text = 'Hello'
     s = Source(text)
     # not raises anything
     s.expect(text)
예제 #9
0
def parse_table(source: Source) -> ParsedTable:
    source.expect('[')
    keys = _parse_table_name(source)
    source.expect(']')

    return ParsedTable(keys)