UNPKG

taipa

Version:

Taiwanese morphological parsing library

660 lines 31.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.TonalSoundUnchangingMorphemeMaker = exports.TonalSoundUnchangingMorpheme = exports.TonalStandaloneMorphemeMaker = exports.TonalStandaloneMorpheme = exports.syllabifyTonal = void 0; const unit_1 = require("../unit"); const maker_1 = require("../maker"); const tonalres_1 = require("../tonal/tonalres"); const unit_2 = require("../unit"); const soundgen_1 = require("../tonal/soundgen"); const syllablelists_1 = require("../tonal/syllablelists"); const matcher_1 = require("./matcher"); const collections_1 = require("../tonal/collections"); const metaplasm_1 = require("./metaplasm"); const metaplasm_2 = require("../metaplasm"); const unit_3 = require("./unit"); function syllabifyTonal(letters, beginOfSyllable) { // get the longest matched syllable pattern let literal = ''; let matched = ''; let begin = 0; let ltrs = new Array(); let matchedLtrs = new Array(); let literalLexicalRoot4th8th = ''; // could be an 4th or 8th root let literalLexicalRootEighth = ''; // specific an 8th root for (let i = beginOfSyllable; i < letters.length; i++) { literal = literal + letters[i].literal; ltrs.push(letters[i].literal); // console.log(`begining of the loop: ${literal}. ${ltrs}`); const had = collections_1.fourthToEighthFinalConsonants.has(letters[i].literal); if (i + 1 < letters.length && had && (tonalres_1.TonalLetterTags.w === letters[i + 1].literal || tonalres_1.TonalLetterTags.x === letters[i + 1].literal)) { const got = collections_1.fourthToEighthFinalConsonants.get(letters[i].literal); // restore the lexical roots for 4th final consonants, which is 8th finals // in case of absent 8th roots, 4th roots should also be restored // e.g. koehwlaih, jiwpowcitwlaw, khihwlih // in case of absent 4th roots for an triplet // e.g. juahxjuahwjuahh. there is no juah present in syllable table // 4th and 8th roots for 3rd checked tones if (got) { // since it is 4th finals, length of 4th final is one, just slice one character literalLexicalRootEighth = literalLexicalRoot4th8th.slice(0, literalLexicalRoot4th8th.length) + got; // console.log(`literalRoot4thFinal: ${literalRoot4thChecked}, 8th: ${literalRoot8thChecked}`); // the below fourth should go after the above eighth literalLexicalRoot4th8th = literalLexicalRoot4th8th + letters[i].literal; } } else { literalLexicalRoot4th8th = literalLexicalRoot4th8th + letters[i].literal; } if ((0, syllablelists_1.isInSyllableTable)(literal) && tonalres_1.freeToneLettersTonal.includes(letters[i].literal)) { // console.log(`i: ${i}, literal: ${literal}, tone: ${letters[i].literal}, letters[i+1]: ${letters[i + 1].literal}`) if (begin === beginOfSyllable) { matched = literal; Object.assign(matchedLtrs, ltrs); } break; } else if (((0, syllablelists_1.isInSyllableTable)(literalLexicalRoot4th8th) || (0, syllablelists_1.isInSyllableTable)(literalLexicalRootEighth)) && tonalres_1.finalConsonantsPtkhppttkkhhTonal.includes(letters[i].literal)) { // console.log(`i: ${i}, literal: ${literal}, root4th8th: ${literalLexicalRoot4th8th}, root8th: ${literalLexicalRootEighth}, stopFinalConsonant: ${letters[i].literal}`); // console.log(`begin: ${begin}, beginOfSyllable: ${beginOfSyllable}`); if (begin === beginOfSyllable) { matched = literal; // assign literal instead of literalRoot4thFinal Object.assign(matchedLtrs, ltrs); } break; } else if (tonalres_1.freeToneLettersTonal.includes(letters[i].literal)) { // check tonals is the subset of free tonals // console.log(`i: ${i}, literal: ${literal}, letters[i].literal, ${letters[i].literal}`); // when there are tonals if (literal.length > 1 && letters[i] && letters[i - 1] && ((0, matcher_1.smBgkpF)(letters[i - 1].literal, letters[i].literal) || (0, matcher_1.smBgkpWx)(letters[i - 1].literal, letters[i].literal) || (0, matcher_1.smJlsF)(letters[i - 1].literal, letters[i].literal) || (0, matcher_1.smJsW)(letters[i - 1].literal, letters[i].literal) || (0, matcher_1.smLWx)(letters[i - 1].literal, letters[i].literal))) { // b, g, bb, gg, l, j, s, ll, ss need to be handled in TonalCombiningMorpheme.assignAllomorph // this combining form is not present in the pool. matched = literal; Object.assign(matchedLtrs, ltrs); break; } else if (literal.length > 2 && letters[i] && letters[i - 1] && letters[i - 2] && ((0, matcher_1.smMnngHWx)(letters[i - 2].literal, letters[i - 1].literal, letters[i].literal) || (0, matcher_1.smMnngHF)(letters[i - 2].literal, letters[i - 1].literal, letters[i].literal))) { // in case of -mhw. matched = literal; Object.assign(matchedLtrs, ltrs); break; } else if (literal.length > 1 && letters[i] && letters[i - 1] && (0, matcher_1.smMngFywxz)(letters[i - 1].literal, letters[i].literal)) { // in case of -iengz, -uamz. // matched = literal; // Object.assign(matchedLtrs, ltrs); // break; } // tone change of free allomorphs const rulesFa = tonalres_1.freeAllomorphStandaloneRules.get(letters[i].literal); const tnlsFa = !rulesFa ? [] : rulesFa.map((x) => x.toString()); // tone sandhi of ay const rulesAy = tonalres_1.standaloneRulesAy.get(letters[i].literal); const tnlsAy = !rulesAy ? [] : rulesAy.map((x) => x.toString()); // merge the above twoo arrays const tnls = tnlsFa.concat(tnlsAy.filter((item) => tnlsFa.indexOf(item) < 0)); // console.log(`literal: ${literal}`); if (tnls.length > 0) { for (let t of tnls) { // console.log(literal, t.toString(), tnls.length, tnls); if ((0, syllablelists_1.isInSyllableTable)(letters .slice(beginOfSyllable, i) .map((x) => x.literal) .join('') + t)) { // this combining form is not present in the pool, // but its standalone forms are. e.g. aw. matched = literal; Object.assign(matchedLtrs, ltrs); break; } } if (matched.length > 0 && matchedLtrs.length > 0) break; } else { // no standalone forms for this combining form. e.g. ax. matched = ''; matchedLtrs = []; } } else if ((0, syllablelists_1.isInSyllableTable)(literal)) { matched = literal; Object.assign(matchedLtrs, ltrs); begin = beginOfSyllable; // console.log(matched); } else { // console.log('no matched for syllabifyTonal:' + ltrs); // when there are no tone letters if (collections_1.finalConsonantsBgjlsbbggjjllss.includes(letters[i].literal)) { // for the syllables with sandhi final consonants that are not present in syllable tables const literalWithoutFinal = letters .map((val, ind, arr) => ind < i && ind >= beginOfSyllable ? arr[ind].literal : '') .join(''); const gotFinalConsonants = collections_1.finalConsonantsForBgjlsbbggjjllss.get(letters[i].literal); if (gotFinalConsonants) { // check if at least one uncombinging form present const isUncombingFormPresent = gotFinalConsonants .map((it) => (0, syllablelists_1.isInSyllableTable)(literalWithoutFinal + it)) .reduce((prev, curr, ind, arr) => prev || curr); // console.log(literal,gotFinalConsonants,isUncombingFormPresent,literalWithoutFinal,`i: ${i}`); if (isUncombingFormPresent) { // at least one standalone form is present matched = literal; Object.assign(matchedLtrs, ltrs); } } } else if ((0, matcher_1.smEk)(ltrs[ltrs.length - 2], ltrs[ltrs.length - 1]) || (0, matcher_1.smIk)(ltrs[ltrs.length - 2], ltrs[ltrs.length - 1])) { // match for -ek or -ik matched = literal; Object.assign(matchedLtrs, ltrs); } else if ((0, matcher_1.smVowelMng)(ltrs[ltrs.length - 2], ltrs[ltrs.length - 1])) { // match for -ieng, -uam // matched = literal; // Object.assign(matchedLtrs, ltrs); } else if (!tonalres_1.freeToneLettersTonal.includes(letters[i].literal)) { // free first tone without a free tonal const rules = tonalres_1.freeAllomorphStandaloneRules.get(tonalres_1.TonalLetterTags.zero); const tnls = !rules ? [] : rules; for (let t of tnls) { // append second tonal letter // check the standalone forms if ((0, syllablelists_1.isInSyllableTable)(literal + t.toString())) { // if the free first tone's lemma is included matched = literal; Object.assign(matchedLtrs, ltrs); //break; } } } // when there is no matched lexcial roots for this syllable, we still assign begin begin = beginOfSyllable; } } // console.log(`literal: ${literal}. matched: ${matched}`); // console.log(matchedLtrs); if (matched.length > 0 && literal.length > matched.length) { // when ~ay is longer than ~a by one letter y // for those first tone lexcial roots that are present matched = ''; matchedLtrs = []; } // console.log('matched: ' + matched); const tsg = new soundgen_1.TonalSoundGenerator(); //console.log('matched: ' + matched) let list = new Array(); if (matched.length > 0) { list = tsg.generate(matchedLtrs); } else { if (ltrs.length == 3 && ltrs[1] === 'a' && ltrs[2] === 'y') { const rea = new metaplasm_2.RemovingEpenthesisOfAy(); const done = rea.applyToString(literal); //console.log(done.toString()) if (collections_1.epentheticLetters.includes(ltrs[0]) && (0, syllablelists_1.isInSyllableTable)(done)) { list = tsg.generate(ltrs); } } } // console.log(list); let matchedLen = 0; let mp = new unit_1.MatchedPattern(); for (let m in list) { const min = Math.min(letters.length - beginOfSyllable, list[m].length); if (list[m].length == min) { for (let n = 0; n < min; n++) { if (list[m][n] != undefined) { if (letters[beginOfSyllable + n].literal === list[m][n].toString()) { //console.log(syllabary[m]) if (n + 1 == min && min > matchedLen) { // to make sure it is longer than previous patterns // last letter matched for the pattern matchedLen = min; // copy the matched letters for (let q = 0; q < matchedLen; q++) { mp.letters[q] = letters[beginOfSyllable + q]; } // copy the pattern of sounds mp.pattern = list[m]; //console.log(syllabary.list[m]) //console.log(mp.letters) } } else { break; } } } } } return mp; } exports.syllabifyTonal = syllabifyTonal; /** A syllable and its standalone forms. */ class TonalStandaloneMorpheme extends unit_1.Morpheme { syllable; allomorph; metaplasm; forms; sounds; constructor(syllable, sounds, metaplasm) { super(); this.syllable = syllable; this.metaplasm = metaplasm; // assign allomorph for each syllable this.sounds = sounds; this.allomorph = this.assignAllomorph(this.sounds); this.forms = this.metaplasm.apply(this.sounds, this.allomorph); } getForms() { return this.forms; } addForms(syllables) { if (syllables && syllables.length == 1) { this.forms.push(syllables[0]); } } assignAllomorph(letters) { let allomorph = new tonalres_1.ZeroAllomorph(); // assign the matched allomorph for this syllable let las = []; // list of allomorphs const s = new unit_3.TonalSyllable(letters.map((it) => new unit_2.AlphabeticLetter(it.characters))); const keys = Array.from(tonalres_1.checkedAllomorphs.keys()); for (let k = 0; k < keys.length; k++) { const am = tonalres_1.checkedAllomorphs.get(keys[k]); if (am && am instanceof tonalres_1.CheckedAllomorph) { if (am.tonal) { if (am.tonal.toString() === s.lastLetter.literal && am.final.toString() === s.lastSecondLetter.literal) { las.push(am); break; } else { if (am.final.toString() === s.lastLetter.literal) { las.push(am); break; } } } } } if (las.length > 0) { // there is only one match after processing, we just assign it const ret = las.shift(); if (ret) return ret; } // after matching with checked allomorphs, we go on matching free allomorphs las = []; if (tonalres_1.freeAllomorphs.has(s.lastLetter.literal)) { const am = tonalres_1.freeAllomorphs.get(s.lastLetter.literal); const stpFnls = letters.filter((it) => it.name === tonalres_1.TonalSpellingTags.stopFinalConsonant); const chkttnls = letters.filter((it) => it.name === tonalres_1.TonalSpellingTags.checkedTone); if (am && !(stpFnls.length == 1 && stpFnls[0].toString().length == 2 && chkttnls.length == 1)) { // when 8th finals *not* followed by a tonal las.push(am); } else las.push(new tonalres_1.Allomorph()); } if (las.length == 0) { // tone 1 has no allomorph allomorph = new tonalres_1.ZeroAllomorph(); } else if (las.length == 1) { // are there multiple allomorphs? there should be only one. for (let i = 0; i < las.length; i++) { if (las[i].tonal.toString() === new tonalres_1.AllomorphX().tonal.toString()) { // this syllable is already in base form // in order to display this inflectional ending, we have to assign allomorph = las[i]; } else { allomorph = las[i]; } } } return allomorph; } } exports.TonalStandaloneMorpheme = TonalStandaloneMorpheme; class TonalStandaloneMorphemeMaker extends maker_1.MorphemeMaker { sandhiFinals = new Array(); sandhiFinalTonals = new Array(); metaplasm; constructor(metaplasm) { super(); this.metaplasm = metaplasm; } createArray() { return new Array(); } createMorpheme(matched, metaplasm) { const tum = new TonalStandaloneMorpheme(new unit_3.TonalSyllable(matched.letters), matched.pattern, metaplasm); return tum; } isCombiningAy(syllables) { const keysAy = Array.from(tonalres_1.standaloneRulesAy.keys()); if (syllables.length >= 2) { const nslFnlLast2nd = syllables[syllables.length - 2].pattern.filter((it) => it.name === tonalres_1.TonalSpellingTags.nasalFinalConsonant); const stpFnlH = syllables[syllables.length - 2].pattern.filter((it) => it.name === tonalres_1.TonalSpellingTags.stopFinalConsonant && it.toString() === tonalres_1.TonalLetterTags.h); const tnl = syllables[syllables.length - 2].pattern.filter((it) => (it.name === tonalres_1.TonalSpellingTags.nasalFinalConsonant || it.name === tonalres_1.TonalSpellingTags.checkedTone) && keysAy.includes(it.toString())); const nslInitLast = syllables[syllables.length - 1].pattern.filter((it) => it.name === tonalres_1.TonalSpellingTags.initialConsonant && collections_1.nasalInitialConsonants.includes(it.toString())); // ending ay const endingAy = syllables[syllables.length - 1].lastSecondLetter.literal === tonalres_1.TonalLetterTags.a && syllables[syllables.length - 1].lastLetter.literal === tonalres_1.TonalLetterTags.y; // ending a is the proceeding form of ay const endingA = syllables[syllables.length - 1].lastLetter.literal === tonalres_1.TonalLetterTags.a; if (!(nslFnlLast2nd.length == 1 && stpFnlH.length == 1 && tnl.length == 1) && (endingAy || endingA)) { // bypass sandhi t. e.g. vunghf~. if (nslInitLast.length == 1 && nslFnlLast2nd.length == 0) { // in case of words like vutfngay return false; } const initLast = syllables[syllables.length - 1].pattern.filter((it) => it.name === tonalres_1.TonalSpellingTags.initialConsonant && tonalres_1.initialConsonantsTonal.includes(it.toString())); const mdlLast = syllables[syllables.length - 1].pattern.filter((it) => it.name === tonalres_1.TonalSpellingTags.vowel); if (stpFnlH.length == 0 && nslFnlLast2nd.length == 1 && initLast.length == 1 && nslFnlLast2nd[0].toString() != initLast[0].toString()) { // in case of words like angzchuay, ngzchuay return false; } else if (initLast.length == 1 && mdlLast.length > 1) { // in case of suafluay, suafsuay return false; } return true; } } return false; } isCombiningEx(syllables) { // ending ex const endingEx = syllables[syllables.length - 1].lastSecondLetter.literal === tonalres_1.TonalLetterTags.e && syllables[syllables.length - 1].lastLetter.literal === tonalres_1.TonalLetterTags.x; if (endingEx) { return true; } return false; } isTransfixInflection(syllables) { // TODO: there are not many of them. make a tiny dictionary to cover the ocurrences const thirds = syllables .map((it) => it.pattern.filter((ltr) => ltr.toString() === tonalres_1.TonalLetterTags.w)) .map((seq) => seq.map((ltr) => ltr.toString())) .filter((arr) => arr.length > 0); const endingAw = syllables[syllables.length - 1].lastSecondLetter.literal === tonalres_1.TonalLetterTags.a; if (syllables.length > 1 && thirds.length == syllables.length && endingAw) return true; return false; } isDoublet(syllables) { if (syllables.length == 2) { const stems = syllables .map((it) => it.pattern.filter((s) => s.name !== tonalres_1.TonalSpellingTags.freeTone)) .map((seq) => seq.map((s) => s.toString()).join('')); // TODO: add checks for tone group const tnls = syllables .map((it) => it.pattern.filter((s) => s.name === tonalres_1.TonalSpellingTags.freeTone)) .map((seq) => seq.map((ltr) => ltr.toString()).join('')); // compare 2 strings/lexical stems if (stems[0] === stems[1]) return true; // identical } return false; } isTriplet(syllables) { if (syllables.length == 3) { const stems = syllables .map((it) => it.pattern.filter((ltr) => ltr.name !== tonalres_1.TonalSpellingTags.freeTone && ltr.name !== tonalres_1.TonalSpellingTags.checkedTone)) .map((seq) => seq.map((ltr) => ltr.toString()).join('')); const fnls = syllables .map((it) => it.pattern.filter((s) => s.name === tonalres_1.TonalSpellingTags.stopFinalConsonant)) .map((seq) => seq.map((s) => s.toString()).join('')); // TODO: add checks for tone group const tnls = syllables .map((it) => it.pattern.filter((s) => s.name === tonalres_1.TonalSpellingTags.freeTone)) .map((seq) => seq.map((s) => s.toString()).join('')); // compare 3 strings/lexical stems if (fnls && fnls.length > 0) { // stems of checked tones if (stems[0] === stems[1] && stems[0] + fnls[0] === stems[2]) return true; } else { // stems of free tones if (stems.every((v, i, a) => v === a[a.length - 1])) return true; // identical } } return false; } /** Check if ~ek or ~ekk available for the ~iet syllable. */ isEkEkkAvailableForRimeIet(syllables) { if (syllables.length >= 2) { const vs = syllables[syllables.length - 2].pattern.filter((i) => i.name === tonalres_1.TonalSpellingTags.vowel); const fcs = syllables[syllables.length - 2].pattern.filter((i) => i.name === tonalres_1.TonalSpellingTags.stopFinalConsonant); const ts = syllables[syllables.length - 2].pattern.filter((i) => i.name === tonalres_1.TonalSpellingTags.checkedTone); if (vs.length == 2 && fcs.length == 1 && ts.length == 1 && vs[0].toString() === tonalres_1.TonalLetterTags.i && vs[1].toString() === tonalres_1.TonalLetterTags.e && fcs[0].toString() === tonalres_1.TonalLetterTags.t && (ts[0].toString() === tonalres_1.TonalLetterTags.f || ts[0].toString() === tonalres_1.TonalLetterTags.w)) { // TODO: check if the standalone forms present in syllable table. return true; } } else if (syllables.length == 1) { // standalone syllables ietw and ietf should be handled in this block } return false; } preprocess(graphemes) { let ltrs = new Array(); ltrs = graphemes.map((it) => it.letter); return ltrs; } postprocess(matched) { const morphemes = this.createArray(); for (let i = 0; i < matched.length; i++) { const ptn = matched[i]; if (this.isCombiningAy(matched) && matched.length == 2) { // ~fa, ~xa, fay, or ~xay. only 2 syllables morphemes.push(this.createMorpheme(ptn, new metaplasm_1.PrecedingAyStandalone())); } else if (this.isCombiningAy(matched) && (matched.length == 3 || matched.length == 4)) { // ~fa, ~xa, fay, or ~xay. more than 2 syllables if (i == matched.length - 2 || i == matched.length - 1) // the last 2 syllables morphemes.push(this.createMorpheme(ptn, new metaplasm_1.PrecedingAyStandalone())); else if (i == matched.length - 3) // the first syllable of a 3-syllable word or the 2nd syllable of a 4-syllable word morphemes.push(this.createMorpheme(ptn, new metaplasm_1.TonalStandaloneForms(matched[i + 1].pattern))); else if (matched.length == 4 && i == matched.length - 4) // the first syllable of a 4-syllable word morphemes.push(this.createMorpheme(ptn, new metaplasm_1.TonalStandaloneForms(matched[i + 1].pattern))); } else if (this.isCombiningEx(matched) && matched.length == 2) { // ~ex morphemes.push(this.createMorpheme(ptn, new metaplasm_1.PrecedingExStandalone())); } else if (this.isTriplet(matched)) { // triplet construction. pass the last syllable as an argument morphemes.push(this.createMorpheme(ptn, new metaplasm_1.LastSyllableForms(matched[2].pattern))); } else if (this.isDoublet(matched)) { // doublet construction. pass the last syllable as an argument morphemes.push(this.createMorpheme(ptn, new metaplasm_1.LastSyllableForms(matched[1].pattern))); } else if (this.isTransfixInflection(matched)) { morphemes.push(this.createMorpheme(ptn, new metaplasm_1.TransfixStandalone())); } else { if (i < matched.length - 1) { // when the target syllable is not the last one in a word. // pass the letters of the following syllable to unchange letters accordingly morphemes.push(this.createMorpheme(ptn, new metaplasm_1.TonalStandaloneForms(matched[i + 1].pattern))); } else { // no sandhi letters to unchange, just pass an empty array // the metaplasm argument would be either TonalStandaloneForms or PhrasalVerbParticleStandalone morphemes.push(this.createMorpheme(ptn, this.metaplasm)); } if (this.isEkEkkAvailableForRimeIet(matched) && i < matched.length - 1) { const forms = this.createMorpheme(ptn, new metaplasm_1.StandaloneFormsIetfIetwToEkEkk()).getForms(); if (forms && forms.length == 1) { morphemes[i].addForms(forms); } } } } return morphemes; } makeMorphemes(graphemes) { const ltrs = this.preprocess(graphemes); const ptns = this.make(ltrs, syllabifyTonal); const ms = this.postprocess(ptns); // TODO: to further check if the syllable is valid, given the following syllable return ms; } } exports.TonalStandaloneMorphemeMaker = TonalStandaloneMorphemeMaker; /** A syllable and its sound changing forms. */ class TonalSoundUnchangingMorpheme extends unit_1.Morpheme { syllable; sounds; constructor(syllable, sounds) { super(); this.syllable = syllable; this.sounds = sounds; } get lastSecondLetter() { return this.sounds[this.sounds.length - 2].toString(); } uninsertNasal() { const ltrs = this.sounds; ltrs.shift(); return [ new unit_3.TonalSyllable(ltrs.map((it) => new unit_2.AlphabeticLetter(it.characters))), ]; } toVoicelessFinal() { // unvoiced if (collections_1.voicedVoicelessFinalConsonants.has(this.sounds[this.sounds.length - 2].toString())) { const fnl = collections_1.voicedVoicelessFinalConsonants.get(this.sounds[this.sounds.length - 2].toString()); if (fnl) { const s = new unit_3.TonalSyllable(this.sounds.map((it) => new unit_2.AlphabeticLetter(it.characters))); s.replaceLetter(s.letters.length - 2, tonalres_1.lowerLettersTonal.get(fnl)); return [s]; } } return []; } unmutateInitialConsonant(initial) { if (initial.name === tonalres_1.TonalSpellingTags.initialConsonant && initial.toString() === tonalres_1.TonalLetterTags.t) { // l- -> t- const s = new unit_3.TonalSyllable(this.sounds.map((it) => new unit_2.AlphabeticLetter(it.characters))); s.replaceLetter(0, tonalres_1.lowerLettersTonal.get(tonalres_1.TonalLetterTags.t)); return [s]; } return []; } unmutateFinalConsonant(initial) { if (initial.name === tonalres_1.TonalSpellingTags.initialConsonant && initial.toString() === tonalres_1.TonalLetterTags.g) { // gg -> tt const syl = new unit_3.TonalSyllable(this.sounds.map((it) => new unit_2.AlphabeticLetter(it.characters))); const idx = this.sounds.findIndex((i) => i.name === tonalres_1.TonalSpellingTags.stopFinalConsonant); syl.replaceLetter(idx, tonalres_1.lowerLettersTonal.get(tonalres_1.TonalLetterTags.tt)); return [syl]; } return []; } uninfect() { const n = this.sounds.filter((i) => i.name === tonalres_1.TonalSpellingTags.nasalization); if (n.length == 1) { let ltrs = this.sounds.filter((i) => i.name !== tonalres_1.TonalSpellingTags.nasalization); const s = new unit_3.TonalSyllable(ltrs.map((it) => new unit_2.AlphabeticLetter(it.characters))); return [s]; } return []; } } exports.TonalSoundUnchangingMorpheme = TonalSoundUnchangingMorpheme; class TonalSoundUnchangingMorphemeMaker extends maker_1.MorphemeMaker { constructor() { super(); } createArray() { return new Array(); } createMorpheme(match) { const tcm = new TonalSoundUnchangingMorpheme(new unit_3.TonalSyllable(match.letters), match.pattern); return tcm; } postprocess(matches) { let morphemes = this.createArray(); for (let i in matches) { morphemes.push(this.createMorpheme(matches[i])); } return morphemes; } makeMorphemes(graphemes) { const ltrs = graphemes.map((it) => it.letter); const ptrns = this.make(ltrs, syllabifyTonal); const ms = this.postprocess(ptrns); return ms; } } exports.TonalSoundUnchangingMorphemeMaker = TonalSoundUnchangingMorphemeMaker; //# sourceMappingURL=morpheme.js.map