This commit is contained in:
Bill D 2021-05-09 20:08:35 +03:00
parent 2dea82c32b
commit c1ee7d3289
1 changed files with 73 additions and 54 deletions

View File

@ -329,6 +329,15 @@ export function addDiacritics({ p, f }: T.PsString, ignoreCommas?: true): T.PsSt
}; };
} }
enum PhonemeStatus {
LeadingLongVowel,
LeadingConsonantOrShortVowel,
DoubleConsonantTashdeed,
EndingWithHeyHim,
DirectMatch,
ShortVowel,
}
function processPhoneme( function processPhoneme(
acc: DiacriticsAccumulator, acc: DiacriticsAccumulator,
phoneme: Phoneme, phoneme: Phoneme,
@ -346,64 +355,46 @@ function processPhoneme(
const { const {
phonemeInfo, phonemeInfo,
isBeginningOfWord,
currentPLetter,
needsTashdeed,
sukunOrDiacritic, sukunOrDiacritic,
nextPLetter, phonemeState,
isEndOfWord,
} = stateInfo({ state, i, phoneme, phonemes }); } = stateInfo({ state, i, phoneme, phonemes });
// if it's not an exception (TODO) const p = phonemeState
// it must be one of the following 5 possibilities
// 1. beginning a word with a long vowel return (p === PhonemeStatus.LeadingLongVowel) ?
if (isBeginningOfWord && (phonemeInfo.longVowel && !phonemeInfo.endingOnly)) { pipe(
if (phoneme !== "aa" && currentPLetter !== "ا" && !phonemeInfo.matches?.includes(nextPLetter)) { advanceP,
throw Error("phonetics error - needs alef prefix"); addP(phonemeInfo.diacritic),
} advanceP,
return pipe( )(state)
advanceP, : (p === PhonemeStatus.LeadingConsonantOrShortVowel) ?
addP(phonemeInfo.diacritic), pipe(
advanceP, advanceP,
)(state); addP(sukunOrDiacritic),
// 2. beginning a word with something else advanceForAin,
} else if (isBeginningOfWord && (phonemeInfo.beginningMatches?.includes(currentPLetter) || phonemeInfo.matches?.includes(currentPLetter))) { )(state)
return pipe( : (p === PhonemeStatus.DoubleConsonantTashdeed) ?
advanceP, pipe(
addP(sukunOrDiacritic), addP(tashdeed)
advanceForAin, )(state)
)(state); : (p === PhonemeStatus.EndingWithHeyHim) ?
// 3. double consonant to be marked with tashdeed pipe(
} else if (needsTashdeed) { advanceP,
return pipe( addP(phoneme === "u" ? hamzaAbove : sukun),
addP(tashdeed) )(state)
)(state); : (p === PhonemeStatus.DirectMatch) ?
// 4. special ه ending pipe(
} else if (isEndOfWord && ((phoneme === "u" && currentPLetter === "ه") || (phoneme === "h" && ["ه", "ح"].includes(currentPLetter)))) { addP(sukunOrDiacritic),
return pipe( advanceP,
advanceP, )(state)
addP(phoneme === "u" ? hamzaAbove : sukun), : // p === PhonemeState.ShortVowel
)(state); pipe(
// 5. direct match of phoneme / P letter advanceForHamzaMid,
} else if (phonemeInfo.matches?.includes(currentPLetter) || (isEndOfWord && phonemeInfo.endingMatches?.includes(currentPLetter)) || (phoneme === "m" && currentPLetter === "ن" && nextPLetter === "ب")) { addP(phonemeInfo.diacritic),
return pipe( advanceForAinOrHamza,
addP(sukunOrDiacritic), )(state);
advanceP,
)(state);
// 6. just a diacritic for short vowel
} else if (phonemeInfo.diacritic && !phonemeInfo.longVowel) {
return pipe(
advanceForHamzaMid,
addP(phonemeInfo.diacritic),
advanceForAinOrHamza,
)(state);
}
// anything that gets to this point is a failure/error
throw new Error("phonetics error");
} }
function stateInfo({ state, i, phonemes, phoneme }: { function stateInfo({ state, i, phonemes, phoneme }: {
state: DiacriticsAccumulator, state: DiacriticsAccumulator,
i: number, i: number,
@ -425,8 +416,36 @@ function stateInfo({ state, i, phonemes, phoneme }: {
const needsSukun = doubleConsonant && ((previousPhoneme !== phoneme) || phonemeInfo.matches?.includes(currentPLetter)); const needsSukun = doubleConsonant && ((previousPhoneme !== phoneme) || phonemeInfo.matches?.includes(currentPLetter));
const diacritic = isEndOfWord ? ((!phonemeInfo.longVowel || phonemeInfo.useEndingDiacritic) ? phonemeInfo.diacritic : undefined) : phonemeInfo.diacritic; const diacritic = isEndOfWord ? ((!phonemeInfo.longVowel || phonemeInfo.useEndingDiacritic) ? phonemeInfo.diacritic : undefined) : phonemeInfo.diacritic;
const sukunOrDiacritic = (needsSukun ? sukun : diacritic); const sukunOrDiacritic = (needsSukun ? sukun : diacritic);
function getPhonemeState(): PhonemeStatus {
if (isBeginningOfWord && (phonemeInfo.longVowel && !phonemeInfo.endingOnly)) {
if (phoneme !== "aa" && currentPLetter !== "ا" && !phonemeInfo.matches?.includes(nextPLetter)) {
throw Error("phonetics error - needs alef prefix");
}
return PhonemeStatus.LeadingLongVowel;
}
if (isBeginningOfWord && (phonemeInfo.beginningMatches?.includes(currentPLetter) || phonemeInfo.matches?.includes(currentPLetter))) {
return PhonemeStatus.LeadingConsonantOrShortVowel;
}
if (needsTashdeed) {
return PhonemeStatus.DoubleConsonantTashdeed;
}
if (isEndOfWord && ((phoneme === "u" && currentPLetter === "ه") || (phoneme === "h" && ["ه", "ح"].includes(currentPLetter)))) {
return PhonemeStatus.EndingWithHeyHim;
}
if ((phonemeInfo.matches?.includes(currentPLetter) || (isEndOfWord && phonemeInfo.endingMatches?.includes(currentPLetter)) || (phoneme === "m" && currentPLetter === "ن" && nextPLetter === "ب"))) {
return PhonemeStatus.DirectMatch;
}
if (phonemeInfo.diacritic && !phonemeInfo.longVowel) {
return PhonemeStatus.ShortVowel;
}
throw new Error("phonetics error - no status found for phoneme: " + phoneme);
}
const phonemeState = getPhonemeState();
return { return {
phonemeInfo, isBeginningOfWord, currentPLetter, needsTashdeed, sukunOrDiacritic, nextPLetter, isEndOfWord, phonemeState, phonemeInfo, sukunOrDiacritic,
}; };
}; };