docs: def _parse(self, context=0, push=True):
          """Parse the wikicode string, using *context* for when to stop."""
          if push:
              self._push(context)
          while True:
              this = self._read()
              if self._context & contexts.UNSAFE:
                  if not self._verify_safe(this):
                      if self._context & contexts.DOUBLE:
                          self._pop()
                      self._fail_route()
              if this not in self.MARKERS:
                  self._emit_text(this)
                  self._head += 1
                  continue
              if this is self.END:
                  return self._handle_end()
              next = self._read(1)
              if this == next == "{":
                  if self._can_recurse():
                      self._parse_template_or_argument()
                  else:
                      self._emit_text("{")
              elif this == "|" and self._context & contexts.TEMPLATE:
                  self._handle_template_param()
              elif this == "=" and self._context & contexts.TEMPLATE_PARAM_KEY:
                  self._handle_template_param_value()
              elif this == next == "}" and self._context & contexts.TEMPLATE:
                  return self._handle_template_end()
              elif this == "|" and self._context & contexts.ARGUMENT_NAME:
                  self._handle_argument_separator()
              elif this == next == "}" and self._context & contexts.ARGUMENT:
                  if self._read(2) == "}":
                      return self._handle_argument_end()
                  else:
                      self._emit_text("}")
              elif this == next == "[" and self._can_recurse():
                  if not self._context & contexts.NO_WIKILINKS:
                      self._parse_wikilink()
                  else:
                      self._emit_text("[")
              elif this == "|" and self._context & contexts.WIKILINK_TITLE:
                  self._handle_wikilink_separator()
              elif this == next == "]" and self._context & contexts.WIKILINK:
                  return self._handle_wikilink_end()
              elif this == "[":
                  self._parse_external_link(True)
              elif this == ":" and self._read(-1) not in self.MARKERS:
                  self._parse_external_link(False)
              elif this == "]" and self._context & contexts.EXT_LINK_TITLE:
                  return self._pop()
              elif this == "=" and not self._global & contexts.GL_HEADING:
                  if self._read(-1) in ("\n", self.START):
                      self._parse_heading()
                  else:
                      self._emit_text("=")
              elif this == "=" and self._context & contexts.HEADING:
                  return self._handle_heading_end()
              elif this == "\n" and self._context & contexts.HEADING:
                  self._fail_route()
              elif this == "&":
                  self._parse_entity()
              elif this == "<" and next == "!":
                  if self._read(2) == self._read(3) == "-":
                      self._parse_comment()
                  else:
                      self._emit_text(this)
              elif this == "<" and next == "/" and self._read(2) is not self.END:
                  if self._context & contexts.TAG_BODY:
                      self._handle_tag_open_close()
                  else:
                      self._handle_invalid_tag_start()
              elif this == "<" and not self._context & contexts.TAG_CLOSE:
                  if self._can_recurse():
                      self._parse_tag()
                  else:
                      self._emit_text("<")
              elif this == ">" and self._context & contexts.TAG_CLOSE:
                  return self._handle_tag_close_close()
              elif this == next == "'" and not self._skip_style_tags:
                  result = self._parse_style()
                  if result is not None:
                      return result
              elif self._read(-1) in ("\n", self.START) and this in ("#", "*", ";", ":"):
                  self._handle_list()
              elif self._read(-1) in ("\n", self.START) and (
                      this == next == self._read(2) == self._read(3) == "-"):
                  self._handle_hr()
              elif this in ("\n", ":") and self._context & contexts.DL_TERM:
                  self._handle_dl_term()
                  if this == "\n":
                      # Kill potential table contexts
                      self._context &= ~contexts.TABLE_CELL_LINE_CONTEXTS
              # Start of table parsing
              elif this == "{" and next == "|" and (
                      self._read(-1) in ("\n", self.START) or
                      (self._read(-2) in ("\n", self.START) and self._read(-1).isspace())):
                  if self._can_recurse():
                      self._parse_table()
                  else:
                      self._emit_text("{")
              elif self._context & contexts.TABLE_OPEN:
                  if this == next == "|" and self._context & contexts.TABLE_TD_LINE:
                      if self._context & contexts.TABLE_CELL_OPEN:
                          return self._handle_table_cell_end()
                      self._handle_table_cell("||", "td", contexts.TABLE_TD_LINE)
                  elif this == next == "|" and self._context & contexts.TABLE_TH_LINE:
                      if self._context & contexts.TABLE_CELL_OPEN:
                          return self._handle_table_cell_end()
                      self._handle_table_cell("||", "th", contexts.TABLE_TH_LINE)
                  elif this == next == "!" and self._context & contexts.TABLE_TH_LINE:
                      if self._context & contexts.TABLE_CELL_OPEN:
                          return self._handle_table_cell_end()
                      self._handle_table_cell("!!", "th", contexts.TABLE_TH_LINE)
                  elif this == "|" and self._context & contexts.TABLE_CELL_STYLE:
                      return self._handle_table_cell_end(reset_for_style=True)
                  # on newline, clear out cell line contexts
                  elif this == "\n" and self._context & contexts.TABLE_CELL_LINE_CONTEXTS:
                      self._context &= ~contexts.TABLE_CELL_LINE_CONTEXTS
                      self._emit_text(this)
                  elif (self._read(-1) in ("\n", self.START) or
                        (self._read(-2) in ("\n", self.START) and self._read(-1).isspace())):
                      if this == "|" and next == "}":
                          if self._context & contexts.TABLE_CELL_OPEN:
                              return self._handle_table_cell_end()
                          if self._context & contexts.TABLE_ROW_OPEN:
                              return self._handle_table_row_end()
                          return self._handle_table_end()
                      elif this == "|" and next == "-":
                          if self._context & contexts.TABLE_CELL_OPEN:
                              return self._handle_table_cell_end()
                          if self._context & contexts.TABLE_ROW_OPEN:
                              return self._handle_table_row_end()
                          self._handle_table_row()
                      elif this == "|":
                          if self._context & contexts.TABLE_CELL_OPEN:
                              return self._handle_table_cell_end()
                          self._handle_table_cell("|", "td", contexts.TABLE_TD_LINE)
                      elif this == "!":
                          if self._context & contexts.TABLE_CELL_OPEN:
                              return self._handle_table_cell_end()
                          self._handle_table_cell("!", "th", contexts.TABLE_TH_LINE)
                      else:
                          self._emit_text(this)
                  else:
                      self._emit_text(this)
  
              else:
                  self._emit_text(this)
              self._head += 1