/// <summary> /// Search for the longest among the following suffixes, and perform the action indicated. /// eed eedly+ /// replace by ee if in R1 /// ed edly+ ing ingly+ /// delete if the preceding word part contains a vowel, and then /// if the word ends at, bl or iz add e (so luxuriat -> luxuriate), or /// if the word ends with a double remove the last letter (so hopp -> hop), or /// if the word is short, add e (so hop -> hope) /// </summary> internal void StripSuffixStep1b() { // eed eedly+ - replace by ee if in R1 if (Stem.EndsWith("eed") || Stem.EndsWith("eedly")) { if (EndsWithAndInR1("eed") || EndsWithAndInR1("eedly")) { if (_r1.Contains(Stem.Length)) { Stem = Stem.Substring(0, Stem.LastIndexOf("eed")) + "ee"; } } return; } // ed edly+ ing ingly+ - delete if the preceding word part contains a vowel, and then if ((Stem.EndsWith("ed") && Stem.IndexOfAny(Vowels, 0, Stem.Length - 2) != -1) || (Stem.EndsWith("edly") && Stem.IndexOfAny(Vowels, 0, Stem.Length - 4) != -1) || (Stem.EndsWith("ing") && Stem.IndexOfAny(Vowels, 0, Stem.Length - 3) != -1) || (Stem.EndsWith("ingly") && Stem.IndexOfAny(Vowels, 0, Stem.Length - 5) != -1)) { StripEnding(new string[4] { "ed", "edly", "ing", "ingly" }); // if the word ends at, bl or iz add e (so luxuriat -> luxuriate), or if (Stem.EndsWith("at") || Stem.EndsWith("bl") || Stem.EndsWith("iz")) { Stem += "e"; return; } // if the word ends with a double remove the last letter (so hopp -> hop), or string end2chars; if (Stem.Length >= 2) { end2chars = Stem.Substring(Stem.Length - 2, 2); } else { return; } var doubleEndings = new List <string>(DoubleChars); if (doubleEndings.Contains(end2chars)) { Stem = Stem.Remove(Stem.Length - 1); return; } // if the word is short, add e (so hop -> hope) if (IsShortWord()) { Stem += "e"; return; } } }
/// <summary> /// replace suffix y or Y by i if preceded by a non-vowel which is not the first letter of the word (so cry -> cri, by -> by, say -> say) /// </summary> internal void ReplaceSuffixStep1c() { //replace suffix y or Y by i if preceded by a non-vowel which is not the first letter of the word (so cry -> cri, by -> by, say -> say) if (Stem.EndsWith("y", StringComparison.OrdinalIgnoreCase) && (Stem.Length > 2) && (Stem.IndexOfAny(Vowels, Stem.Length - 2) != Stem.Length - 2)) { Stem = Stem.Substring(0, Stem.Length - 1) + "i"; } }
/// <summary> /// Define a short syllable in a word as either /// (a) a vowel followed by a non-vowel other than w, x or Y and preceded by a non-vowel, or * /// (b) a vowel at the beginning of the word followed by a non-vowel. /// </summary> /// <param name="index"></param> /// <returns></returns> internal bool IsShortSyllable(int index) { //Define a short syllable in a word as either int vowelIndex = Stem.IndexOfAny(Vowels, index); if (vowelIndex < 0) //Don't have a vowel { return(false); } //(a) a vowel followed by a non-vowel other than w, x or Y and preceded by a non-vowel, if (vowelIndex > 0) { int expectedShortEnd = vowelIndex + 2; //Check word has room for a single non-vowel //and so we add two because length is one more than index of last char int nextVowelIndex = Stem.IndexOfAny(Vowels, vowelIndex + 1); if (nextVowelIndex == expectedShortEnd || Stem.Length == expectedShortEnd) { int nonVowelIndex = Stem.IndexOfAny(NotShortSyllableNonVowels, vowelIndex + 1); int earlyVowelIndex = Stem.IndexOfAny(Vowels, vowelIndex - 1); return(nonVowelIndex != vowelIndex + 1 && //Check not-a-vowel (or w,x,Y) found after vowel earlyVowelIndex == vowelIndex); // Check no vowels found in char before vowel } else { return(false); } } else //or * (b) a vowel at the beginning of the word followed by a non-vowel. { return(Stem.IndexOfAny(Vowels) == 0 && Stem.Length > 1 && Stem.IndexOfAny(Vowels, 1) != 1); } }