def spanstring2tokens(docgraph, span_string):
    """
    Converts a span string (e.g. 'word_88..word_91') into a list of token
    IDs (e.g. ['word_88', 'word_89', 'word_90', 'word_91']. Token IDs that
    do not occur in the given document graph will be filtered out.

    Q: Why are some token IDs missing in a document graph?
    A: They either have been removed manually (e.g. because someone thought
       the annotation/tokenization was 'wrong') or have been renamed
       during the merging of several document graphs.

    Parameters
    ----------
    docgraph : MMAXDocumentGraph
        a document graph which represent an MMAX2 annotated document
    span_string : str
        a string representing a (non)-contiguous series of tokens by their
        token IDs

    Returns
    -------
    existing_tokens : list of str
        a list of all those tokens that are represented by the span string
        and which actually exist in the given graph
    """
    tokens = convert_spanstring(span_string)
    existing_nodes = set(docgraph.nodes())

    existing_tokens = []
    for tok in tokens:
        if tok in existing_nodes:
            existing_tokens.append(tok)
        else: # we're trying to catch all token IDs that have been
              # renamed during merging of document graphs / annotation layers
            if hasattr(docgraph, 'renamed_nodes'):
                renamed_token_id = docgraph.renamed_nodes.get(tok)
                if renamed_token_id in existing_nodes:
                    existing_tokens.append(renamed_token_id)
            # else: there was no merging /renaming going on, so the
            # token is missing because it's <word> element was removed
            # from the associated *_words.xml file.
            # This is another 'bug' in the PCC corpus, cf. issue #134
    return existing_tokens