1.1 --- a/moinformat.py Thu Apr 27 23:15:30 2017 +0200
1.2 +++ b/moinformat.py Thu Apr 27 23:42:43 2017 +0200
1.3 @@ -54,6 +54,8 @@
1.4 def append(self, node):
1.5 self.nodes.append(node)
1.6
1.7 + append_text = append
1.8 +
1.9 def normalise(self):
1.10
1.11 "Combine adjacent text nodes."
1.12 @@ -102,6 +104,12 @@
1.13 self.level = level
1.14 self.type = type
1.15
1.16 + def append_text(self, s):
1.17 + if self.is_transparent():
1.18 + self.nodes[-1].append(s)
1.19 + else:
1.20 + self.append(s)
1.21 +
1.22 def have_end(self, s):
1.23 return self.level and s.startswith("}") and self.level == len(s)
1.24
1.25 @@ -312,6 +320,8 @@
1.26
1.27 parse_region_header(items, region)
1.28
1.29 + # Parse section body.
1.30 +
1.31 if region.is_transparent():
1.32 parse_region_wiki(items, region)
1.33 else:
1.34 @@ -332,103 +342,94 @@
1.35
1.36 "Parse the data provided by 'items' to populate a wiki 'region'."
1.37
1.38 - # Process exposed text and sections.
1.39 -
1.40 - block = new_block(region)
1.41 + new_block(region)
1.42 + parse_region_details(items, region, ["break", "regionstart", "regionend"])
1.43
1.44 - while True:
1.45 +def parse_region_opaque(items, region):
1.46
1.47 - # Obtain text before any marker or the end of the input.
1.48 + "Parse the data provided by 'items' to populate an opaque 'region'."
1.49 +
1.50 + parse_region_details(items, region, ["regionend"])
1.51
1.52 - preceding = items.read_until(["break", "regionstart", "regionend"])
1.53 - if preceding:
1.54 - block.append(Text(preceding))
1.55 +def parse_region_details(items, region, pattern_names):
1.56
1.57 - # Obtain any feature.
1.58 + "Parse 'items' within 'region' searching using 'pattern_names'."
1.59
1.60 - feature = items.read_match()
1.61 + try:
1.62 + while True:
1.63
1.64 - # End of input.
1.65 -
1.66 - if not items.matching:
1.67 - break
1.68 + # Obtain text before any marker or the end of the input.
1.69
1.70 - # Start a section if an appropriate marker is given.
1.71 + preceding = items.read_until(pattern_names)
1.72 + if preceding:
1.73 + region.append_text(Text(preceding))
1.74
1.75 - if items.matching == "regionstart":
1.76 - block = parse_region_within_wiki_region(items, region)
1.77 + # End of input.
1.78
1.79 - # Interpret the given marker, closing the current section if the
1.80 - # given marker is the corresponding end marker for the current
1.81 - # section.
1.82 + if not items.matching:
1.83 + break
1.84 +
1.85 + # Obtain any feature.
1.86
1.87 - elif items.matching == "regionend" and region.have_end(feature):
1.88 - break
1.89 + feature = items.read_match()
1.90 + handler = handlers.get(items.matching)
1.91
1.92 - # Start a new block if a paragraph break is found.
1.93 + # Handle each feature or add text to the region.
1.94
1.95 - elif items.matching == "break":
1.96 - block = parse_block(items, region)
1.97 + if handler:
1.98 + handler(items, region)
1.99 + else:
1.100 + region.append_text(Text(feature))
1.101
1.102 - # Add any inappropriate marker to the text.
1.103 -
1.104 - else:
1.105 - block.append(Text(feature))
1.106 + except StopIteration:
1.107 + pass
1.108
1.109 region.normalise()
1.110
1.111 -def parse_region_within_wiki_region(items, region):
1.112 +def end_region(items, region):
1.113
1.114 - # Parse the section and start a new block after the section.
1.115 + "End the parsing of 'region'."
1.116
1.117 - feature = items.read_match()
1.118 - region.append(parse_region(items, len(feature)))
1.119 - return new_block(region)
1.120 + raise StopIteration
1.121
1.122 -def parse_block(items, region):
1.123 +def parse_break(items, region):
1.124 +
1.125 + "Handle a paragraph break within 'region'."
1.126
1.127 # Mark any previous block as not being the final one in a sequence.
1.128
1.129 block = region.nodes[-1]
1.130 block.final = False
1.131 - return new_block(region)
1.132 -
1.133 -def parse_region_opaque(items, region):
1.134 + new_block(region)
1.135
1.136 - "Parse the data provided by 'items' to populate an opaque 'region'."
1.137 +def parse_section(items, region):
1.138
1.139 - # Process exposed text and the section end.
1.140 + "Handle the start of a new section within 'region'."
1.141
1.142 - while True:
1.143 -
1.144 - # Obtain text before any marker or the end of the input.
1.145 + # Parse the section and start a new block after the section.
1.146
1.147 - preceding = items.read_until(["regionend"])
1.148 - if preceding:
1.149 - region.append(Text(preceding))
1.150 + level = len(items.read_match())
1.151 + region.append(parse_region(items, level))
1.152 + new_block(region)
1.153
1.154 - # Obtain any marker.
1.155 +def parse_section_end(items, region):
1.156
1.157 - marker = items.read_match()
1.158 + "Handle the end of a new section within 'region'."
1.159
1.160 - # End of input.
1.161 -
1.162 - if not marker:
1.163 - break
1.164 + feature = items.read_match()
1.165 + if region.have_end(feature):
1.166 + raise StopIteration
1.167 + else:
1.168 + region.append_text(Text(feature))
1.169
1.170 - # Interpret the given marker, closing the current section if the
1.171 - # given marker is the corresponding end marker for the current
1.172 - # section.
1.173 -
1.174 - if region.have_end(marker):
1.175 - break
1.176 +# Pattern handlers.
1.177
1.178 - # Add any inappropriate marker to the text.
1.179 -
1.180 - else:
1.181 - region.append(Text(marker))
1.182 -
1.183 - region.normalise()
1.184 +handlers = {
1.185 + None : end_region,
1.186 + "break" : parse_break,
1.187 + "regionstart" : parse_section,
1.188 + "regionend" : parse_section_end,
1.189 + }
1.190
1.191 def new_block(region):
1.192
1.193 @@ -436,7 +437,6 @@
1.194
1.195 block = Block([])
1.196 region.append(block)
1.197 - return block
1.198
1.199
1.200