def segment(self, word_phonemes: tuple, key_items: list) -> tuple:
"""Return per-token keys and per-token phones.
:param word_phonemes: (tuple) Pronunciation of each token ('-' separated phones).
:param key_items: (list) Cueing result: list of (keys_str, phones_str).
:return: (tuple) (codes_by_token, phones_by_token), each is a tuple of strings ('.' separated).
"""
words_phones = self.__parse_words(word_phonemes)
(flat_codes, flat_phons) = self.__flatten_key_items(key_items)
token_codes = [[] for _ in range(len(words_phones))]
token_phons = [[] for _ in range(len(words_phones))]
token_consumed = [False for _ in range(len(words_phones))]
cursor = _PhonesCursor(words_phones, token_consumed)
for i in range(len(flat_codes)):
code_item = flat_codes[i]
phon_item = flat_phons[i]
(consonants, vowels) = self.__parse_key_pair(phon_item)
token_index = None
if len(consonants) > 0:
token_index = cursor.consume(consonants, 'consonants')
cursor.advance_if_done()
if len(vowels) > 0:
token_index = cursor.consume(vowels, 'vowels')
if token_index is None:
raise ValueError('Key has neither consonant nor vowel phones: ' + phon_item)
token_codes[token_index].append(code_item)
token_phons[token_index].append(phon_item)
for i in range(len(words_phones)):
if token_consumed[i] is True and len(token_codes[i]) == 0:
token_codes[i].append(self.__PLACEHOLDER_CODE)
token_phons[i].append(self.__PLACEHOLDER_PHON)
codes_by_token = tuple(['.'.join(items) for items in token_codes])
phons_by_token = tuple(['.'.join(items) for items in token_phons])
return (codes_by_token, phons_by_token)