Beispiel #1
0
def parse_section(ctx: CTX, mark: str, location: Location, content: Content,
                  before_mark_indentation: int) -> int:
    if mark not in heading_block_marks:
        return PASS

    parent_section = ctx.get_parent_section()
    section_level = section_levels[mark]

    if (parent_section is not None and parent_section.level >= section_level):
        content.go_back(location)
        return EXIT

    # TODO is this ok?
    skip_void(content)

    after_mark_indentation = content.column

    section = Section(location, section_level)

    ctx.composer.add(section)

    ctx.section_stack.append(section)

    section.heading = capture_component(ctx, after_mark_indentation, True)
    section.content = capture_component(ctx, before_mark_indentation, True)

    ctx.section_stack.pop()

    return CONSUMED
Beispiel #2
0
def parse_values(content: Content) -> List[Value]:
    items = []

    can_be_none = True

    while True:
        loc0 = content.get_location()

        value = try_parse_item(content)

        if value is None:
            if can_be_none:
                content.go_back(loc0)
                break
            else:
                raise Exception('Expected to read a group item')

        items.append(value)

        loc0 = content.get_location()

        skip_void(content)

        c = content.peek()

        if c == GROUP_SEPARATOR_CHAR:
            content.move_next()

            skip_void(content)

            can_be_none = False
        else:
            content.go_back(loc0)
            break

    return items
Beispiel #3
0
def try_parse_token_or_entry(
        content: Content,
        allow_entry_separator=True) -> Union[Token, Entry, None]:
    text = try_parse_text(content)

    if text is None:
        return None

    loc0 = content.get_location()

    skip_void(content)

    c = content.peek()

    if c == ENTRY_SEPARATOR_CHAR and allow_entry_separator:
        content.move_next()

        skip_void(content)

        entry_name = text
        entry_value = try_parse_item(content, allow_entry_separator=False)

        if entry_value is None:
            raise StxError('Expected an entry value', content.get_location())

        return Entry(entry_name, entry_value)

    group = try_parse_group(content)

    if group is not None:
        return Entry(text, group)

    # go before skipping void
    content.go_back(loc0)

    return Token(text)
Beispiel #4
0
def parse_inline_text(ctx: CTX, mark: str, location: Location,
                      content: Content, indentation: int) -> int:
    if mark is not None:
        return PASS

    out = StringIO()

    completed = False

    while content.peek() is not None:
        # Check if the text is broken by an inline or stop mark
        if content.test_any(inline_marks):
            break
        elif content.test(ctx.stop_mark):
            break

        c = content.peek()

        if c == '\n':
            out.write(c)
            content.move_next()

            # Check if the text is completed by an empty line
            if content.consume_empty_line():
                completed = True
                break

            loc0 = content.get_location()

            spaces = content.read_spaces(indentation)

            # Check if the text is completed by indentation change
            if spaces < indentation:
                content.go_back(loc0)
                completed = True
                break

            # Check if the text is completed by a non-inline mark
            if content.test_any(not_inline_marks):
                content.go_back(loc0)
                completed = True
                break
        elif c == escape_char:
            content.move_next()

            escaped_mark = content.pull_any(all_marks)
            if escaped_mark is not None:
                out.write(escaped_mark)
            elif content.pull(ctx.stop_mark):
                out.write(ctx.stop_mark)
            elif content.pull(escape_char):
                out.write(escape_char)
            else:
                raise StxError('invalid escaped char')
        else:
            out.write(c)
            content.move_next()

    text = out.getvalue()

    if text == '':
        return EXIT

    ctx.composer.add(PlainText(location, text))

    if completed:
        return EXIT
    return CONSUMED
Beispiel #5
0
def parse_table(ctx: CTX, mark: str, location: Location,
                content: Content) -> int:
    if mark == header_row_block_mark:
        header = True
        reuse_row = False
    elif mark == normal_row_block_mark:
        header = False
        reuse_row = False
    elif mark == cell_block_mark:
        header = False
        reuse_row = True
    else:
        return PASS

    table = ctx.composer.get_last_component()

    if not isinstance(table, Table):
        table = Table(location)

        ctx.composer.add(table)

    row = table.get_last_row() if reuse_row else None

    if row is None:
        row = TableRow(location, header)

        table.rows.append(row)

    # TODO is this ok?
    skip_void(content)

    indentation0 = content.column
    indentation = indentation0

    while True:
        with ctx.using_stop_mark(cell_block_mark):
            cell = capture_component(ctx, indentation, True)

            row.cells.append(cell)

        if not ctx.reader.active():
            break

        content = ctx.reader.get_content()

        loc0 = content.get_location()

        # Consume indentation when it is the beginning of the line
        if content.column == 0:
            if content.read_spaces(indentation0) < indentation0:
                content.go_back(loc0)
                break

        if content.peek() == cell_block_mark:
            content.move_next()
            content.read_spaces()

            indentation = content.column
        else:
            break

    return CONSUMED