| @@ -629,20 +629,106 @@ class Tokenizer(object): | |||||
| else: | else: | ||||
| self._emit_all(tag) | self._emit_all(tag) | ||||
| def _really_parse_style(self, context): | |||||
| """Parse wiki-style bold or italics. Raises :py:exc:`BadRoute`.""" | |||||
| stack = self._parse(context) | |||||
| markup = "''" if context & contexts.STYLE_ITALICS else "'''" | |||||
| tag = "i" if context & contexts.STYLE_ITALICS else "b" | |||||
| def _emit_tag_open(self, tag, markup): | |||||
| """Write the three tokens in a tag opening sequence.""" | |||||
| self._emit(tokens.TagOpenOpen(wiki_markup=markup)) | self._emit(tokens.TagOpenOpen(wiki_markup=markup)) | ||||
| self._emit_text(tag) | self._emit_text(tag) | ||||
| self._emit(tokens.TagCloseOpen()) | self._emit(tokens.TagCloseOpen()) | ||||
| self._emit_all(stack) | |||||
| def _emit_tag_close(self, tag): | |||||
| """Write the three tokens in a tag closing sequence.""" | |||||
| self._emit(tokens.TagOpenClose()) | self._emit(tokens.TagOpenClose()) | ||||
| self._emit_text(tag) | self._emit_text(tag) | ||||
| self._emit(tokens.TagCloseClose()) | self._emit(tokens.TagCloseClose()) | ||||
| def _really_parse_style(self, context, reset, markup, tag): | |||||
| """Parse wiki-style bold or italics. Raises :py:exc:`BadRoute`.""" | |||||
| if context & contexts.STYLE_ITALICS: | |||||
| try: | |||||
| stack = self._parse(context) | |||||
| except BadRoute: ## only if STYLE_PASS_AGAIN in destroyed context | |||||
| self._head = reset | |||||
| stack = self._parse(context | contexts.STYLE_PASS_2) | |||||
| else: | |||||
| stack = self._parse(context) | |||||
| self._emit_tag_open(tag, markup) | |||||
| self._emit_all(stack) | |||||
| self._emit_tag_close(tag) | |||||
| def _parse_italics(self): | |||||
| """Parse wiki-style italics.""" | |||||
| reset = self._head | |||||
| try: | |||||
| self._really_parse_style(contexts.STYLE_ITALICS, reset, "''", "i") | |||||
| except BadRoute: | |||||
| self._head = reset | |||||
| self._emit_text("''") | |||||
| def _parse_bold(self): | |||||
| """Parse wiki-style bold.""" | |||||
| reset = self._head | |||||
| try: | |||||
| self._really_parse_style(contexts.STYLE_BOLD, reset, "'''", "b") | |||||
| except BadRoute: | |||||
| self._head = reset | |||||
| if self._context & contexts.STYLE_PASS_2: | |||||
| self._emit_text("'") | |||||
| return True | |||||
| elif self._context & contexts.STYLE_ITALICS: | |||||
| # Set STYLE_PASS_AGAIN | |||||
| self._emit_text("'''") | |||||
| else: | |||||
| self._emit_text("'") | |||||
| self._parse_italics() | |||||
| def _parse_italics_and_bold(self): | |||||
| """Parse wiki-style italics and bold together (i.e., five ticks).""" | |||||
| reset = self._head | |||||
| try: | |||||
| stack = self._parse(contexts.STYLE_BOLD) | |||||
| except BadRoute: | |||||
| self._head = reset | |||||
| try: | |||||
| stack = self._parse(contexts.STYLE_ITALICS) | |||||
| except BadRoute: | |||||
| self._head = reset | |||||
| self._emit_text("'''''") | |||||
| else: | |||||
| reset = self._head | |||||
| try: | |||||
| stack2 = self._parse(contexts.STYLE_BOLD) | |||||
| except BadRoute: | |||||
| self._head = reset | |||||
| self._emit_text("'''") | |||||
| self._emit_tag_open("i", "''") | |||||
| self._emit_all(stack) | |||||
| self._emit_tag_close("i") | |||||
| else: | |||||
| self._emit_tag_open("b", "'''") | |||||
| self._emit_tag_open("i", "''") | |||||
| self._emit_all(stack) | |||||
| self._emit_tag_close("i") | |||||
| self._emit_all(stack2) | |||||
| self._emit_tag_close("b") | |||||
| else: | |||||
| reset = self._head | |||||
| try: | |||||
| stack2 = self._parse(contexts.STYLE_ITALICS) | |||||
| except BadRoute: | |||||
| self._head = reset | |||||
| self._emit_text("''") | |||||
| self._emit_tag_open("b", "'''") | |||||
| self._emit_all(stack) | |||||
| self._emit_tag_close("b") | |||||
| else: | |||||
| self._emit_tag_open("i", "''") | |||||
| self._emit_tag_open("b", "'''") | |||||
| self._emit_all(stack) | |||||
| self._emit_tag_close("b") | |||||
| self._emit_all(stack2) | |||||
| self._emit_tag_close("i") | |||||
| def _parse_style(self): | def _parse_style(self): | ||||
| """Parse wiki-style formatting (``''``/``'''`` for italics/bold).""" | """Parse wiki-style formatting (``''``/``'''`` for italics/bold).""" | ||||
| self._head += 2 | self._head += 2 | ||||
| @@ -650,7 +736,8 @@ class Tokenizer(object): | |||||
| while self._read() == "'": | while self._read() == "'": | ||||
| self._head += 1 | self._head += 1 | ||||
| ticks += 1 | ticks += 1 | ||||
| reset = self._head | |||||
| italics = self._context & contexts.STYLE_ITALICS | |||||
| bold = self._context & contexts.STYLE_BOLD | |||||
| if ticks > 5: | if ticks > 5: | ||||
| self._emit_text("'" * (ticks - 5)) | self._emit_text("'" * (ticks - 5)) | ||||
| @@ -659,127 +746,24 @@ class Tokenizer(object): | |||||
| self._emit_text("'") | self._emit_text("'") | ||||
| ticks = 3 | ticks = 3 | ||||
| if ticks == 2: | |||||
| if self._context & contexts.STYLE_ITALICS: | |||||
| return self._pop() | |||||
| if self._can_recurse(): | |||||
| try: | |||||
| self._really_parse_style(contexts.STYLE_ITALICS) | |||||
| except BadRoute: | |||||
| self._head = reset | |||||
| try: ## only if STYLE_PASS_AGAIN in destroyed context | |||||
| self._really_parse_style(contexts.STYLE_ITALICS|contexts.STYLE_PASS_2) | |||||
| except BadRoute: | |||||
| self._head = reset | |||||
| self._emit_text("''") | |||||
| else: | |||||
| self._emit_text("''") | |||||
| if (italics and ticks in (2, 5)) or (bold and ticks in (3, 5)): | |||||
| if ticks == 5: | |||||
| self._head -= 3 if italics else 2 | |||||
| return self._pop() | |||||
| elif not self._can_recurse(): | |||||
| if ticks == 3: | |||||
| if self._context & contexts.STYLE_PASS_2: | |||||
| self._emit_text("'") | |||||
| return self._pop() | |||||
| # Set STYLE_PASS_AGAIN | |||||
| self._emit_text("'" * ticks) | |||||
| elif ticks == 2: | |||||
| self._parse_italics() | |||||
| elif ticks == 3: | elif ticks == 3: | ||||
| if self._context & contexts.STYLE_BOLD: | |||||
| if self._parse_bold(): | |||||
| return self._pop() | return self._pop() | ||||
| elif self._can_recurse(): | |||||
| try: | |||||
| self._really_parse_style(contexts.STYLE_BOLD) | |||||
| except BadRoute: | |||||
| self._head = reset | |||||
| if self._context & contexts.STYLE_ITALICS: | |||||
| if self._context & contexts.STYLE_PASS_2: | |||||
| self._emit_text("'") | |||||
| return self._pop() | |||||
| self._emit_text("'''") ## here is our hook for STYLE_PASS_AGAIN | |||||
| else: | |||||
| self._emit_text("'") | |||||
| try: | |||||
| self._really_parse_style(contexts.STYLE_ITALICS) | |||||
| except BadRoute: | |||||
| self._head = reset | |||||
| try: ## only if STYLE_PASS_AGAIN in destroyed context | |||||
| self._really_parse_style(contexts.STYLE_ITALICS|contexts.STYLE_PASS_2) | |||||
| except BadRoute: | |||||
| self._head = reset | |||||
| self._emit_text("''") | |||||
| elif self._context & contexts.STYLE_ITALICS and self._context & contexts.STYLE_PASS_2: | |||||
| self._emit_text("'") | |||||
| return self._pop() | |||||
| else: ## here is our hook for STYLE_PASS_AGAIN | |||||
| self._emit_text("'''") | |||||
| elif ticks == 5: | elif ticks == 5: | ||||
| if self._context & contexts.STYLE_ITALICS: | |||||
| self._head -= 3 | |||||
| return self._pop() | |||||
| elif self._context & contexts.STYLE_BOLD: | |||||
| self._head -= 2 | |||||
| return self._pop() | |||||
| elif self._can_recurse(): | |||||
| try: | |||||
| stack = self._parse(contexts.STYLE_BOLD) | |||||
| except BadRoute: | |||||
| self._head = reset | |||||
| try: | |||||
| stack = self._parse(contexts.STYLE_ITALICS) | |||||
| except BadRoute: | |||||
| self._head = reset | |||||
| self._emit_text("'''''") | |||||
| else: | |||||
| reset = self._head | |||||
| try: | |||||
| stack2 = self._parse(contexts.STYLE_BOLD) | |||||
| except BadRoute: | |||||
| self._head = reset | |||||
| self._emit_text("'''") | |||||
| self._emit(tokens.TagOpenOpen(wiki_markup="''")) | |||||
| self._emit_text("i") | |||||
| self._emit(tokens.TagCloseOpen()) | |||||
| self._emit_all(stack) | |||||
| self._emit(tokens.TagOpenClose()) | |||||
| self._emit_text("i") | |||||
| self._emit(tokens.TagCloseClose()) | |||||
| else: | |||||
| self._emit(tokens.TagOpenOpen(wiki_markup="'''")) | |||||
| self._emit_text("b") | |||||
| self._emit(tokens.TagCloseOpen()) | |||||
| self._emit(tokens.TagOpenOpen(wiki_markup="''")) | |||||
| self._emit_text("i") | |||||
| self._emit(tokens.TagCloseOpen()) | |||||
| self._emit_all(stack) | |||||
| self._emit(tokens.TagOpenClose()) | |||||
| self._emit_text("i") | |||||
| self._emit(tokens.TagCloseClose()) | |||||
| self._emit_all(stack2) | |||||
| self._emit(tokens.TagOpenClose()) | |||||
| self._emit_text("b") | |||||
| self._emit(tokens.TagCloseClose()) | |||||
| else: | |||||
| reset = self._head | |||||
| try: | |||||
| stack2 = self._parse(contexts.STYLE_ITALICS) | |||||
| except BadRoute: | |||||
| self._head = reset | |||||
| self._emit_text("''") | |||||
| self._emit(tokens.TagOpenOpen(wiki_markup="'''")) | |||||
| self._emit_text("b") | |||||
| self._emit(tokens.TagCloseOpen()) | |||||
| self._emit_all(stack) | |||||
| self._emit(tokens.TagOpenClose()) | |||||
| self._emit_text("b") | |||||
| self._emit(tokens.TagCloseClose()) | |||||
| else: | |||||
| self._emit(tokens.TagOpenOpen(wiki_markup="''")) | |||||
| self._emit_text("i") | |||||
| self._emit(tokens.TagCloseOpen()) | |||||
| self._emit(tokens.TagOpenOpen(wiki_markup="'''")) | |||||
| self._emit_text("b") | |||||
| self._emit(tokens.TagCloseOpen()) | |||||
| self._emit_all(stack) | |||||
| self._emit(tokens.TagOpenClose()) | |||||
| self._emit_text("b") | |||||
| self._emit(tokens.TagCloseClose()) | |||||
| self._emit_all(stack2) | |||||
| self._emit(tokens.TagOpenClose()) | |||||
| self._emit_text("i") | |||||
| self._emit(tokens.TagCloseClose()) | |||||
| else: | |||||
| self._emit_text("'''''") | |||||
| self._parse_italics_and_bold() | |||||
| self._head -= 1 | self._head -= 1 | ||||
| def _handle_list_marker(self): | def _handle_list_marker(self): | ||||