Returns a list of 5-tuples describing each RST span (i.e. the nucleus
    or satellite of a relation) in the document. (This function is meant for
    people who prefer to work with R / DataFrames / CSV files instead of
    graphs.)

    Parameters
    ----------
    docgraph : DiscourseDocumentGraph
        a document graph which contains RST annotations

    Returns
    -------
    all_spans : list of (str, str, str, int, int)
        each list element represents an RST span (i.e. the nucleus or satellite)
        as a 5-tuple
        (relation string, span type, relation type, token onset, token offset).
        In the example ('rst:16-rst:2', 'N', 'evaluation-s', 9, 24), the
        relation string 'rst:16-rst:2' consists of two parts, the relation root
        node ID and the node ID of its nucleus (span type 'N').
        In the example ('rst:16-rst:4-rst:3', 'N1', 'list', 20, 24), the
        relation string consists of 3 parts, the relation root
        node ID and the node IDs of its nucleii (span type 'N1', 'N2').

    Examples
    --------
        [('rst:16-rst:4-rst:3', 'N1', 'list', 20, 24),
        ('rst:16-rst:4-rst:3', 'N2', 'list', 9, 19),
        ('rst:16-rst:2', 'N', 'evaluation-s', 9, 24),
        ('rst:16-rst:2', 'S', 'evaluation-s', 4, 8)]

def get_rst_spans(rst_graph):
    """
    Returns a list of 5-tuples describing each RST span (i.e. the nucleus
    or satellite of a relation) in the document. (This function is meant for
    people who prefer to work with R / DataFrames / CSV files instead of
    graphs.)

    Parameters
    ----------
    docgraph : DiscourseDocumentGraph
        a document graph which contains RST annotations

    Returns
    -------
    all_spans : list of (str, str, str, int, int)
        each list element represents an RST span (i.e. the nucleus or satellite)
        as a 5-tuple
        (relation string, span type, relation type, token onset, token offset).
        In the example ('rst:16-rst:2', 'N', 'evaluation-s', 9, 24), the
        relation string 'rst:16-rst:2' consists of two parts, the relation root
        node ID and the node ID of its nucleus (span type 'N').
        In the example ('rst:16-rst:4-rst:3', 'N1', 'list', 20, 24), the
        relation string consists of 3 parts, the relation root
        node ID and the node IDs of its nucleii (span type 'N1', 'N2').

    Examples
    --------
        [('rst:16-rst:4-rst:3', 'N1', 'list', 20, 24),
        ('rst:16-rst:4-rst:3', 'N2', 'list', 9, 19),
        ('rst:16-rst:2', 'N', 'evaluation-s', 9, 24),
        ('rst:16-rst:2', 'S', 'evaluation-s', 4, 8)]
    """
    token_map = TokenMapper(rst_graph).id2index
    rst_relations = get_rst_relations(rst_graph)
    all_spans = []
    for dom_node in rst_relations:
        if 'multinuc' in rst_relations[dom_node]:
            nuc_count = 1
            multinuc_start, multinuc_end = sys.maxint, 0
            multinuc_spans = rst_relations[dom_node]['multinuc']
            multinuc_rel_id = "{0}-{1}".format(
                dom_node, '-'.join(target for target, _rel, _toks in multinuc_spans))

            for _, relname, toks in multinuc_spans:
                nuc_start, nuc_end = get_segment_token_offsets(toks, token_map)
                multinuc_span = (multinuc_rel_id, "N{}".format(nuc_count),
                                 relname, nuc_start, nuc_end)
                all_spans.append(multinuc_span)
                nuc_count += 1
                # determine the token offsets of the whole multinuc relation iteratively
                if nuc_start < multinuc_start:
                    multinuc_start = nuc_start
                if nuc_end > multinuc_end:
                    multinuc_end = nuc_end

        if 'satellites' in rst_relations[dom_node]:
            # find the nucleus
            if 'nucleus' in rst_relations[dom_node]:
                nuc_id, nuc_toks = rst_relations[dom_node]['nucleus']
                nuc_start, nuc_end = get_segment_token_offsets(nuc_toks, token_map)
            elif 'multinuc' in rst_relations[dom_node]:
                nuc_id = dom_node # multinuc as a whole is the nucleus
                nuc_start, nuc_end = multinuc_start, multinuc_end
            elif 'tokens' in rst_relations[dom_node]:
                nuc_id = dom_node # dominating segment node directly dominates these tokens
                nuc_start, nuc_end = get_segment_token_offsets(
                    rst_relations[dom_node]['tokens'], token_map)
            else:
                raise ValueError(
                    "Can't find a nucleus for these satellites: {}".format(
                        rst_relations[dom_node]['satellites']))

            sat_spans = rst_relations[dom_node]['satellites']
            for satellite, relname, sat_toks in sat_spans:
                sat_start, sat_end = get_segment_token_offsets(sat_toks, token_map)
                nucleus_span = ("{0}-{1}".format(nuc_id, satellite), 'N',
                                relname, nuc_start, nuc_end)
                all_spans.append(nucleus_span)
                satellite_span = ("{0}-{1}".format(nuc_id, satellite), 'S',
                                  relname, sat_start, sat_end)
                all_spans.append(satellite_span)
    return all_spans