If a VVV-sequence contains a long vowel, there is a syllable boundary
    between it and the third vowel, e.g. [kor.ke.aa], [yh.ti.öön], [ruu.an],
    [mää.yt.te].
553462
def apply_T6(word):
    ''''''
    WORD = word
    offset = 0

    for vvv in vvv_sequences(WORD):
        seq = vvv.group(2)
        j = 2 if is_long(seq[:2]) else 1 if is_long(seq[1:]) else 0

        if j:
            i = vvv.start(2) + j + offset
            WORD = WORD[:i] + '.' + WORD[i:]
            offset += 1

    RULE = ' T6' if word != WORD else ''

    return WORD, RULE
632019
def is_rhyme(d, w1, w2):
    """"""
    for p1 in d[w1]:
        # extract only "rhyming portion"
        p1 = p1.split("'")[-1]
        m = VOWELS_RE.search(p1)
        if not m:
            print(p1)
        p1 = p1[m.start():]
        for p2 in d[w2]:
            p2 = p2.split("'")[-1]
            m = VOWELS_RE.search(p2)
            if not m:
                print(w2, p2)
            p2 = p2[m.start():]
            if p1 == p2:
                return True
    return False
987819
def apply_T11(word):
    ''''''
    WORD = word
    offset = 0

    for vvv in t11_vvv_sequences(WORD):
        # i = vvv.start(1) + (1 if vvv.group(1).startswith('i') else 2) + offset
        i = vvv.start(1) + (1 if vvv.group(1)[-1] in 'uy' else 2) + offset
        WORD = WORD[:i] + '.' + WORD[i:]
        offset += 1

    RULE = ' T11' if word != WORD else ''

    return WORD, RULE
446635
def _equivalent(self, char, prev, next, implicitA):
        
        result = []
        if char.unichr != DevanagariCharacter._VIRAMA:
            result.append(char.equivalents[self.name])
        """ Append implicit A to consonants if the next character isn't a vowel. """
        if implicitA and char.isConsonant \
        and ((next is not None \
        and next.unichr != DevanagariCharacter._VIRAMA \
        and not next.isVowel) \
        or next is None):
            result.append(characterBlocks['DEVANAGARI']\
                   [DevanagariCharacter._LETTER_A].equivalents[self.name])
        return result
1348046
protected function vowelinstem()
    {
        for ($i = 0; $i <= $this->j; $i++) {
            if (! $this->cons($i))
                return true;
        }

        return false;
    }
