<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def build_toc(filename: str, ordered: bool = False, no_links: bool = False, no_indentation: bool = False, no_list_coherence: bool = False, keep_header_levels: int = 3, parser: str = 'github', list_marker: str = '-') -> str: r"""Build the table of contents of a single file. :parameter filename: the file that needs to be read. :parameter ordered: decides whether to build an ordered list or not. Defaults to ``False``. :parameter no_links: disables the use of links. Defaults to ``False``. :parameter no_indentation: disables indentation in the list. Defaults to ``False``. :parameter keep_header_levels: the maximum level of headers to be considered as such when building the table of contents. Defaults to ``3``. :parameter parser: decides rules on how to generate anchor links. Defaults to ``github``. :type filename: str :type ordered: bool :type no_links: bool :type no_indentation: bool :type keep_header_levels: int :type parser: str :returns: toc, the corresponding table of contents of the file. :rtype: str :raises: a built-in exception. """

    toc = str()
    header_type_counter = dict()
    header_type_curr = 0
    header_type_prev = 0
    header_duplicate_counter = dict()
    no_of_indentation_spaces_prev = 0
    if ordered:
        list_marker_log = build_list_marker_log(parser, list_marker)
    if filename == '-':
        f = sys.stdin
    else:
        f = open(filename, 'r')
    line = f.readline()
    if ordered:
        list_marker_log = build_list_marker_log(parser, list_marker)
    else:
        list_marker_log = list()
    is_within_code_fence = False
    code_fence = None
    is_document_end = False
    if not no_indentation and not no_list_coherence:
        # if indentation and list coherence.
        indentation_list = build_indentation_list(parser)
    while line:
        # Document ending detection.
        #
        # This changes the state of is_within_code_fence if the
        # file has no closing fence markers. This serves no practial
        # purpose since the code would run correctly anyway. It is
        # however more sematically correct.
        #
        # See the unit tests (examples 95 and 96 of the github parser)
        # and the is_closing_code_fence function.
        if filename != '-':
            # stdin is not seekable.
            file_pointer_pos = f.tell()
            if f.readline() == str():
                is_document_end = True
            f.seek(file_pointer_pos)

        # Code fence detection.
        if is_within_code_fence:
            is_within_code_fence = not is_closing_code_fence(
                line, code_fence, is_document_end, parser)
            line = f.readline()
        else:
            code_fence = is_opening_code_fence(line, parser)
            if code_fence is not None:
                # Update the status of the next line.
                is_within_code_fence = True
                line = f.readline()

        if not is_within_code_fence or code_fence is None:

            # Header detection and gathering.
            header = get_md_header(line, header_duplicate_counter,
                                   keep_header_levels, parser, no_links)
            if header is not None:
                header_type_curr = header['type']

                # Take care of the ordered TOC.
                if ordered:
                    increase_index_ordered_list(header_type_counter,
                                                header_type_prev,
                                                header_type_curr, parser)
                    index = header_type_counter[header_type_curr]
                else:
                    index = 1

                # Take care of list indentations.
                if no_indentation:
                    no_of_indentation_spaces_curr = 0
                    # TOC list coherence checks are not necessary
                    # without indentation.
                else:
                    if not no_list_coherence:
                        if not toc_renders_as_coherent_list(
                                header_type_curr, indentation_list, parser):
                            raise TocDoesNotRenderAsCoherentList
                    no_of_indentation_spaces_curr = compute_toc_line_indentation_spaces(
                        header_type_curr, header_type_prev,
                        no_of_indentation_spaces_prev, parser, ordered,
                        list_marker, list_marker_log, index)

                # Build a single TOC line.
                toc_line_no_indent = build_toc_line_without_indentation(
                    header, ordered, no_links, index, parser, list_marker)

                # Save the TOC line with the indentation.
                toc += build_toc_line(toc_line_no_indent,
                                      no_of_indentation_spaces_curr) + '\n'

                header_type_prev = header_type_curr
                no_of_indentation_spaces_prev = no_of_indentation_spaces_curr

            # endif

        # endif

        line = f.readline()

    # endwhile

    f.close()

    return toc