# HG changeset patch # User Paul Boddie # Date 1494543080 -7200 # Node ID 743a15ed73aaca182c85bc971f87d841cf8083db # Parent 7b9f5d3e242dd07f51c4f15058b8eb6209771bec Reorganised the parsing framework, removing the pattern dictionary from the TokenStream class, sending pattern mappings into the tokeniser when searching for patterns and removing the need to stack tokenisers with different patterns. Introduced items (tokeniser) and region instance attributes to the parser classes for convenience, simplifying method signatures, also introducing convenience methods for accessing the tokeniser. Adjusted some patterns to forbid newlines in some whitespace regions that were causing parsing errors. diff -r 7b9f5d3e242d -r 743a15ed73aa moinformat/__init__.py --- a/moinformat/__init__.py Fri May 05 22:38:31 2017 +0200 +++ b/moinformat/__init__.py Fri May 12 00:51:20 2017 +0200 @@ -19,91 +19,13 @@ this program. If not, see . """ -from moinformat.parsing import ParserBase, TokenStream, get_patterns, \ - init_formats, new_block +from moinformat.parsing import ParserBase, get_patterns, get_subset, new_block from moinformat.serialisers import serialise from moinformat.tree import Break, DefItem, DefTerm, FontStyle, Heading, \ Larger, ListItem, Monospace, Region, Rule, Smaller, \ Subscript, Superscript, Table, TableAttr, \ TableAttrs, TableCell, TableRow, Text, Underline -# Regular expressions. - -syntax = { - # Page regions: - "regionstart" : r"((^\s*)([{]{3,}))", # {{{... - "regionend" : r"^\s*([}]{3,})", # }}}... - "header" : r"#!(.*?)\n", # #! char-excl-nl - - # Region contents: - # Line-oriented patterns: - # blank line - "break" : r"^(\s*?)\n", - # ws... expecting text :: - "defterm" : r"^(\s+)(?=.+?::)", - # ws... expecting :: ws... - "defterm_empty" : r"^(\s+)(?=::\s+)", - # [ws...] =... ws... expecting headingend - "heading" : r"^(\s*)(?P=+)(\s+)(?=.*?\s+(?P=x)\s*\n)", - # ws... list-item [ws...] - "listitem" : r"^(\s+)(\*)(\s*)", - # ws... number-item ws... - "listitem_num" : r"^(\s+)(\d+\.)(\s+)", - # ws... alpha-item ws... - "listitem_alpha": r"^(\s+)([aA]\.)(\s+)", - # ws... roman-item ws... - "listitem_roman": r"^(\s+)([iI]\.)(\s+)", - # ws... dot-item [ws...] - "listitem_dot" : r"^(\s+)(\.)(\s*)", - # || - "tablerow" : r"^\|\|", - - # Region contents: - # Inline patterns: - "fontstyle" : r"('{2,6})", - "larger" : r"~\+", - "monospace" : r"`", - "rule" : r"(-----*)", # ----... - "smaller" : r"~-", - "sub" : r",,", - "super" : r"\^", - "underline" : r"__", - - # Inline contents: - "largerend" : r"\+~", - "monospaceend" : r"`", - "smallerend" : r"-~", - "subend" : r",,", - "superend" : r"\^", - "underlineend" : r"__", - - # Heading contents: - "headingend" : r"(\s+)(=+)(\s*\n)", # ws... =... [ws...] nl - - # List contents: - "deftermend" : r"::(\s*?\n)", - "deftermsep" : r"::(\s+)", - "listitemend" : r"^", # next line - - # Table contents: - "tableattrs" : r"<", - "tablecell" : r"\|\|", - "tableend" : r"(\s*?)^", # [ws...] next line - - # Table attributes: - "tableattrsend" : r">", - "halign" : r"([(:)])", - "valign" : r"([v^])", - "colour" : r"(\#[0-9A-F]{6})", - "colspan" : r"-(\d+)", - "rowspan" : r"\|(\d+)", - "width" : r"(\d+%)", - "attrname" : r"((?![-\d])[-\w]+)", # not-dash-or-digit dash-or-word-char... - "attrvalue" : r"""=(?P['"])(.*?)(?P=x)""", - } - - - class Parser(ParserBase): "A wiki region parser." @@ -115,145 +37,101 @@ names to parser objects. """ - default_formats = {"wiki" : self} + # Introduce this class as the default parser for the wiki format. + + default_formats = {"wiki" : Parser} if formats: default_formats.update(formats) ParserBase.__init__(self, default_formats) - # Pattern details. - - patterns = get_patterns(syntax) - - table_pattern_names = [ - "attrname", "colour", "colspan", "halign", "rowspan", "tableattrsend", - "valign", "width" - ] - - inline_pattern_names = [ - "fontstyle", "larger", "monospace", "smaller", "sub", "super", "underline", - ] - - region_pattern_names = inline_pattern_names + [ - "break", "heading", "defterm", "defterm_empty", "listitem", - "listitem_alpha", "listitem_dot", "listitem_num", "listitem_roman", - "regionstart", "regionend", "rule", "tablerow", - ] - - table_region_pattern_names = inline_pattern_names + [ - "tableattrs", "tablecell", "tableend" - ] - - def inline_patterns_for(self, name): - names = self.inline_pattern_names[:] - names[names.index(name)] = "%send" % name - return names - # Principal parser methods. - def get_items(self, s, pos=0): - - "Return a sequence of token items for 's' and 'pos'." - - return TokenStream(s, self.patterns, pos) - def parse(self, s): """ Parse page text 's'. Pages consist of regions delimited by markers. """ - items = self.get_items(s) - region = Region([]) + self.items = self.get_items(s) + self.region = Region([]) # Parse page header. - self.parse_region_header(items, region) + self.parse_region_header(self.region) - # Handle pages directly with this parser. + # Handle pages directly with this parser. Pages do not need to use an + # explicit format indicator. + + if not self.region.type: + self.parse_region_content(self.items, self.region) + # Otherwise, test the type and find an appropriate parser. - if not region.type: - self.parse_region_content(items, region) else: - self.parse_region_type(items, region) - - return region - - def parse_region_content(self, items, region): - - "Parse the data provided by 'items' to populate a wiki 'region'." + self.parse_region_type(self.region) - # Obtain a suitable token stream. - - items = self.replace_items(items) - - # Define a block to hold text and start parsing. + return self.region - new_block(region) - self.parse_region_details(items, region, self.region_pattern_names) - # Update the previous token stream. - - self.update_items(items) # Parser methods supporting different page features. - def parse_attrname(self, items, attrs): + def parse_attrname(self, attrs): "Handle an attribute name within 'attrs'." - name = items.read_match() + name = self.read_match() attr = TableAttr(name) - preceding = items.read_until(["attrvalue"], False) + preceding = self.read_until(["attrvalue"], False) if preceding == "": - attr.quote = items.read_match(1) - attr.value = items.read_match(2) + attr.quote = self.read_match(1) + attr.value = self.read_match(2) attrs.append(attr) - def parse_break(self, items, region): + def parse_break(self, region): "Handle a paragraph break within 'region'." region.add(Break()) new_block(region) - def parse_defitem(self, items, region, extra=""): + def parse_defitem(self, region, extra=""): "Handle a definition item within 'region'." - pad = items.read_match(1) + pad = self.read_match(1) item = DefItem([], pad, extra) - self.parse_region_details(items, item, ["listitemend"]) + self.parse_region_details(item, ["listitemend"]) region.add(item) new_block(region) - def parse_defterm(self, items, region): + def parse_defterm(self, region): "Handle a definition term within 'region'." - pad = items.read_match(1) + pad = self.read_match(1) term = DefTerm([], pad) - self.parse_region_details(items, term, ["deftermend", "deftermsep"]) + self.parse_region_details(term, ["deftermend", "deftermsep"]) region.add(term) - if items.matching == "deftermsep": - self.parse_defitem(items, region) + if self.read_matching() == "deftermsep": + self.parse_defitem(region) - def parse_defterm_empty(self, items, region): + def parse_defterm_empty(self, region): "Handle an empty definition term within 'region'." - extra = items.read_match(1) - self.parse_region_details(items, region, ["deftermsep"]) - self.parse_defitem(items, region, extra) + extra = self.read_match(1) + self.parse_region_details(region, ["deftermsep"]) + self.parse_defitem(region, extra) - def parse_fontstyle(self, items, region): + def parse_fontstyle(self, region): "Handle emphasis and strong styles." - n = len(items.read_match(1)) + n = len(self.read_match(1)) # Handle endings. @@ -271,7 +149,7 @@ if not active: if n: - items.rewind(n) + self.items.rewind(n) raise StopIteration elif not n: @@ -285,87 +163,87 @@ span = FontStyle([], emphasis, strong) if not double: - self.parse_region_details(items, span, self.inline_pattern_names) + self.parse_region_details(span, self.inline_pattern_names) region.append_inline(span) - def parse_halign(self, items, attrs): + def parse_halign(self, attrs): "Handle horizontal alignment within 'attrs'." - value = items.read_match() + value = self.read_match() attr = TableAttr("halign", value == "(" and "left" or value == ")" and "right" or "center", True) attrs.append(attr) - def parse_heading(self, items, region): + def parse_heading(self, region): "Handle a heading." - start_extra = items.read_match(1) - level = len(items.read_match(2)) - start_pad = items.read_match(3) + start_extra = self.read_match(1) + level = len(self.read_match(2)) + start_pad = self.read_match(3) heading = Heading([], level, start_extra, start_pad) - self.parse_region_details(items, heading, ["headingend"] + self.inline_pattern_names) + self.parse_region_details(heading, ["headingend"] + self.inline_pattern_names) region.add(heading) new_block(region) - def parse_heading_end(self, items, heading): + def parse_heading_end(self, heading): "Handle the end of a heading." - level = len(items.read_match(2)) + level = len(self.read_match(2)) if heading.level == level: - heading.end_pad = items.read_match(1) - heading.end_extra = items.read_match(3) + heading.end_pad = self.read_match(1) + heading.end_extra = self.read_match(3) raise StopIteration - def parse_listitem(self, items, region): + def parse_listitem(self, region): "Handle a list item marker within 'region'." - indent = len(items.read_match(1)) - marker = items.read_match(2) - space = items.read_match(3) + indent = len(self.read_match(1)) + marker = self.read_match(2) + space = self.read_match(3) item = ListItem([], indent, marker, space) - self.parse_region_details(items, item, ["listitemend"]) + self.parse_region_details(item, self.listitem_pattern_names) region.add(item) new_block(region) - def parse_rule(self, items, region): + def parse_rule(self, region): "Handle a horizontal rule within 'region'." - length = len(items.read_match(1)) + length = len(self.read_match(1)) rule = Rule(length) region.add(rule) new_block(region) - def parse_section(self, items, region): + def parse_section(self, region): "Handle the start of a new section within 'region'." # Parse the section and start a new block after the section. - indent = len(items.read_match(2)) - level = len(items.read_match(3)) - region.add(self.parse_region(items, level, indent)) + indent = len(self.read_match(2)) + level = len(self.read_match(3)) + region.add(self.parse_region(level, indent)) new_block(region) - def parse_section_end(self, items, region): + def parse_section_end(self, region): "Handle the end of a new section within 'region'." - feature = items.read_match() + feature = self.read_match() if region.have_end(feature): raise StopIteration else: region.append_inline(Text(feature)) - def parse_table_attrs(self, items, cell): + def parse_table_attrs(self, cell): "Handle the start of table attributes within 'cell'." attrs = TableAttrs([]) - self.parse_region_details(items, attrs, self.table_pattern_names) + self.parse_region_details(attrs, self.table_pattern_names) # Test the validity of the attributes. @@ -396,7 +274,7 @@ cell.append_inline(Text(serialise(attrs))) - def parse_table_row(self, items, region): + def parse_table_row(self, region): "Handle the start of a table row within 'region'." @@ -414,12 +292,12 @@ while True: cell = TableCell([]) - self.parse_region_details(items, cell, self.table_region_pattern_names) + self.parse_region_details(cell, self.table_region_pattern_names) # Handle the end of the row. - if items.matching == "tableend": - trailing = items.read_match() + if self.read_matching() == "tableend": + trailing = self.read_match() # If the cell was started but not finished, convert the row into text. @@ -453,11 +331,11 @@ new_block(region) - def parse_valign(self, items, attrs): + def parse_valign(self, attrs): "Handle vertical alignment within 'attrs'." - value = items.read_match() + value = self.read_match() attr = TableAttr("valign", value == "^" and "top" or "bottom", True) attrs.append(attr) @@ -465,54 +343,162 @@ # Inline formatting handlers. - def parse_inline(self, items, region, cls, pattern_name): + def parse_inline(self, region, cls, pattern_name): "Handle an inline region." span = cls([]) - self.parse_region_details(items, span, self.inline_patterns_for(pattern_name)) + self.parse_region_details(span, self.inline_patterns_for(pattern_name)) region.append_inline(span) - def parse_larger(self, items, region): - self.parse_inline(items, region, Larger, "larger") + def parse_larger(self, region): + self.parse_inline(region, Larger, "larger") - def parse_monospace(self, items, region): - self.parse_inline(items, region, Monospace, "monospace") + def parse_monospace(self, region): + self.parse_inline(region, Monospace, "monospace") - def parse_smaller(self, items, region): - self.parse_inline(items, region, Smaller, "smaller") + def parse_smaller(self, region): + self.parse_inline(region, Smaller, "smaller") - def parse_sub(self, items, region): - self.parse_inline(items, region, Subscript, "sub") + def parse_sub(self, region): + self.parse_inline(region, Subscript, "sub") - def parse_super(self, items, region): - self.parse_inline(items, region, Superscript, "super") + def parse_super(self, region): + self.parse_inline(region, Superscript, "super") - def parse_underline(self, items, region): - self.parse_inline(items, region, Underline, "underline") + def parse_underline(self, region): + self.parse_inline(region, Underline, "underline") # Table attribute handlers. - def parse_table_attr(self, items, attrs, pattern_name): + def parse_table_attr(self, attrs, pattern_name): "Handle a table attribute." - value = items.read_match() - attrs.append(TableAttr(pattern_name, value, True)) + attrs.append(TableAttr(pattern_name, self.read_match(), True)) + + def parse_colour(self, cell): + self.parse_table_attr(cell, "colour") + + def parse_colspan(self, cell): + self.parse_table_attr(cell, "colspan") + + def parse_rowspan(self, cell): + self.parse_table_attr(cell, "rowspan") + + def parse_width(self, cell): + self.parse_table_attr(cell, "width") + + + + # Regular expressions. + + syntax = { + # Page regions: + "regionstart" : r"((^\N*)([{]{3,}))", # {{{... + "regionend" : r"^\N*([}]{3,})", # }}}... + "header" : r"#!(.*?)\n", # #! char-excl-nl - def parse_colour(self, items, cell): - self.parse_table_attr(items, cell, "colour") + # Region contents: + # Line-oriented patterns: + # blank line + "break" : r"^(\s*?)\n", + # ws... expecting text :: + "defterm" : r"^(\N+)(?=.+?::)", + # ws... expecting :: ws... + "defterm_empty" : r"^(\N+)(?=::\s+)", + # [ws...] =... ws... expecting headingend + "heading" : r"^(\N*)(?P=+)(\s+)(?=.*?\N+(?P=x)\N*$)", + # ws... list-item [ws...] + "listitem" : r"^(\N+)(\*)(\s*)", + # ws... number-item ws... + "listitem_num" : r"^(\N+)(\d+\.)(\s+)", + # ws... alpha-item ws... + "listitem_alpha": r"^(\N+)([aA]\.)(\s+)", + # ws... roman-item ws... + "listitem_roman": r"^(\N+)([iI]\.)(\s+)", + # ws... dot-item [ws...] + "listitem_dot" : r"^(\N+)(\.)(\s*)", + # || + "tablerow" : r"^\|\|", + + # Region contents: + # Inline patterns: + "fontstyle" : r"('{2,6})", + "larger" : r"~\+", + "monospace" : r"`", + "rule" : r"(-----*)", # ----... + "smaller" : r"~-", + "sub" : r",,", + "super" : r"\^", + "underline" : r"__", - def parse_colspan(self, items, cell): - self.parse_table_attr(items, cell, "colspan") + # Inline contents: + "largerend" : r"\+~", + "monospaceend" : r"`", + "smallerend" : r"-~", + "subend" : r",,", + "superend" : r"\^", + "underlineend" : r"__", + + # Heading contents: + "headingend" : r"(\N+)(=+)(\N*$)", # ws... =... [ws...] nl + + # List contents: + "deftermend" : r"::(\s*?\n)", + "deftermsep" : r"::(\s+)", + "listitemend" : r"^", # next line + + # Table contents: + "tableattrs" : r"<", + "tablecell" : r"\|\|", + "tableend" : r"(\s*?)^", # [ws...] next line - def parse_rowspan(self, items, cell): - self.parse_table_attr(items, cell, "rowspan") + # Table attributes: + "tableattrsend" : r">", + "halign" : r"([(:)])", + "valign" : r"([v^])", + "colour" : r"(\#[0-9A-F]{6})", + "colspan" : r"-(\d+)", + "rowspan" : r"\|(\d+)", + "width" : r"(\d+%)", + "attrname" : r"((?![-\d])[-\w]+)", # not-dash-or-digit dash-or-word-char... + "attrvalue" : r"""=(?P['"])(.*?)(?P=x)""", + } + + patterns = get_patterns(syntax) + + + + # Pattern details. - def parse_width(self, items, cell): - self.parse_table_attr(items, cell, "width") + table_pattern_names = [ + "attrname", "colour", "colspan", "halign", "rowspan", "tableattrsend", + "valign", "width" + ] + + inline_pattern_names = [ + "fontstyle", "larger", "monospace", "smaller", "sub", "super", "underline", + ] + + listitem_pattern_names = inline_pattern_names + ["listitemend"] + + region_pattern_names = inline_pattern_names + [ + "break", "heading", "defterm", "defterm_empty", "listitem", + "listitem_alpha", "listitem_dot", "listitem_num", "listitem_roman", + "regionstart", "regionend", "rule", "tablerow", + ] + + table_region_pattern_names = inline_pattern_names + [ + "tableattrs", "tablecell", "tableend" + ] + + def inline_patterns_for(self, name): + names = self.inline_pattern_names[:] + names[names.index(name)] = "%send" % name + return names @@ -570,6 +556,6 @@ # Top-level functions. def parse(s, formats=None): - return Parser(init_formats(formats)).parse(s) + return Parser(formats).parse(s) # vim: tabstop=4 expandtab shiftwidth=4 diff -r 7b9f5d3e242d -r 743a15ed73aa moinformat/parsing.py --- a/moinformat/parsing.py Fri May 05 22:38:31 2017 +0200 +++ b/moinformat/parsing.py Fri May 12 00:51:20 2017 +0200 @@ -40,20 +40,14 @@ patterns[name] = re.compile(value, re.UNICODE | re.MULTILINE) return patterns -def combine_patterns(patterns, syntax): +def get_subset(d, keys): - "Combine 'patterns' with those defined by the given 'syntax' mapping." - - return combine_dicts([patterns, get_patterns(syntax)]) + "Return a subset of 'd' having the given 'keys'." -def combine_dicts(dicts): - - "Combine the given 'dicts'." - - combined = {} - for d in dicts: - combined.update(d) - return combined + subset = {} + for key in keys: + subset[key] = d[key] + return subset @@ -63,9 +57,8 @@ "A stream of tokens taken from a string." - def __init__(self, s, patterns, pos=0): + def __init__(self, s, pos=0): self.s = s - self.patterns = patterns self.pos = pos self.match = None self.matching = None @@ -76,12 +69,12 @@ self.pos -= min(length, self.pos) - def read_until(self, pattern_names, remaining=True): + def read_until(self, patterns, remaining=True): """ - Find the first match for the given 'pattern_names'. Return the text - preceding any match, the remaining text if no match was found, or None - if no match was found and 'remaining' is given as a false value. + Find the first match for the given 'patterns'. Return the text preceding + any match, the remaining text if no match was found, or None if no match + was found and 'remaining' is given as a false value. """ first = None @@ -89,8 +82,8 @@ # Find the first matching pattern. - for pattern_name in pattern_names: - match = self.patterns[pattern_name].search(self.s, self.pos) + for pattern_name, pattern in patterns.items(): + match = pattern.search(self.s, self.pos) if match: start, end = match.span() if self.matching is None or start < first: @@ -143,6 +136,8 @@ "Common parsing methods." + region_pattern_names = None + def __init__(self, formats=None): """ @@ -151,26 +146,66 @@ """ self.formats = formats - self.replaced_items = None + + def get_parser(self, format_type): + + """ + Return a parser for 'format_type' or None if no suitable parser is found. + """ + + if not self.formats: + return None + + cls = self.formats.get(format_type) + if cls: + return cls(self.formats) + else: + return None + + def get_patterns(self, pattern_names): + + "Return a mapping of the given 'pattern_names' to patterns." + + return get_subset(self.patterns, pattern_names) def get_items(self, s, pos=0): "Return a sequence of token items for 's' and 'pos'." - raise NotImplementedError + return TokenStream(s, pos) + + def set_region(self, items, region): + + "Set the 'items' used to populate the given 'region'." - def replace_items(self, items): + self.items = items + self.region = region + + def read_until(self, pattern_names, remaining=True): - "Replace the given 'items' with a sequence employing the same state." + """ + Read the next portion of input, matching using 'pattern_names'. Return + the text preceding any match, the remaining text if no match was found, + or None if no match was found and 'remaining' is given as a false value. + """ - self.replaced_items = items - return self.get_items(items.s, items.pos) + return self.items.read_until(self.get_patterns(pattern_names)) + + def read_match(self, group=1): + + """ + Return the group of the matching pattern with the given 'group' number. + """ - def update_items(self, items): + return self.items.read_match(group) + + def read_matching(self): - "Update the state of the replaced items with that of 'items'." + "Return the name of the matching pattern." - self.replaced_items.pos = items.pos + return self.items.matching + + # Parser methods invoked from other objects. def parse(self, s): @@ -178,92 +213,104 @@ Parse page text 's'. Pages consist of regions delimited by markers. """ - return self.parse_region(self.get_items(s)) + self.items = self.get_items(s) + self.region = self.parse_region() + return self.region + + def parse_region_content(self, items, region): + + "Parse the data provided by 'items' to populate a 'region'." + + self.set_region(items, region) - def parse_region(self, items, level=0, indent=0): + # Define a block to hold text and start parsing. + + new_block(region) + + if self.region_pattern_names: + self.parse_region_details(region, self.region_pattern_names) + + # Top-level parser handler methods. + + def parse_region(self, level=0, indent=0): """ - Parse the data provided by 'items' to populate a region with the given - 'level' at the given 'indent'. + Parse the data to populate a region with the given 'level' at the given + 'indent'. """ region = Region([], level, indent) # Parse section headers, then parse according to region type. - self.parse_region_header(items, region) - self.parse_region_type(items, region) + self.parse_region_header(region) + self.parse_region_type(region) return region - def parse_region_type(self, items, region): + def parse_region_type(self, region): """ - Given data provided by 'items', use configured parsers to parse the - 'region' based on its type. + Use configured parsers to parse 'region' based on its type. """ # Find an appropriate parser given the type. - if self.formats.has_key(region.type): - self.formats[region.type].parse_region_content(items, region) + parser = self.get_parser(region.type) + + if parser: + parser.parse_region_content(self.items, region) # Otherwise, treat the section as opaque. else: - self.parse_region_opaque(items, region) + self.parse_region_opaque(region) - def parse_region_header(self, items, region): + def parse_region_header(self, region): """ - Parse the region header from the 'items', setting it for the given 'region'. + Parse the region header, setting it on the 'region' object. """ - if items.read_until(["header"], False) == "": # None means no header - region.type = items.read_match() + if self.read_until(["header"], False) == "": # None means no header + region.type = self.read_match() - def parse_region_opaque(self, items, region): + def parse_region_opaque(self, region): - "Parse the data provided by 'items' to populate an opaque 'region'." + "Parse the data to populate an opaque 'region'." region.transparent = False - self.parse_region_details(items, region, ["regionend"]) - - def parse_region_content(self, items, region): - - "Parse the data provided by 'items' to populate the given 'region'." - - pass + self.parse_region_details(region, ["regionend"]) # Parsing utilities. - def parse_region_details(self, items, region, pattern_names): + def parse_region_details(self, region, pattern_names): - "Parse 'items' within 'region' searching using 'pattern_names'." + "Search 'region' using the 'pattern_names'." try: while True: # Obtain text before any marker or the end of the input. - preceding = items.read_until(pattern_names) + preceding = self.read_until(pattern_names) if preceding: region.append_inline(Text(preceding)) # End of input. - if not items.matching: + if not self.read_matching(): break # Obtain any feature. - feature = items.read_match() - handler = self.handlers.get(items.matching) + feature = self.read_match() + handler = self.handlers.get(self.read_matching()) # Handle each feature or add text to the region. if handler: - handler(self, items, region) + handler(self, region) else: region.append_inline(Text(feature)) @@ -272,26 +319,10 @@ region.normalise() - def end_region(self, items, region): + def end_region(self, region): "End the parsing of 'region', breaking out of the parsing loop." raise StopIteration - -# Format mapping initialisation. - -def init_formats(formats): - - """ - Convert the given 'formats' mapping from a name-to-class mapping to a - name-to-instance mapping with each parser instance employing the format - mapping itself. Return the converted mapping. - """ - - d = {} - for name, cls in formats.items(): - d[name] = cls(d) - return d - # vim: tabstop=4 expandtab shiftwidth=4