1042588
public static function initial_reordering_syllable (&$info, $GSUBdata, $indic_config, $scriptblock, $is_old_spec, $start, $end) {
	/* vowel_syllable: We made the vowels look like consonants. So uses the consonant logic! */
	/* broken_cluster: We already inserted dotted-circles, so just call the standalone_cluster. */
	/* standalone_cluster: We treat NBSP/dotted-circle as if they are consonants, so we should just chain. */

	$syllable_type = ($info[$start]['syllable'] & 0x0F);
	if ($syllable_type==self::NON_INDIC_CLUSTER ) { return; }
	if ($syllable_type==self::BROKEN_CLUSTER  || $syllable_type==self::STANDALONE_CLUSTER ) { 
		//if ($uniscribe_bug_compatible) {
		/* For dotted-circle, this is what Uniscribe does:
		* If dotted-circle is the last glyph, it just does nothing.
		* i.e. It doesn't form Reph. */
		if ($info[$end - 1]['indic_category'] == self::OT_DOTTEDCIRCLE) {
			return;
		}
	}

	/* 1. Find base consonant:
	*
	* The shaping engine finds the base consonant of the syllable, using the
	* following algorithm: starting from the end of the syllable, move backwards
	* until a consonant is found that does not have a below-base or post-base
	* form (post-base forms have to follow below-base forms), or that is not a
	* pre-base reordering Ra, or arrive at the first consonant. The consonant
	* stopped at will be the base.
	*
	*	o If the syllable starts with Ra + Halant (in a script that has Reph)
	*	and has more than one consonant, Ra is excluded from candidates for
	*	base consonants.
	*/

	$base = $end;
	$has_reph = false;
	$limit = $start;

	if ($scriptblock != UCDN::SCRIPT_KHMER) { 
		/* -> If the syllable starts with Ra + Halant (in a script that has Reph)
		*	and has more than one consonant, Ra is excluded from candidates for
		*	base consonants. */
		if (count($GSUBdata['rphf']) /* ?? $indic_plan->mask_array[RPHF] */ && $start + 3 <= $end &&
			(
			($indic_config[4] == self::REPH_MODE_IMPLICIT && !self::is_joiner($info[$start + 2])) ||
			($indic_config[4] == self::REPH_MODE_EXPLICIT && $info[$start + 2]['indic_category'] == self::OT_ZWJ)
			)) {
			/* See if it matches the 'rphf' feature. */
			//$glyphs = array($info[$start]['uni'], $info[$start + 1]['uni']);
			//if ($indic_plan->rphf->would_substitute ($glyphs, count($glyphs), true, face)) {
			if (isset($GSUBdata['rphf'][$info[$start]['uni']]) && self::is_halant_or_coeng($info[$start + 1]) ) {
				$limit += 2;
				while ($limit < $end && self::is_joiner($info[$limit]))
					$limit++;
				$base = $start;
				$has_reph = true;
			}
		}
		else if ($indic_config[4] == self::REPH_MODE_LOG_REPHA && $info[$start]['indic_category'] == self::OT_Repha) {
			$limit += 1;
			while ($limit < $end && self::is_joiner($info[$limit]))
				$limit++;
			$base = $start;
			$has_reph = true;
		}
	}

	switch ($indic_config[2]) {	// base_pos
		case self::BASE_POS_LAST:
			/* -> starting from the end of the syllable, move backwards */
			$i = $end;
			$seen_below = false;
			do {
				$i--;
				/* -> until a consonant is found */
				if (self::is_consonant($info[$i])) {
					/* -> that does not have a below-base or post-base form
					* (post-base forms have to follow below-base forms), */
					if ($info[$i]['indic_position'] != self::POS_BELOW_C && ($info[$i]['indic_position'] != self::POS_POST_C || $seen_below)) {
						$base = $i;
						break;
					}
					if ($info[$i]['indic_position'] == self::POS_BELOW_C)
						$seen_below = true;

					/* -> or that is not a pre-base reordering Ra,
					*
					* IMPLEMENTATION NOTES:
					*
					* Our pre-base reordering Ra's are marked POS_POST_C, so will be skipped
					* by the logic above already.
					*/

					/* -> or arrive at the first consonant. The consonant stopped at will
					* be the base. */
					$base = $i;
				}
				else {
					/* A ZWJ after a Halant stops the base search, and requests an explicit
					* half form. 
					* [A ZWJ before a Halant, requests a subjoined form instead, and hence
					* search continues. This is particularly important for Bengali
					* sequence Ra,H,Ya that should form Ya-Phalaa by subjoining Ya] */
					if ($start < $i && $info[$i]['indic_category'] == self::OT_ZWJ && $info[$i - 1]['indic_category'] == self::OT_H) {
						if (!defined("OMIT_INDIC_FIX_1") || OMIT_INDIC_FIX_1!=1) { $base = $i; }	// INDIC_FIX_1
						break;
					}
					// ZKI8
					if ($start < $i && $info[$i]['indic_category'] == self::OT_ZWNJ) {
						break;
					}
				}
			} while ($i > $limit);
			break;

		case self::BASE_POS_FIRST:
			/* In scripts without half forms (eg. Khmer), the first consonant is always the base. */

				if (!$has_reph)
					$base = $limit;

				/* Find the last base consonant that is not blocked by ZWJ.	If there is
				* a ZWJ right before a base consonant, that would request a subjoined form. */
				for ($i = $limit; $i < $end; $i++) {
					if (self::is_consonant($info[$i]) && $info[$i]['indic_position'] == self::POS_BASE_C) {
						if ($limit < $i && $info[$i - 1]['indic_category'] == self::OT_ZWJ)
							break;
						else
							$base = $i;
					}
				}

			/* Mark all subsequent consonants as below. */
			for ($i = $base + 1; $i < $end; $i++) {
				if (self::is_consonant ($info[$i]) && $info[$i]['indic_position'] == self::POS_BASE_C)
					$info[$i]['indic_position'] = self::POS_BELOW_C;
			}
			break;
		//default:
			//assert (false);
			/* fallthrough */
	}

	/* -> If the syllable starts with Ra + Halant (in a script that has Reph)
	*	and has more than one consonant, Ra is excluded from candidates for
	*	base consonants.
	*
	*	Only do this for unforced Reph. (ie. not for Ra,H,ZWJ. */
	if ($scriptblock != UCDN::SCRIPT_KHMER) { 
		if ($has_reph && $base == $start && $limit - $base <= 2) {
			/* Have no other consonant, so Reph is not formed and Ra becomes base. */
			$has_reph = false;
		}
	}

	/* 2. Decompose and reorder Matras:
	*
	* Each matra and any syllable modifier sign in the cluster are moved to the
	* appropriate position relative to the consonant(s) in the cluster. The
	* shaping engine decomposes two- or three-part matras into their constituent
	* parts before any repositioning. Matra characters are classified by which
	* consonant in a conjunct they have affinity for and are reordered to the
	* following positions:
	*
	*		o Before first half form in the syllable
	*		o After subjoined consonants
	*		o After post-form consonant
	*		o After main consonant (for above marks)
	*
	* IMPLEMENTATION NOTES:
	*
	* The normalize() routine has already decomposed matras for us, so we don't
	* need to worry about that.
	*/


	/* 3.	Reorder marks to canonical order:
	*
	* Adjacent nukta and halant or nukta and vedic sign are always repositioned
	* if necessary, so that the nukta is first.
	*
	* IMPLEMENTATION NOTES:
	*
	* Use the combining Class from Unicode categories? to bubble_sort.
	*/

	/* Reorder characters */

	for ($i = $start; $i < $base; $i++)
		$info[$i]['indic_position'] = min(self::POS_PRE_C, $info[$i]['indic_position']);

	if ($base < $end)
		$info[$base]['indic_position'] = self::POS_BASE_C;

	/* Mark final consonants. A final consonant is one appearing after a matra,
	* ? only in Khmer. */
	for ($i = $base + 1; $i < $end; $i++)
		if ($info[$i]['indic_category'] == self::OT_M) {
			for ($j = $i + 1; $j < $end; $j++)
				if (self::is_consonant ($info[$j])) {
					$info[$j]['indic_position'] = self::POS_FINAL_C;
					break;
				}
			break;
		}

	/* Handle beginning Ra */
	if ($scriptblock != UCDN::SCRIPT_KHMER) { 
		if ($has_reph)
			$info[$start]['indic_position'] = self::POS_RA_TO_BECOME_REPH;
   	}


	/* For old-style Indic script tags, move the first post-base Halant after
	* last consonant.	Only do this if there is *not* a Halant after last
	* consonant. Otherwise it becomes messy. */
	if ($is_old_spec) {
		for ($i = $base + 1; $i < $end; $i++) {
			if ($info[$i]['indic_category'] == self::OT_H) {
				for ($j = $end - 1; $j > $i; $j--) {
					if (self::is_consonant($info[$j]) || $info[$j]['indic_category'] == self::OT_H) { break; }
				}
				if ($info[$j]['indic_category'] != self::OT_H && $j > $i) {
					/* Move Halant to after last consonant. */
					self::_move_info_pos($info, $i, $j+1);
				}
				break;
			}
		}
	}

	/* Attach misc marks to previous char to move with them. */
	$last_pos = self::POS_START;
	for ($i = $start; $i < $end; $i++) {
		if ((self::FLAG($info[$i]['indic_category']) & (self::FLAG(self::OT_ZWJ)| self::FLAG(self::OT_ZWNJ) | self::FLAG(self::OT_N) | self::FLAG (self::OT_RS) | self::FLAG (self::OT_H) | self::FLAG (self::OT_Coeng) ))) {
			$info[$i]['indic_position'] = $last_pos;
			if ($info[$i]['indic_category'] == self::OT_H && $info[$i]['indic_position'] == self::POS_PRE_M) {
				/*
				* Uniscribe doesn't move the Halant with Left Matra.
				* TEST: U+092B,U+093F,U+094DE
				* We follow.	This is important for the Sinhala
				* U+0DDA split matra since it decomposes to U+0DD9,U+0DCA
				* where U+0DD9 is a left matra and U+0DCA is the virama.
				* We don't want to move the virama with the left matra.
				* TEST: U+0D9A,U+0DDA
				*/
				for ($j = $i; $j > $start; $j--)
					if ($info[$j - 1]['indic_position'] != self::POS_PRE_M) {
						$info[$i]['indic_position'] = $info[$j - 1]['indic_position'];
						break;
					}
			}
		}
		else if ($info[$i]['indic_position'] != self::POS_SMVD) {
			$last_pos = $info[$i]['indic_position'];
		}
	}

	/* Re-attach ZWJ, ZWNJ, and halant to next char, for after-base consonants. */
	$last_halant = $end;
	for ($i = $base + 1; $i < $end; $i++) {
		if (self::is_halant_or_coeng($info[$i]))
			$last_halant = $i;
		else if (self::is_consonant($info[$i])) {
			for ($j = $last_halant; $j < $i; $j++)
				if ($info[$j]['indic_position'] != self::POS_SMVD)
					$info[$j]['indic_position'] = $info[$i]['indic_position'];
		}
	}


	if ($scriptblock == UCDN::SCRIPT_KHMER) { 
		/* KHMER_FIX_2 */
		/* Move Coeng+RO (Halant,Ra) sequence before base consonant. */
		for ($i = $base + 1; $i < $end; $i++) {
			if (self::is_halant_or_coeng($info[$i]) && self::is_ra($info[$i + 1]['uni'])) {
				$info[$i]['indic_position'] = self::POS_PRE_C;
				$info[$i + 1]['indic_position'] = self::POS_PRE_C;
				break;
			}
		}
	}


/*
if (!defined("OMIT_INDIC_FIX_2") || OMIT_INDIC_FIX_2 != 1) {
	// INDIC_FIX_2
	$ZWNJ_found = false;
	$POST_ZWNJ_c_found = false;
	for ($i = $base + 1; $i < $end; $i++) {
		if ($info[$i]['indic_category'] == self::OT_ZWNJ) { $ZWNJ_found = true; }
		else if ($ZWNJ_found && $info[$i]['indic_category'] == self::OT_C) { $POST_ZWNJ_c_found = true; }
		else if ($POST_ZWNJ_c_found && $info[$i]['indic_position'] == self::POS_BEFORE_SUB) { $info[$i]['indic_position'] = self::POS_AFTER_SUB; }
	}
}
*/

	/* Setup masks now */
	for ($i = $start; $i < $end; $i++) {
		$info[$i]['mask'] = 0;
	}


	if ($scriptblock == UCDN::SCRIPT_KHMER) { 
		/* Find a Coeng+RO (Halant,Ra) sequence and mark it for pre-base processing. */
		$mask = self::FLAG(self::PREF);
		for ($i = $base; $i < $end-1; $i++) {	/* KHMER_FIX_1 From $start (not base) */
			if (self::is_halant_or_coeng($info[$i]) && self::is_ra($info[$i + 1]['uni'])  ) {

				$info[$i]['mask'] |= self::FLAG(self::PREF);
				$info[$i + 1]['mask'] |= self::FLAG(self::PREF);

				/* Mark the subsequent stuff with 'cfar'.  Used in Khmer.
				* Read the feature spec.
				* This allows distinguishing the following cases with MS Khmer fonts:
				* U+1784,U+17D2,U+179A,U+17D2,U+1782  [C+Coeng+RO+Coeng+C] => Should activate CFAR
				* U+1784,U+17D2,U+1782,U+17D2,U+179A  [C+Coeng+C+Coeng+RO] => Should NOT activate CFAR
				*/
				for ($j=($i+2); $j < $end; $j++)
					$info[$j]['mask'] |= self::FLAG(self::CFAR);

				break;
			}
		}
	}



	/* Sit tight, rock 'n roll! */
	self::bubble_sort ($info, $start, $end - $start);

	/* Find base again */
	$base = $end;
	for ($i = $start; $i < $end; $i++) {
		if ($info[$i]['indic_position'] == self::POS_BASE_C) {
			$base = $i;
			break;
		}
	}

	if ($scriptblock != UCDN::SCRIPT_KHMER) { 
		/* Reph */
		for ($i = $start; $i < $end; $i++) {
			if ($info[$i]['indic_position'] == self::POS_RA_TO_BECOME_REPH) {
				$info[$i]['mask'] |= self::FLAG(self::RPHF);
			}
		}

		/* Pre-base */
		$mask = self::FLAG(self::HALF);
		for ($i = $start; $i < $base; $i++) {
			$info[$i]['mask'] |= $mask;
		}
	}

	/* Post-base */
	$mask = (self::FLAG(self::BLWF) | self::FLAG(self::ABVF) | self::FLAG(self::PSTF));
	for ($i = $base + 1; $i < $end; $i++) {
		$info[$i]['mask'] |= $mask;
	}


	if ($scriptblock != UCDN::SCRIPT_KHMER) { 
	if (!defined("OMIT_INDIC_FIX_3") || OMIT_INDIC_FIX_3 != 1) {
		/* INDIC_FIX_3 */
		/* Find a (pre-base) Consonant, Halant,Ra sequence and mark Halant|Ra for below-base BLWF processing. */
		// TEST CASE &#x995;&#x9cd;&#x9b0;&#x9cd;&#x995; in FreeSans versus Vrinda
		if (($base - $start) >= 3) {
			for ($i = $start; $i < ($base-2); $i++) {
				if (self::is_consonant($info[$i])) {
					if (self::is_halant_or_coeng($info[$i + 1]) && self::is_ra($info[$i + 2]['uni'])) {
						// If would substitute Halant+Ra...BLWF
						if (isset($GSUBdata['blwf'][$info[$i+2]['uni']])) { 
							$info[$i + 1]['mask'] |= self::FLAG(self::BLWF);
							$info[$i + 2]['mask'] |= self::FLAG(self::BLWF);
	 					}
						/* If would not substitute as blwf, mark Ra+Halant for RPHF using following Halant (if present) */
						else if (self::is_halant_or_coeng($info[$i + 3])) {
							$info[$i + 2]['mask'] |= self::FLAG(self::RPHF);
							$info[$i + 3]['mask'] |= self::FLAG(self::RPHF);
						}
						break;
					}
				}
			}
		}
	}
	}



	if ($is_old_spec && $scriptblock == UCDN::SCRIPT_DEVANAGARI) {
		/* Old-spec eye-lash Ra needs special handling.	From the spec:
		* "The feature 'below-base form' is applied to consonants
		* having below-base forms and following the base consonant.
		* The exception is vattu, which may appear below half forms
		* as well as below the base glyph. The feature 'below-base
		* form' will be applied to all such occurrences of Ra as well."
		*
		* Test case: U+0924,U+094D,U+0930,U+094d,U+0915
		* with Sanskrit 2003 font.
		*
		* However, note that Ra,Halant,ZWJ is the correct way to
		* request eyelash form of Ra, so we wouldbn't inhibit it
		* in that sequence.
		*
		* Test case: U+0924,U+094D,U+0930,U+094d,U+200D,U+0915
		*/
		for ($i = $start; ($i + 1) < $base; $i++) {
			if ($info[$i]['indic_category'] == self::OT_Ra && $info[$i+1]['indic_category'] == self::OT_H &&
				($i + 2 == $base || $info[$i+2]['indic_category'] != self::OT_ZWJ)) {
				$info[$i]['mask'] |= self::FLAG(self::BLWF);
				$info[$i+1]['mask'] |= self::FLAG(self::BLWF);
			}
		}
	}

	if ($scriptblock != UCDN::SCRIPT_KHMER) { 
		if (count($GSUBdata['pref']) && $base + 2 < $end) {
			/* Find a Halant,Ra sequence and mark it for pre-base processing. */
			for ($i = $base + 1; $i + 1 < $end; $i++) {
				// If old_spec find Ra-Halant...
				if ((isset($GSUBdata['pref'][$info[$i + 1]['uni']]) && self::is_halant_or_coeng($info[$i]) && self::is_ra($info[$i + 1]['uni'])  ) || 
				($is_old_spec && isset($GSUBdata['pref'][$info[$i]['uni']]) && self::is_halant_or_coeng($info[$i + 1]) && self::is_ra($info[$i]['uni'])  )
					) {
					$info[$i++]['mask'] |= self::FLAG(self::PREF);
					$info[$i++]['mask'] |= self::FLAG(self::PREF);
					break;
				}
			}
		}
	}


	/* Apply ZWJ/ZWNJ effects */
	for ($i = $start + 1; $i < $end; $i++) {
		if (self::is_joiner ($info[$i])) {
			$non_joiner = ($info[$i]['indic_category'] == self::OT_ZWNJ);
			$j = $i;
			while ($j > $start) {
				if (defined("OMIT_INDIC_FIX_4") && OMIT_INDIC_FIX_4 == 1) {
					// INDIC_FIX_4 = do nothing - carry on //
					// ZWNJ should block H C from forming blwf post-base - need to unmask backwards beyond first consonant arrived at //
					if  (!self::is_consonant($info[$j])) { break; }
				}
				$j--;

				/* ZWJ/ZWNJ should disable CJCT.	They do that by simply
	 			* being there, since we don't skip them for the CJCT
	 			* feature (ie. F_MANUAL_ZWJ) */

				/* A ZWNJ disables HALF. */
				if ($non_joiner) {
					$info[$j]['mask'] &= ~(self::FLAG(self::HALF) | self::FLAG(self::BLWF));
				}

			} 
		}
	}
}
773382
def calc_offset(self, syllables_spaces: List[str]) -> Dict[int, int]:
        
        line = string_utils.flatten(syllables_spaces)
        mydict = {} # type: Dict[int, int]
        # #defaultdict(int) #type: Dict[int, int]
        for idx, syl in enumerate(syllables_spaces):
            target_syllable = syllables_spaces[idx]
            skip_qu = string_utils.starts_with_qu(target_syllable)
            matches = list(self.syllable_matcher.finditer(target_syllable))
            for position, possible in enumerate(matches):
                if skip_qu:
                    skip_qu = False
                    continue
                (start, end) = possible.span()
                if target_syllable[start:end] in \
                        self.constants.VOWELS + self.constants.ACCENTED_VOWELS:
                    part = line[:len("".join(syllables_spaces[:idx]))]
                    offset = len(part) + start
                    if line[offset] not in self.constants.VOWELS + self.constants.ACCENTED_VOWELS:
                        LOG.error("Problem at line {} offset {}".format(line, offset))
                    mydict[idx] = offset
        return mydict
