def make_token_dict(sentences, pad_token=None, extra_tokens=None):
    """Extract tokens from tokenized *sentences*, remove all duplicates, sort
    the resulting set and map all tokens onto ther indices.

    :param sentences: tokenized sentences.
    :type sentences: list([list([str])])
    :param pad_token: add a token for padding.
    :type pad_char: str
    :param extra_tokens: add any tokens for other purposes.
    :type extra_tokens: list([str])
    :return: the dict created and the index of the padding token (it's
        always the last index, if pad_token is not None); the indices of
        the extra tokens.
    :rtype: tuple(dict({char: int}), int, list([int])|None)
    """
    t2idx = {
        x: i for i, x in enumerate(sorted(set(
            x for x in sentences for x in x
        )))
    }

    def add_token(token):
        if token:
            assert token not in t2idx, \
                   "ERROR: token '{}' is already in the dict".format(token)
            idx = t2idx[token] = len(t2idx)
        else:
            idx = None
        return idx

    if extra_tokens is not None:
        extra_idxs = [add_token(t) for t in extra_tokens]
    else:
        extra_idxs = None
    pad_idx = add_token(pad_token)

    return t2idx, pad_idx, extra_idxs