taipa
Version:
Taiwanese morphological parsing library
292 lines • 12.3 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.TonalSoundChangingMorphemeMaker = exports.TonalCombiningMorphemeMaker = exports.TonalSoundChangingMorpheme = exports.TonalCombiningMorpheme = void 0;
const unit_1 = require("../unit");
const maker_1 = require("../maker");
const morpheme_1 = require("../unchange/morpheme");
const unit_2 = require("../unchange/unit");
const tonalres_1 = require("../tonal/tonalres");
const unit_3 = require("../unit");
const collections_1 = require("../tonal/collections");
/** A syllable and its combining forms. */
class TonalCombiningMorpheme extends unit_1.Morpheme {
syllable;
allomorph; // required to populate stems
metaplasm;
sounds;
forms;
constructor(syllable, sounds, metaplasm) {
super();
this.syllable = syllable;
this.metaplasm = metaplasm;
// assign allomorph for each syllable
this.allomorph = this.assignAllomorph(this.syllable);
this.sounds = sounds;
this.forms = this.metaplasm.apply(this.sounds, this.allomorph);
}
getForms() {
return this.forms;
}
isAy() {
if (this.sounds[this.sounds.length - 1].toString() === tonalres_1.TonalLetterTags.y &&
this.sounds[this.sounds.length - 2].toString() === tonalres_1.TonalLetterTags.a)
return true;
return false;
}
assignAllomorph(syllable) {
if (tonalres_1.uncombinedCheckedAllomorphs.has(syllable.lastLetter.literal)) {
const am = tonalres_1.uncombinedCheckedAllomorphs.get(syllable.lastLetter.literal);
if (am)
return am;
return new tonalres_1.Allomorph();
}
if (tonalres_1.checkedToneLettersTonal.includes(syllable.lastLetter.literal) &&
(tonalres_1.uncombinedCheckedAllomorphs.has(syllable.lastSecondLetter.literal) ||
collections_1.finalConsonantsForBgjlsbbggjjllss.has(syllable.lastSecondLetter.literal))) {
// in case of a final followed by a tonal
const ams = tonalres_1.combinedCheckedAllomorphs.get(syllable.lastSecondLetter.literal + syllable.lastLetter.literal);
if (ams && ams.length > 0) {
const ret = ams.filter((it) => it.tonal.toString() === syllable.lastLetter.literal);
return ret[0];
}
return new tonalres_1.Allomorph();
}
if (tonalres_1.combinedFreeAllomorphs.has(syllable.lastLetter.literal)) {
const am = tonalres_1.combinedFreeAllomorphs.get(syllable.lastLetter.literal);
if (am)
return am;
return new tonalres_1.Allomorph(); // return empty allomorph
}
return new tonalres_1.ZeroAllomorph();
}
}
exports.TonalCombiningMorpheme = TonalCombiningMorpheme;
/** A syllable and its sound changing forms. */
class TonalSoundChangingMorpheme 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();
}
insertNasal(sound) {
if (sound) {
if (sound.name === tonalres_1.TonalSpellingTags.nasalFinalConsonant) {
// insertion of nasals, both internal and external sandhi
const ltrs = this.sounds;
ltrs.splice(0, 0, sound);
return [
new unit_2.TonalSyllable(ltrs.map((x) => new unit_3.AlphabeticLetter(x.characters))),
];
}
}
return [];
}
infect() {
const n = tonalres_1.nasalizationsTonal.sounds[0];
if (n) {
if (n.name === tonalres_1.TonalSpellingTags.nasalization) {
const snds = this.sounds;
if (snds[snds.length - 1].name === tonalres_1.TonalSpellingTags.freeTone) {
snds.splice(snds.length - 1, 0, n);
}
else if (snds[snds.length - 1].name === tonalres_1.TonalSpellingTags.vowel) {
snds.push(n);
}
return [
new unit_2.TonalSyllable(snds.map((x) => new unit_3.AlphabeticLetter(x.characters))),
];
}
}
return [];
}
/** Mutate initial consonants. */
mutateInitialConsonant(sound) {
if (sound) {
if (sound.name === tonalres_1.TonalSpellingTags.initialConsonant) {
const snds = this.sounds;
if (snds[0].toString() === sound.toString()) {
const s = new unit_2.TonalSyllable(this.sounds.map((it) => new unit_3.AlphabeticLetter(it.characters)));
s.replaceLetter(0, tonalres_1.lowerLettersTonal.get(tonalres_1.TonalLetterTags.l));
return [s];
}
return [
new unit_2.TonalSyllable(snds.map((x) => new unit_3.AlphabeticLetter(x.characters))),
];
}
}
return [];
}
mutateFinalConsonant(sound) {
if (sound) {
const snds = this.sounds;
const syl = new unit_2.TonalSyllable(this.sounds.map((i) => new unit_3.AlphabeticLetter(i.characters)));
const idx = snds.findIndex((i) => i.name === tonalres_1.TonalSpellingTags.stopFinalConsonant);
syl.replaceLetter(idx, tonalres_1.lowerLettersTonal.get(tonalres_1.TonalLetterTags.gg));
return [syl];
}
return [];
}
changeFinalTTt(initial) {
// absolute assimilation, except for t or tt followed by j. regressive
if ((this.sounds[this.sounds.length - 2].toString() === tonalres_1.TonalLetterTags.tt &&
Object.values(collections_1.initialConsonantsForTT).includes(initial.toString())) ||
(this.sounds[this.sounds.length - 2].toString() === tonalres_1.TonalLetterTags.t &&
Object.values(collections_1.initialConsonantsForFinalT).includes(initial.toString()))) {
const s = new unit_2.TonalSyllable(this.sounds.map((it) => new unit_3.AlphabeticLetter(it.characters)));
let fnl = collections_1.ttInitialTInitialPairs.get(this.sounds[this.sounds.length - 2].toString() + initial.toString());
if (!fnl && initial.toString() === tonalres_1.TonalLetterTags.j) {
// this block is dedicated to -tfj- and -twj-, since there is only -jfj- but not -jwj-
fnl = collections_1.ttInitialTInitialPairs.get(this.sounds[this.sounds.length - 2].toString() +
this.sounds[this.sounds.length - 1] +
initial.toString());
}
if (fnl) {
s.replaceLetter(s.letters.length - 2, tonalres_1.lowerLettersTonal.get(fnl));
if (collections_1.nasalInitialConsonants.includes(initial.toString())) {
s.insertLetter(s.letters.length - 2, new unit_3.AlphabeticLetter(initial.characters));
}
return [s];
}
}
return [];
}
changeFinalHHh(initial) {
// TODO: mutate consonants hh and h.
return [];
}
changeFinalPPp(initial) {
// TODO: neutrals. pp -> hh. p -> h.
return [];
}
changeWithInitialMnng(initial) {
if (initial.name === tonalres_1.TonalSpellingTags.initialConsonant &&
collections_1.nasalInitialConsonants.includes(initial.toString())) {
return this.voicedFinal();
}
return [];
}
changeWithMedial(medial) {
if (medial.name === tonalres_1.TonalSpellingTags.vowel &&
tonalres_1.vowelsTonal.includes(medial.toString())) {
return this.voicedFinal();
}
return [];
}
changeWithInitialBghjl(initial) {
if (initial.name === tonalres_1.TonalSpellingTags.initialConsonant &&
collections_1.initialConsonantsBghjl.includes(initial.toString())) {
return this.voicedFinal();
}
return [];
}
/**
* Change a final with the beginning letter of the following syllable
* @param beginning Beginning letter of the following syllable
*/
changeFinalPtkppttkk(beginning) {
const sandhiTTt = this.changeFinalTTt(beginning);
if (sandhiTTt.length > 0)
return sandhiTTt;
const sandhiHHh = this.changeFinalHHh(beginning);
if (sandhiHHh.length > 0)
return sandhiHHh;
const sandhiPPp = this.changeFinalPPp(beginning);
if (sandhiPPp.length > 0)
return sandhiPPp;
const voicedWithMnng = this.changeWithInitialMnng(beginning);
if (voicedWithMnng.length > 0)
return voicedWithMnng;
const voicedWithMedial = this.changeWithMedial(beginning);
if (voicedWithMedial.length > 0)
return voicedWithMedial;
const voicedWithBghjl = this.changeWithInitialBghjl(beginning);
if (voicedWithBghjl.length > 0)
return voicedWithBghjl;
}
changeFinalN(initial) {
if (this.sounds[this.sounds.length - 2].name !=
tonalres_1.TonalSpellingTags.stopFinalConsonant &&
this.sounds[this.sounds.length - 2].name !=
tonalres_1.TonalSpellingTags.nasalFinalConsonant) {
return [];
}
if (initial.toString() === tonalres_1.TonalLetterTags.b &&
this.sounds[this.sounds.length - 2].toString() === tonalres_1.TonalLetterTags.n) {
// replace final n with final m
const s = new unit_2.TonalSyllable(this.sounds.map((it) => new unit_3.AlphabeticLetter(it.characters)));
s.replaceLetter(s.letters.length - 2, tonalres_1.lowerLettersTonal.get(tonalres_1.TonalLetterTags.m));
return [s];
}
return [];
}
voicedFinal() {
const fnl = collections_1.voicelessVoicedFinalConsonants.get(this.sounds[this.sounds.length - 2].toString());
if (fnl) {
const s = new unit_2.TonalSyllable(this.sounds.map((it) => new unit_3.AlphabeticLetter(it.characters)));
s.replaceLetter(s.letters.length - 2, tonalres_1.lowerLettersTonal.get(fnl));
return [s];
}
return [];
}
}
exports.TonalSoundChangingMorpheme = TonalSoundChangingMorpheme;
class TonalCombiningMorphemeMaker extends maker_1.MorphemeMaker {
metaplasm;
constructor(metaplasm) {
super();
this.metaplasm = metaplasm;
}
createArray() {
return new Array();
}
createMorpheme(matched) {
const tcm = new TonalCombiningMorpheme(new unit_2.TonalSyllable(matched.letters), matched.pattern, this.metaplasm);
return tcm;
}
postprocess(patterns) {
let morphemes = this.createArray();
for (let i in patterns) {
morphemes.push(this.createMorpheme(patterns[i]));
}
return morphemes;
}
makeMorphemes(graphemes) {
const ltrs = graphemes.map((it) => it.letter);
const ptrns = this.make(ltrs, morpheme_1.syllabifyTonal);
const ms = this.postprocess(ptrns);
return ms;
}
}
exports.TonalCombiningMorphemeMaker = TonalCombiningMorphemeMaker;
class TonalSoundChangingMorphemeMaker extends maker_1.MorphemeMaker {
constructor() {
super();
}
createArray() {
return new Array();
}
createMorpheme(match) {
const tcm = new TonalSoundChangingMorpheme(new unit_2.TonalSyllable(match.letters), match.pattern);
return tcm;
}
postprocess(matches) {
const 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, morpheme_1.syllabifyTonal);
const ms = this.postprocess(ptrns);
return ms;
}
}
exports.TonalSoundChangingMorphemeMaker = TonalSoundChangingMorphemeMaker;
//# sourceMappingURL=morpheme.js.map