245879
def analyze_sequence(ipa):
    
    # we need some very good strategy here, which should be lightwayt and easy
    # to re-implement in other languages (e.g. JS)

    # get sound-class rep of stirng first
    seqs = re.split('([₁₂₃₄₅₆₀¹²³⁴⁵⁶⁰])+', ipa)
    out = ''
    for i in range(len(seqs)):
        seqs = ipa2tokens(tokens2class(ipa, merge_vowels=False, expand_nasals=True),'asjp')
    
        D = {}

        pass
1326635
def pk_prom(word):
    ''''''
    LIGHT = r'[ieaAoO]{1}[\.]*(u|y)(\.|$)'

    # # if the word is not monosyllabic, lop off the final syllable, which is
    # # extrametrical
    # if '.' in word:
    #     word = word[:word.rindex('.')]

    # gather the indices of syllable boundaries
    delimiters = [0, ] + [i for i, char in enumerate(word) if char == '.']

    if len(delimiters) % 2 != 0:
        delimiters.append(len(word))

    stressed = []

    # gather the indices of stressed positions
    for i, d in enumerate(delimiters):
        if i % 2 == 0:
            stressed.extend(range(d + 1, delimiters[i + 1]))

    # find the number of stressed light syllables
    heavies = re.finditer(LIGHT, word)
    violations = sum(1 for m in heavies if m.start(1) in stressed)

    return violations
