def _parse_thead_tbody_tfoot(self, table_html):
header_rows = self._parse_thead_tr(table_html)<EOL>body_rows = self._parse_tbody_tr(table_html)<EOL>footer_rows = self._parse_tfoot_tr(table_html)<EOL>def row_is_all_th(row):<EOL><INDENT>return all(self._equals_tag(t, '<STR_LIT>') for t in<EOL>self._parse_td(row))<EOL><DEDENT>if not header_rows:<EOL><INDENT>while body_rows and row_is_all_th(body_rows[<NUM_LIT:0>]):<EOL><INDENT>header_rows.append(body_rows.pop(<NUM_LIT:0>))<EOL><DEDENT><DEDENT>header = self._expand_colspan_rowspan(header_rows)<EOL>body = self._expand_colspan_rowspan(body_rows)<EOL>footer = self._expand_colspan_rowspan(footer_rows)<EOL>return header, body, footer<EOL>
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>