def make_alphabet(sentences, pad_char=None, extra_chars=None,
                  allowed_chars=None, exclude_chars=None):
    """Make alphabet from the given corpus of tokenized *sentences*.

    :param sentences: tokenized sentences.
    :type sentences: list([list([str])])
    :param pad_char: add a token for padding.
    :type pad_char: str
    :param extra_chars: add tokens for other purposes.
    :type extra_chars: list([str])
    :param allowed_chars: if not None, all charactes not from *allowed_chars*
        will be removed.
    :type allowed_chars: str|list([str])
    :param exclude_chars: if not None, all charactes from *exclude_chars* will
        be removed.
    :type exclude_chars: str|list([str])
    :return: the alphabet created; the index of the padding token (it's always
        the last index, if pad_char is not None); the indices of the extra
        characters.
    :rtype: tuple(dict({char: int}), int, list([int])|None)
    """
    abc = {
        x: i for i, x in enumerate(sorted(set(
            x for x in sentences
                if (not allowed_chars or x in allowed_chars)
               and (not exclude_chars or x not in exclude_chars)
                for x in x for x in x
        )))
    }

    def add_char(char):
        if char:
            assert char not in abc, \
                   "ERROR: char '{}' is already in the alphabet".format(char)
            idx = abc[char] = len(abc)
        else:
            idx = None
        return idx

    if extra_chars is not None:
        extra_idxs = [add_char(c) for c in extra_chars]
    else:
        extra_idxs = None
    pad_idx = add_char(pad_char)

    return abc, pad_idx, extra_idxs