780068
private static String wordShapeChris2Long(String s, boolean omitIfInBoundary, int len, Collection<String> knownLCWords) {
    final char[] beginChars = new char[BOUNDARY_SIZE];
    final char[] endChars = new char[BOUNDARY_SIZE];
    int beginUpto = 0;
    int endUpto = 0;
    final Set<Character> seenSet = new TreeSet<Character>();  // TreeSet guarantees stable ordering; has no size parameter

    boolean nonLetters = false;

    for (int i = 0; i < len; i++) {
      int iIncr = 0;
      char c = s.charAt(i);
      char m = c;
      if (Character.isDigit(c)) {
        m = 'd';
      } else if (Character.isLowerCase(c)) {
        m = 'x';
      } else if (Character.isUpperCase(c) || Character.isTitleCase(c)) {
        m = 'X';
      }
      for (String gr : greek) {
        if (s.startsWith(gr, i)) {
          m = 'g';
          //System.out.println(s + "  ::  " + s.substring(i+1));
          iIncr = gr.length() - 1;
          break;
        }
      }
      if (m != 'x' && m != 'X') {
        nonLetters = true;
      }

      if (i < BOUNDARY_SIZE) {
        beginChars[beginUpto++] = m;
      } else if (i < len - BOUNDARY_SIZE) {
        seenSet.add(Character.valueOf(m));
      } else {
        endChars[endUpto++] = m;
      }
      i += iIncr;
      // System.out.println("Position skips to " + i);
    }

    // Calculate size. This may be an upperbound, but is often correct
    int sbSize = beginUpto + endUpto + seenSet.size();
    if (knownLCWords != null) { sbSize++; }
    final StringBuilder sb = new StringBuilder(sbSize);
    // put in the beginning chars
    sb.append(beginChars, 0, beginUpto);
    // put in the stored ones sorted
    if (omitIfInBoundary) {
      for (Character chr : seenSet) {
        char ch = chr.charValue();
        boolean insert = true;
        for (int i = 0; i < beginUpto; i++) {
          if (beginChars[i] == ch) {
            insert = false;
            break;
          }
        }
        for (int i = 0; i < endUpto; i++) {
          if (endChars[i] == ch) {
            insert = false;
            break;
          }
        }
        if (insert) {
          sb.append(ch);
        }
      }
    } else {
      for (Character chr : seenSet) {
        sb.append(chr.charValue());
      }
    }
    // and add end ones
    sb.append(endChars, 0, endUpto);

    if (knownLCWords != null) {
      if (!nonLetters && knownLCWords.contains(s.toLowerCase())) {
        sb.append('k');
      }
    }
    // System.out.println(s + " became " + sb);
    return sb.toString();
  }
