code: def _parse_thead_tbody_tfoot(self, table_html):
          
  
          header_rows = self._parse_thead_tr(table_html)
          body_rows = self._parse_tbody_tr(table_html)
          footer_rows = self._parse_tfoot_tr(table_html)
  
          def row_is_all_th(row):
              return all(self._equals_tag(t, 'th') for t in
                         self._parse_td(row))
  
          if not header_rows:
              # The table has no <thead>. Move the top all-<th> rows from
              # body_rows to header_rows. (This is a common case because many
              # tables in the wild have no <thead> or <tfoot>
              while body_rows and row_is_all_th(body_rows[0]):
                  header_rows.append(body_rows.pop(0))
  
          header = self._expand_colspan_rowspan(header_rows)
          body = self._expand_colspan_rowspan(body_rows)
          footer = self._expand_colspan_rowspan(footer_rows)
  
          return header, body, footer
docs: Given a table, return parsed header, body, and foot.
  
          Parameters
          ----------
          table_html : node-like
  
          Returns
          -------
          tuple of (header, body, footer), each a list of list-of-text rows.
  
          Notes
          -----
          Header and body are lists-of-lists. Top level list is a list of
          rows. Each row is a list of str text.
  
          Logic: Use <thead>, <tbody>, <tfoot> elements to identify
                 header, body, and footer, otherwise:
                 - Put all rows into body
                 - Move rows from top of body to header only if
                   all elements inside row are <th>
                 - Move rows from bottom of body to footer only if
                   all elements inside row are <th>