def _parse_table(
        self, parent_name=None
    ):  # type: (Optional[str]) -> Tuple[Key, Union[Table, AoT]]
        """
        Parses a table element.
        """
        if self._current != "[":
            raise self.parse_error(
                InternalParserError, "_parse_table() called on non-bracket character."
            )

        indent = self.extract()
        self.inc()  # Skip opening bracket

        if self.end():
            raise self.parse_error(UnexpectedEofError)

        is_aot = False
        if self._current == "[":
            if not self.inc():
                raise self.parse_error(UnexpectedEofError)

            is_aot = True

        # Key
        self.mark()
        while self._current != "]" and self.inc():
            if self.end():
                raise self.parse_error(UnexpectedEofError)

            pass

        name = self.extract()
        if not name.strip():
            raise self.parse_error(EmptyTableNameError)

        key = Key(name, sep="")
        name_parts = tuple(self._split_table_name(name))
        missing_table = False
        if parent_name:
            parent_name_parts = tuple(self._split_table_name(parent_name))
        else:
            parent_name_parts = tuple()

        if len(name_parts) > len(parent_name_parts) + 1:
            missing_table = True

        name_parts = name_parts[len(parent_name_parts) :]

        values = Container(True)

        self.inc()  # Skip closing bracket
        if is_aot:
            # TODO: Verify close bracket
            self.inc()

        cws, comment, trail = self._parse_comment_trail()

        result = Null()

        if len(name_parts) > 1:
            if missing_table:
                # Missing super table
                # i.e. a table initialized like this: [foo.bar]
                # without initializing [foo]
                #
                # So we have to create the parent tables
                table = Table(
                    Container(True),
                    Trivia(indent, cws, comment, trail),
                    is_aot and name_parts[0].key in self._aot_stack,
                    is_super_table=True,
                    name=name_parts[0].key,
                )

                result = table
                key = name_parts[0]

                for i, _name in enumerate(name_parts[1:]):
                    if _name in table:
                        child = table[_name]
                    else:
                        child = Table(
                            Container(True),
                            Trivia(indent, cws, comment, trail),
                            is_aot and i == len(name_parts[1:]) - 1,
                            is_super_table=i < len(name_parts[1:]) - 1,
                            name=_name.key,
                            display_name=name if i == len(name_parts[1:]) - 1 else None,
                        )

                    if is_aot and i == len(name_parts[1:]) - 1:
                        table.append(_name, AoT([child], name=table.name, parsed=True))
                    else:
                        table.append(_name, child)

                    table = child
                    values = table.value
        else:
            if name_parts:
                key = name_parts[0]

        while not self.end():
            item = self._parse_item()
            if item:
                _key, item = item
                if not self._merge_ws(item, values):
                    if _key is not None and _key.is_dotted():
                        self._handle_dotted_key(values, _key, item)
                    else:
                        values.append(_key, item)
            else:
                if self._current == "[":
                    is_aot_next, name_next = self._peek_table()

                    if self._is_child(name, name_next):
                        key_next, table_next = self._parse_table(name)

                        values.append(key_next, table_next)

                        # Picking up any sibling
                        while not self.end():
                            _, name_next = self._peek_table()

                            if not self._is_child(name, name_next):
                                break

                            key_next, table_next = self._parse_table(name)

                            values.append(key_next, table_next)

                    break
                else:
                    raise self.parse_error(
                        InternalParserError,
                        "_parse_item() returned None on a non-bracket character.",
                    )

        if isinstance(result, Null):
            result = Table(
                values,
                Trivia(indent, cws, comment, trail),
                is_aot,
                name=name,
                display_name=name,
            )

            if is_aot and (not self._aot_stack or name != self._aot_stack[-1]):
                result = self._parse_aot(result, name)

        return key, result
Parses a table element.