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
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
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)
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
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