verb-master

web application to practice verb conjugations for the korean language
git clone git://brookjeynes.dev/bjeynes/verb-master.git
Log | Files | Refs | README | LICENSE

merge_rules.js (3484B)


      1 // SPDX-License-Identifier: AGPL-3.0-or-later
      2 // Copyright (C) 2009 Dan Bravender
      3 // Modifications Copyright (c) 2026 Brook Jeynes <me@brookjeynes.dev>
      4 import { getLead, getPadchim, getVowel, hasHiddenPadchim, join, matchGeulja } from "./hangul.js";
      5 /**
      6  * Helper function for defining common contractions between a character without
      7  * a padchim and a character that starts with 'ᄋ', e.g. ㅐ + ㅕ -> ㅐ when
      8  * applied to 해 + 였 yields 했.
      9  *
     10  * @param {string} vowel1
     11  * @param {string} vowel2
     12  * @param {string} new_vowel
     13  * @returns {Rule} The created rule.
     14  */
     15 function vowelContraction(vowel1, vowel2, new_vowel) {
     16     function rule(x, y) {
     17         if (matchGeulja(x[x.length - 1], undefined, vowel1, null) && matchGeulja(y[0], "ᄋ", vowel2, undefined)) {
     18             return [`vowel contraction [${vowel1} + ${vowel2} -> ${new_vowel}]`, x.substring(0, x.length - 1) + join(getLead(x[x.length - 1]), new_vowel, getPadchim(y[0])) + y.substring(1)];
     19         }
     20         return null;
     21     }
     22     return rule;
     23 }
     24 /**
     25  * Helper function for defining merges where a character will take the padchim
     26  * of a merged character if the first character doesn't already have a padchim,
     27  * .e.g. 습 -> 가 + 습니다 -> 갑니다.
     28  */
     29 function noPadchimRule(geuljas) {
     30     function rule(x, y) {
     31         if (!getPadchim(x[x.length - 1]) && geuljas.includes(y[0])) {
     32             return ["borrow padchim", x.substring(0, x.length - 1) + join(getLead(x[x.length - 1]), getVowel(x[x.length - 1]), getPadchim(y[0])) + y.substring(1)];
     33         }
     34         return null;
     35     }
     36     return rule;
     37 }
     38 export const merge_rules = [
     39     noPadchimRule(["을", "습", "읍", "는", "음"]),
     40     (x, y) => {
     41         if (getPadchim(x[x.length - 1]) === "ᆯ" && y.startsWith("음")) {
     42             return ["ㄹ + ㅁ -> ᆱ", x.slice(0, x.length - 1) + join(getLead(x[x.length - 1]), getVowel(x[x.length - 1]), "ᆱ")];
     43         }
     44         return null;
     45     },
     46     vowelContraction("ㅐ", "ㅓ", "ㅐ"),
     47     vowelContraction("ㅡ", "ㅓ", "ㅓ"),
     48     vowelContraction("ㅜ", "ㅓ", "ㅝ"),
     49     vowelContraction("ㅗ", "ㅏ", "ㅘ"),
     50     vowelContraction("ㅚ", "ㅓ", "ㅙ"),
     51     vowelContraction("ㅙ", "ㅓ", "ㅙ"),
     52     vowelContraction("ㅘ", "ㅓ", "ㅘ"),
     53     vowelContraction("ㅝ", "ㅓ", "ㅝ"),
     54     vowelContraction("ㅏ", "ㅏ", "ㅏ"),
     55     vowelContraction("ㅡ", "ㅏ", "ㅏ"),
     56     vowelContraction("ㅣ", "ㅓ", "ㅕ"),
     57     vowelContraction("ㅓ", "ㅓ", "ㅓ"),
     58     vowelContraction("ㅓ", "ㅣ", "ㅐ"),
     59     vowelContraction("ㅏ", "ㅣ", "ㅐ"),
     60     vowelContraction("ㅑ", "ㅣ", "ㅒ"),
     61     vowelContraction("ㅒ", "ㅓ", "ㅒ"),
     62     vowelContraction("ㅔ", "ㅓ", "ㅔ"),
     63     vowelContraction("ㅕ", "ㅓ", "ㅕ"),
     64     vowelContraction("ㅏ", "ㅕ", "ㅐ"),
     65     vowelContraction("ㅖ", "ㅓ", "ㅖ"),
     66     vowelContraction("ㅞ", "ㅓ", "ㅞ"),
     67     // Rule: Don't append 으 to ㄹ irregulars.
     68     (x, y) => {
     69         if (getPadchim(x[x.length - 1]) === "ᆯ" && y.startsWith("면")) {
     70             return ["join", x.toString() + y.toString()];
     71         }
     72         return null;
     73     },
     74     // Rule: 으 insertion.
     75     (x, y) => {
     76         const geuljas = ["면", "세", "십"];
     77         if ((hasHiddenPadchim(x[x.length - 1]) || getPadchim(x[x.length - 1])) && geuljas.includes(y[0])) {
     78             return ["padchim + consonant -> insert 으", x + "으" + y];
     79         }
     80         return null;
     81     },
     82     // Default rule: Just append the contents.
     83     (x, y) => ["join", x.toString() + y.toString()],
     84 ];