Public
Edited
Dec 30, 2023
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
[...alternativeForms("가르치", true, false)] // 가르칠어
Insert cell
[...alternativeForms("나쁘", true, false)] // 나빠
Insert cell
[...alternativeForms("고프", true, false)] // 고파
Insert cell
[...alternativeForms("가", true, false)] // 가세요
Insert cell
Insert cell
Insert cell
/**
* Yields alternative forms of the verb or adjective with the given `stem`.
*/
function* alternativeForms(
stem,
isVerb,
ignorePassive,
) {
for (
const [basicAlternativeForm, text] of basicAlternativeForms(stem, isVerb)
) {
yield [`${basicAlternativeForm}, present`, text];
}

let pastStem;
let passiveStem;
let activeStem;

if (stem.endsWith("하")) {
const noun = stem.slice(0, stem.length - 1);

pastStem = noun + "했";
passiveStem = ignorePassive ? undefined : noun + "되";

if (isVerb) {
yield ["adjective, present", stem + "하는"];
yield ["adjective, past", stem + "한"];
} else {
yield ["adjective, present", stem + "한"];
}
yield ["adjective, future", stem + "할"];
} else if (stem.endsWith("되")) {
const noun = stem.slice(0, stem.length - 1);

pastStem = noun + "됐";
activeStem = ignorePassive ? undefined : noun + "하";

if (isVerb) {
yield ["verb, present", stem + "되는"];
yield ["verb, past", stem + "된"];
} else {
yield ["adjective, present", stem + "된"];
}
yield ["adjective, future", stem + "될"];
} else {
const jamo = Jamo.fromSyllables(stem[stem.length - 1]);
const trimmedStem = stem.slice(0, -1);

if (jamo[1] === "ㅏ") {
if (jamo.length === 2) {
pastStem = trimmedStem + Jamo.toSyllable(jamo + "ㅆ");
} else {
pastStem = stem + "았";
}

yield ["adjective, present", stem + "하는"];
} else if (jamo[1] === "ㅗ") {
if (jamo.length === 2) {
pastStem = trimmedStem + Jamo.toSyllable(jamo[0] + "ㅘㅆ");
} else {
pastStem = stem + "았";
}
} else if (jamo[1] === "ㅡ" && jamo.length === 2) {
pastStem = trimmedStem + Jamo.toSyllable(jamo[0] + "ㅓㅆ");
} else {
if (stem[stem.length - 1] === "업") {
pastStem = trimmedStem + "어웠";
} else if (jamo.length === 2) {
let casualLastJamo = "";

switch (jamo[1]) {
case "ㅣ":
casualLastJamo = jamo[0] + "ㅕ";
break;

case "ㅓㅔ":
casualLastJamo = jamo[0] + jamo[1];
break;

default:
casualLastJamo = jamo[0] + jamo[1];
break;
}

pastStem = trimmedStem + Jamo.toSyllable(casualLastJamo + "ㅆ");
} else {
pastStem = stem + "었";
}
}
}

for (
const [basicAlternativeForm, text] of basicAlternativeForms(
pastStem,
isVerb,
/* isPast= */ true,
)
) {
yield [`${basicAlternativeForm}, past`, text];
}

for (
const [basicAlternativeForm, text] of basicAlternativeForms(
combine모음or자음(stem, "ㄹ", "을"),
isVerb,
)
) {
yield [`${basicAlternativeForm}, future`, text];
}

for (
const [form, suffix] of [
["informal casual", "겠어"],
["informal polite", "겠어요"],
["formal casual", "겠다"],
["formal polite", "겠습니다"],
]
) {
yield [`${form}, future`, stem + suffix];
}

yield ["noun", stem + "기"];
yield ["noun", combine모음or자음(stem, "ㅁ", "음")];

if (passiveStem !== undefined) {
yield* alternativeForms(passiveStem, isVerb, /* ignorePassive= */ true);
}
if (activeStem !== undefined) {
yield* alternativeForms(activeStem, isVerb, /* ignorePassive= */ true);
}
}
Insert cell
function* basicAlternativeForms(
stem,
isVerb,
isPast,
) {
yield ["unconjugated stem", stem];

if (stem.endsWith("하")) {
const noun = stem.slice(0, -1);

yield ["formal polite", noun + "합니다"];
if (isVerb === undefined || isVerb === true) {
yield ["formal casual", noun + "한다"];
}
if (isVerb === undefined || isVerb === false) {
yield ["formal casual", noun + "하다"];
}
yield ["informal polite", noun + "해요"];
yield ["informal casual", noun + "해"];

return;
}

if (stem.endsWith("시")) {
const wo시 = stem.slice(0, -1);

yield ["formal polite", wo시 + "십니다"];
yield ["formal casual", wo시 + "신다"];
yield ["informal polite", wo시 + "세요"];
yield ["informal casual", wo시 + "셔"];

return;
}

if (stem.endsWith("되")) {
const noun = stem.slice(0, -1);

yield ["formal polite", noun + "됩니다"];
if (isVerb === undefined || isVerb === true) {
yield ["formal casual", noun + "된다"];
}
if (isVerb === undefined || isVerb === false) {
yield ["formal casual", noun + "되다"];
}
yield ["informal polite", noun + "돼요"];
yield ["informal casual", noun + "돼"];

return;
}

const jamo = Jamo.fromSyllables(stem[stem.length - 1]);
const trimmedStem = stem.slice(0, -1);

if (jamo[1] === "ㅏ" && !isPast) {
if (jamo.length === 2) {
yield ["informal casual", stem];
yield ["informal polite", stem + "요"];
yield [
"formal casual",
trimmedStem + (isVerb ? Jamo.toSyllable(jamo[0] + "ㅏㄴ") : jamo) + "다",
];
yield [
"formal polite",
trimmedStem + Jamo.toSyllable(jamo[0] + "ㅏㅂ") + "니다",
];
} else {
yield ["informal casual", stem + "아"];
yield ["informal polite", stem + "아요"];
yield ["formal casual", (isVerb ? stem + "는" : stem) + "다"];
yield ["formal polite", stem + "습니다"];
}
} else if (jamo[1] === "ㅗ") {
if (jamo.length === 2) {
yield ["informal casual", trimmedStem + Jamo.toSyllable(jamo[0] + "ㅘ")];
yield [
"informal polite",
trimmedStem + Jamo.toSyllable(jamo[0] + "ㅘ") + "요",
];
yield [
"formal casual",
(isVerb ? trimmedStem + Jamo.toSyllable(jamo[0] + "ㅗㄴ") : stem) + "다",
];
yield [
"formal polite",
trimmedStem + Jamo.toSyllable(jamo[0] + "ㅗㅂ") + "니다",
];
} else {
yield ["informal casual", stem + "아"];
yield ["informal polite", stem + "아요"];
yield ["formal casual", (isVerb ? stem + "는" : stem) + "다"];
yield ["formal polite", stem + "습니다"];
}
} else if (jamo[1] === "ㅡ" && jamo.length === 2) {
yield ["informal casual", trimmedStem + Jamo.toSyllable(jamo[0] + "ㅓ")];
yield ["informal polite", trimmedStem + Jamo.toSyllable(jamo[0] + "ㅓ") + "요"];
yield ["formal casual", trimmedStem + (isVerb ? stem + "는" : stem) + "다"];
yield [
"formal polite",
trimmedStem + Jamo.toSyllable(jamo[0] + "ㅡㅂ") + "니다",
];
} else {
if (stem[stem.length - 1] === "업") {
yield ["informal casual", trimmedStem + "어워"];
yield ["formal polite", trimmedStem + "업니다"];
} else if (jamo.length === 2) {
let casualLastJamo = "";

switch (jamo[1]) {
case "ㅣ":
casualLastJamo = jamo[0] + "ㅕ";
break;

case "ㅓㅔ":
casualLastJamo = jamo[0] + jamo[1];
break;

default:
casualLastJamo = jamo[0] + jamo[1];
break;
}

yield ["informal casual", trimmedStem + Jamo.toSyllable(casualLastJamo)];
yield [
"formal polite",
trimmedStem + Jamo.toSyllable(jamo[0] + jamo[1] + "ㅂ") + "니다",
];
} else {
yield ["informal casual", stem + "어"];
yield ["informal polite", stem + "어요"];
yield ["formal polite", stem + "습니다"];
yield ["format casual", (isVerb ? stem + "는" : stem) + "다"];
}
}
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more