324369
function acceptable(value) {
  return vowels.test(value.charAt(0))
    ? value.length > 1
    : value.length > 2 && vowels.test(value)
}
89009
def apply_T7(word):
    ''''''
    WORD = word
    offset = 0

    for vvv in vvv_sequences(WORD):
        i = vvv.start(2) + 2 + offset
        WORD = WORD[:i] + '.' + WORD[i:]
        offset += 1

    RULE = ' T7' if word != WORD else ''

    return WORD, RULE
383766
def matches(self, other):
		'''
		
		'''
		if other is None:
			return False
		if isinstance(other, PhonemeDisjunction):
			return any([phoneme.matches(other) for phoneme in self])
		if isinstance(other, list) or isinstance(other, PhonologicalFeature):
			other = phoneme(other)
		return any([phoneme <= other for phoneme in self])
89757
def apply_T12(word):
    ''''''
    WORD = word
    offset = 0

    for vv in new_vv(WORD):
        # import pdb; pdb.set_trace()
        seq = vv.group(1)

        if not is_diphthong(seq) and not is_long(seq):
            i = vv.start(1) + 1 + offset
            WORD = WORD[:i] + '.' + WORD[i:]
            offset += 1

    RULE = ' T2' if word != WORD else ''

    return WORD, RULE
825886
def apply_T7(word):
    ''''''
    T7 = ''
    WORD = word.split('.')

    for i, v in enumerate(WORD):

        if contains_VVV(v):

            for I, V in enumerate(v[::-1]):

                if is_vowel(V):
                    WORD[i] = v[:I] + '.' + v[I:]
                    T7 = ' T7'

    word = '.'.join(WORD)

    return word, T7
906811
def syllable_split(string):
    ''''''
    p = r'\'[%s]+|`[%s]+|[%s]+|[^%s\'`\.]+|[^\.]{1}' % (A, A, A, A)
    return re.findall(p, string, flags=FLAGS)
1283113
private final boolean vowelinstem() {
		int i;
		for (i = k0; i <= j; i++)
			if (!cons(i))
				return true;
		return false;
	}