# HG changeset patch # User Paul Boddie # Date 1493329363 -7200 # Node ID 0cbb97f958954a7835d01b33203abd78baa86031 # Parent 863171f41eacadb3e30c1f2283b4cebcf0596619 Consolidated region parsing further, adding a mechanism of invoking handlers corresponding to the patterns encountered. diff -r 863171f41eac -r 0cbb97f95895 moinformat.py --- a/moinformat.py Thu Apr 27 23:15:30 2017 +0200 +++ b/moinformat.py Thu Apr 27 23:42:43 2017 +0200 @@ -54,6 +54,8 @@ def append(self, node): self.nodes.append(node) + append_text = append + def normalise(self): "Combine adjacent text nodes." @@ -102,6 +104,12 @@ self.level = level self.type = type + def append_text(self, s): + if self.is_transparent(): + self.nodes[-1].append(s) + else: + self.append(s) + def have_end(self, s): return self.level and s.startswith("}") and self.level == len(s) @@ -312,6 +320,8 @@ parse_region_header(items, region) + # Parse section body. + if region.is_transparent(): parse_region_wiki(items, region) else: @@ -332,103 +342,94 @@ "Parse the data provided by 'items' to populate a wiki 'region'." - # Process exposed text and sections. - - block = new_block(region) + new_block(region) + parse_region_details(items, region, ["break", "regionstart", "regionend"]) - while True: +def parse_region_opaque(items, region): - # Obtain text before any marker or the end of the input. + "Parse the data provided by 'items' to populate an opaque 'region'." + + parse_region_details(items, region, ["regionend"]) - preceding = items.read_until(["break", "regionstart", "regionend"]) - if preceding: - block.append(Text(preceding)) +def parse_region_details(items, region, pattern_names): - # Obtain any feature. + "Parse 'items' within 'region' searching using 'pattern_names'." - feature = items.read_match() + try: + while True: - # End of input. - - if not items.matching: - break + # Obtain text before any marker or the end of the input. - # Start a section if an appropriate marker is given. + preceding = items.read_until(pattern_names) + if preceding: + region.append_text(Text(preceding)) - if items.matching == "regionstart": - block = parse_region_within_wiki_region(items, region) + # End of input. - # Interpret the given marker, closing the current section if the - # given marker is the corresponding end marker for the current - # section. + if not items.matching: + break + + # Obtain any feature. - elif items.matching == "regionend" and region.have_end(feature): - break + feature = items.read_match() + handler = handlers.get(items.matching) - # Start a new block if a paragraph break is found. + # Handle each feature or add text to the region. - elif items.matching == "break": - block = parse_block(items, region) + if handler: + handler(items, region) + else: + region.append_text(Text(feature)) - # Add any inappropriate marker to the text. - - else: - block.append(Text(feature)) + except StopIteration: + pass region.normalise() -def parse_region_within_wiki_region(items, region): +def end_region(items, region): - # Parse the section and start a new block after the section. + "End the parsing of 'region'." - feature = items.read_match() - region.append(parse_region(items, len(feature))) - return new_block(region) + raise StopIteration -def parse_block(items, region): +def parse_break(items, region): + + "Handle a paragraph break within 'region'." # Mark any previous block as not being the final one in a sequence. block = region.nodes[-1] block.final = False - return new_block(region) - -def parse_region_opaque(items, region): + new_block(region) - "Parse the data provided by 'items' to populate an opaque 'region'." +def parse_section(items, region): - # Process exposed text and the section end. + "Handle the start of a new section within 'region'." - while True: - - # Obtain text before any marker or the end of the input. + # Parse the section and start a new block after the section. - preceding = items.read_until(["regionend"]) - if preceding: - region.append(Text(preceding)) + level = len(items.read_match()) + region.append(parse_region(items, level)) + new_block(region) - # Obtain any marker. +def parse_section_end(items, region): - marker = items.read_match() + "Handle the end of a new section within 'region'." - # End of input. - - if not marker: - break + feature = items.read_match() + if region.have_end(feature): + raise StopIteration + else: + region.append_text(Text(feature)) - # Interpret the given marker, closing the current section if the - # given marker is the corresponding end marker for the current - # section. - - if region.have_end(marker): - break +# Pattern handlers. - # Add any inappropriate marker to the text. - - else: - region.append(Text(marker)) - - region.normalise() +handlers = { + None : end_region, + "break" : parse_break, + "regionstart" : parse_section, + "regionend" : parse_section_end, + } def new_block(region): @@ -436,7 +437,6 @@ block = Block([]) region.append(block) - return block