diff --git a/taibu.js b/taibu.js index 9480129..f780642 100644 --- a/taibu.js +++ b/taibu.js @@ -9,6 +9,8 @@ /** @type { 音韻地位['屬於'] } */ const is = (...x) => 音韻地位.屬於(...x); +/** @type { 音韻地位['判斷'] } */ +const when = (...x) => 音韻地位.判斷(...x); // 推導選項 if (!音韻地位) return [ @@ -25,273 +27,233 @@ const 輕脣 = ['f', 'v']; const 翹舌或輕脣 = 翹舌.concat(輕脣); function 聲母規則(白讀) { - if (is`幫母`) { - if (is`東韻 三等 或 鍾微虞廢文元陽尤凡韻` && !白讀) return 'f'; - return 'b'; - } - if (is`滂母`) { - if (is`東韻 三等 或 鍾微虞廢文元陽尤凡韻` && !白讀) return 'f'; - return 'p'; - } - if (is`並母`) { - if (is`東韻 三等 或 鍾微虞廢文元陽尤凡韻` && !白讀) return 'f'; - return 'p'; - } - if (is`明母`) { - if (is`東韻 三等 或 鍾微虞廢文元陽尤凡韻` && !白讀) return 'v'; - return 'm'; - } - - if (is`端母`) return 'd'; - if (is`透母`) return 't'; - if (is`定母`) return 't'; - if (is`泥母`) return 'n'; - if (is`來母`) return 'l'; - - if (is`知母`) return is`二等` ? 'z' : 'zh'; - if (is`徹母`) return is`二等` ? 'c' : 'ch'; - if (is`澄母`) return is`二等` ? 'c' : 'ch'; - if (is`孃母`) return 'n'; - - if (is`精母`) return 'z'; - if (is`清母`) return 'c'; - if (is`從母`) return 'c'; - if (is`心母`) return 's'; - if (is`邪母`) { - if (is`支脂之微韻 去聲`) return 'c'; - if (is`魚虞模東冬鍾侵韻 平聲`) return 'c'; - if (is`侯尤幽麻韻`) return 'c'; - return 's'; - } - - if (is`莊母`) return 'z'; - if (is`初母`) return 'c'; - if (is`崇母`) return 'c'; - if (is`生母`) return 's'; - if (is`俟母`) return 'c'; - - if (is`章母`) return 'zh'; - if (is`昌母`) return 'ch'; - if (is`常母`) return 'sh'; - if (is`書母`) return 'sh'; - if (is`船母`) return 'sh'; - if (is`日母`) return 'ng'; - - if (is`見母`) return 'g'; - if (is`溪母`) return 'k'; - if (is`羣母`) return 'k'; - if (is`疑母`) return 'ng'; - - if (is`曉母`) { - if (is`合口`) return 'f'; - if (is`三四等`) return 'x'; - return 'h'; - } - if (is`匣母`) { - if (is`合口 或 東模韻`) return 'f'; - if (is`開口 四等`) return 'x'; - return 'h'; - } - if (is`影母`) { - if (is`合口`) return 'v'; - if (is`三四等`) return 'rh'; - return ''; - } - if (is`云母`) { - if (is`東韻`) return 'x'; - if (is`支脂之微唐陽韻 或 魚虞模韻 平聲`) return 'v'; - return 'rh'; - } - if (is`以母`) { - if (is`支脂之微韻 合口`) return 'v'; - return 'rh'; - } - - throw new Error('無聲母規則'); + return when([ + [!白讀 && '幫滂並母 C類', 'f'], + [!白讀 && '明母 C類', 'v'], + ['幫母', 'b'], + ['滂並母', 'p'], + ['明母', 'm'], + + ['端母', 'd'], + ['透定母', 't'], + ['泥孃母', 'n'], + ['來母', 'l'], + + ['知母 二等 或 精莊母', 'z'], + ['徹澄母 二等 或 清從初崇俟母 或 邪母 (止攝 去聲 或 遇通深攝 平聲 或 流假攝)', 'c'], + ['心邪生母', 's'], + + ['知章母', 'zh'], + ['徹澄昌母', 'ch'], + ['常書船母', 'sh'], + + ['見母', 'g'], + ['溪羣母', 'k'], + ['日疑母', 'ng'], + + ['曉母 合口 或 匣母 (合口 或 東模韻)', 'f'], + ['曉母 三四等 或 匣母 開口 四等', 'x'], + ['曉匣母', 'h'], + + ['影母 合口 或 云母 (止宕攝 或 遇攝 平聲) 或 以母 止攝 合口', 'v'], + ['云母 東韻', 'x'], + ['影母 三四等 或 云以母', 'rh'], + ['影母', ''], + ], '無聲母規則'); } function 韻母規則(白讀) { - // 通攝 - if (is`東冬鍾韻 幫組`) return 'ung'; - if (is`東冬鍾韻 一等`) return 'ung'; - if (is`東冬鍾韻 三等`) return 'iung'; // (>ung/翹舌_) - - // 江攝 - if (is`江韻`) return 'ong'; // 例外: 窗雙 ung - - // 宕攝 - if (is`唐韻 幫組`) return 'ong'; - if (is`唐韻 開口`) return 'ong'; - if (is`唐韻 合口`) return 'uong'; // (>ong/輕脣_) - if (is`陽韻 幫組`) return 白讀 ? 'iong' : 'ong'; - if (is`陽韻 莊組`) return 'ong'; - if (is`陽韻 開口`) return 'iong'; // (>ong/翹舌_) - if (is`陽韻 合口`) return 'uong'; // (>ong/輕脣_) - - // 止攝 - if (is`支脂韻 幫組`) return 'i'; // 例外: 美費 ui - if (is`微韻 幫組`) return 'ui'; - if (is`支脂之微韻 開口`) return 'i'; // (>ii/平翘舌_) 例外: 知姊死四 i - if (is`支脂之微韻 合口`) return 'ui'; // 例外: 炊吹衰睡 oi - - // 遇攝 - if (is`虞韻 幫組`) return 'u'; - if (is`魚虞韻 莊組`) return 'ii'; - if (is`魚虞韻`) { - if (is`知章組`) return 'u'; - return 'i'; // (>ii/翘舌_) - } - if (is`模韻`) return 'u'; // 例外: 蜈梧吾吳午五伍 零韻母 - - // 蟹攝 - if (is`咍韻`) return 白讀 ? 'oi' : 'ai'; - if (is`泰韻 幫組`) return 'ui'; - if (is`泰韻 開口`) return 'ai'; // 例外: 蓋害 oi - if (is`泰韻 合口`) { - if (is`見組`) return 'uai'; - return 'ui'; - } - if (is`灰廢韻`) return 白讀 ? 'oi' : 'ui'; - if (is`佳韻 幫組`) return 'ai'; - if (is`佳韻 開口`) { - if (is`影組`) return 'ei'; - return 'ai'; - } - if (is`佳韻 合口`) return 'ua'; // (>a/輕脣_) - if (is`皆夬韻 幫組`) return 'ai'; - if (is`皆夬韻 開口`) return 'ai'; - if (is`皆夬韻 合口`) return 'uai'; // (>ai/輕脣_) - if (is`齊祭韻 幫組`) return 'i'; - if (is`祭韻 開口`) return 'i'; // (>ii/翹舌_) - if (is`祭韻 合口`) return 白讀 ? 'oi' : 'ui'; // 例外: 脆 cioi5 歲 sei5 - if (is`齊韻 開口`) { - if (is`影組`) return 'i'; - return 白讀 ? 'ei' : 'i'; // 例外: 梯 toi1 - } - if (is`齊韻 合口`) return 'ui'; - - // 臻攝 - if (is`痕韻`) return 'en'; // 例外: 吞 tun1; 痕 fin2 - if (is`魂韻`) return 'un'; - if (is`真韻 幫組`) return 'in'; // 例外: 閩敏憫 en; 密蜜 ed - if (is`文韻 幫組`) return 'un'; - if (is`真臻文殷韻 見組`) return 白讀 ? 'iun' : 'in'; - if (is`真臻文殷韻 開口`) return 'in'; // 例外: 韌 ngiun5 瑟 sed7 - if (is`真臻文殷韻 合口`) { - if (is`精組`) return 'un'; - return 'iun'; // (>un/翹舌_) - } - - // 山攝 - if (is`寒韻 幫組`) return 'an'; - if (is`寒韻 開口`) { - if (is`見影組`) return 'on'; - return 'an'; // 例外: 餐 on - } else if (is`寒韻 合口`) { - if (is`見影組`) return 'uan'; // (>an/輕脣_) - return 'on'; - } - if (is`刪山韻 幫組`) return 'an'; // 例外: 慢 een; 八捌 eed - if (is`刪山韻 開口`) { - if (is`見影組`) return 'ien'; // 例外: 限 een; 瞎 eed - return 'an'; - } else if (is`刪山韻 合口`) { - if (is`見影組`) return 'uan'; // (>an/輕脣_) - return 'on'; - } - if (is`仙韻 幫組`) return 'ien'; - if (is`仙韻 開口`) return 'ien'; // (>een/翹舌_) - if (is`仙韻 合口`) { - if (is`見影組`) return 'ien'; // (>een/翹舌_) 例外: 圓 vien2 - if (is`精莊組 入聲`) return 'ied'; - return 'ion'; // (>on/翹舌_) - } - if (is`先韻`) { - if (is`幫組`) return 白讀 ? 'een' : 'ien'; - if (is`端組`) return 'een'; - if (is`來母`) return 'een'; - return 'ien'; // (>een/翹舌_) - } - if (is`元韻`) { - if (is`幫組`) return 'an'; // 例外: 飯 on - return 'ien'; // (>een/翹舌_) 例外: 冤園遠 ien - } - - // 效攝 - if (is`豪韻`) return 'ou'; // 例外: 熬靠考袍 au - if (is`肴韻`) return 'au'; // (>au/翹舌_) - if (is`宵韻`) return 'iau'; // (>au/翹舌_) - if (is`蕭韻`) { - if (is`端組`) return 'eeu'; - if (is`來母`) return 'eeu'; - return 'iau'; // (>au/翹舌_) - } - - // 果攝 - if (is`歌韻 一等`) return 'ou'; - if (is`歌韻 三等`) return 'iau'; - - // 假攝 - if (is`麻韻 幫組`) return 'a'; - if (is`麻韻 二等 開口`) return 'a'; - if (is`麻韻 二等 合口`) return 'ua'; // (>a/輕脣_) - if (is`麻韻 三等`) return 'ia'; // (>a/翹舌_) - if (is`麻韻`) return 'a'; // 其他(如四等爹小韻) - - // 梗攝 - if (is`庚韻 二等 幫組`) return 白讀 ? 'ang' : 'en'; - if (is`庚韻 二等 開口`) return 白讀 ? 'ang' : 'en'; - if (is`庚韻 二等 合口`) return 白讀 ? 'uang' : 'uen'; // (>白ang|文en/輕脣_) - if (is`庚韻 三等 幫組`) return 白讀 ? 'iang' : 'in'; // 例外: 盟 en - if (is`庚韻 三等 開口`) return 白讀 ? 'iang' : 'in'; // (>白ang|文in/翹舌_) 例外: 省 en - if (is`庚韻 三等 合口`) return 白讀 ? 'iung' : 'un'; // (>白ung|文un/翹舌_) 例外: 憬 in - if (is`耕韻`) return 白讀 ? 'ang' : 'en'; // 例外: 拼莖 in - if (is`清韻`) return 白讀 ? 'iang' : 'in'; // (>白ang|文in/翹舌_) 例外: 碧 ed - if (is`青韻`) { - if (is`端見組 舒聲`) return 'en'; - if (is`端見組 入聲`) return 'id'; - if (is`來母 舒聲`) return 'en'; - if (is`來母 入聲`) return 'id'; - return 白讀 ? 'iang' : 'in'; // 例外: 星 en - } - - // 曾攝 - if (is`蒸韻`) { - if (is`莊組`) return 'en'; - return 'in'; - } - if (is`登韻`) return 'en'; // 例外: 國 ued - - // 流攝 - if (is`侯韻`) return 'eu'; - if (is`尤幽韻`) return 'iu'; - - // 深攝 - if (is`侵韻`) { - if (is`莊組`) return 'em'; - return 'im'; - } - - // 咸攝 - if (is`覃談咸銜凡韻`) return 'am'; // 例外: 鹹 eem; 減 iam; 夾插 iab - if (is`鹽嚴韻`) return 'iam'; // (>am/翹舌_) 例外: 黏驗 eem; 躡 eeb - if (is`添韻`) { - if (is`端組`) return 'eem'; - if (is`來母`) return 'eem'; - return 'iam'; // (>am/翹舌_) - } - - throw new Error('無韻母規則'); + return when([ + ['通攝', [ + ['脣音 或 一等', 'ung'], + ['三等', 'iung'], // (>ung/翹舌_) + ]], + + ['止攝', [ + ['脣音 微韻', 'ui'], + ['脣音 或 開口', 'i'], // (>ii/平翹舌_) 例外: 美費 ui 知姊死四 i + ['合口', 'ui'], // 例外: 炊吹衰睡 oi + ]], + + ['遇攝', [ + ['一等 或 虞韻 脣音 或 知章組', 'u'], // 例外: 蜈梧吾吳午五伍 零韻母 + ['莊組', 'ii'], + ['', 'i'], // (>ii/翹舌_) + ]], + + ['蟹攝', [ + ['三等', [ + ['廢韻 或 合口', 白讀 ? 'oi' : 'ui'], // 例外: 脆 cioi5 歲 sei5 + ['', 'i'], // (>ii/翹舌_) + ]], + ['四等', [ + ['脣音 或 開口 影組', 'i'], + ['開口', 白讀 ? 'ei' : 'i'], // 例外: 梯 toi1 + ['', 'ui'], + ]], + ['二等', [ + ['佳韻 合口', 'ua'], // (>a/輕脣_) + ['合口', 'uai'], // (>ai/輕脣_) + ['佳韻 影組', 'ei'], + ['', 'ai'], + ]], + ['一等', [ + ['咍韻', 白讀 ? 'oi' : 'ai'], + ['灰韻', 白讀 ? 'oi' : 'ui'], + ['泰韻', [ + ['開口', 'ai'], // 例外: 蓋害 oi + ['合口 見組', 'uai'], + ['', 'ui'], + ]], + ]], + ]], + + ['臻攝', [ + ['三等', [ + ['真韻 脣音', 'in'], // 例外: 閩敏憫 en; 密蜜 ed + ['文韻 脣音', 'un'], + ['見組', 白讀 ? 'iun' : 'in'], + ['開口', 'in'], // 例外: 韌 ngiun5 瑟 sed7 + ['合口 精組', 'un'], + ['合口', 'iun'], // (>un/翹舌_) + ]], + ['一等', [ + ['脣音 或 合口', 'un'], + ['', 'en'], // 例外: 吞 tun1; 痕 fin2 + ]], + ]], + + ['山攝', [ + ['三等', [ + ['元韻 脣音', 'an'], // 例外: 飯 on + ['脣音 或 開口', 'ien'], // (>een/翹舌_) + ['合口', [ + ['元韻 或 見影組', 'ien'], // 例外: 冤園遠 ien + ['精莊組 入聲', 'ied'], + ['', 'ion'], // (>on/翹舌_) + ]], + ]], + ['四等', [ + ['脣音', 白讀 ? 'een' : 'ien'], + ['端組 或 來母', 'een'], + ['', 'ien'], + ]], + ['一二等', [ + ['脣音', 'an'], + ['開口', [ + ['見影組 二等', 'ien'], // 例外: 限 een; 瞎 eed + ['見影組', 'on'], + ['', 'an'], // 例外: 餐 on + ]], + ['合口', [ + ['見影組', 'uan'], // (>an/輕脣_) + ['', 'on'], + ]], + ]], + ]], + + ['效攝', [ + ['三等', 'iau'], // (>au/翹舌_) + ['四等', [ + ['端組 或 來母', 'eeu'], + ['', 'iau'], + ]], + ['二等', 'au'], // (>au/翹舌_) + ['一等', 'ou'], // 例外: 熬靠考袍 au + ]], + + ['果假攝', [ + ['麻韻 脣音', 'a'], + ['三等', [ + ['歌韻', 'iau'], + ['麻韻', 'ia'], // (>a/翹舌_) + ]], + ['二等', [ + ['脣音 或 開口', 'a'], + ['合口', 'ua'], // (>a/輕脣_) + ]], + ['一等', 'ou'], + ['四等', 'a'], // 爹小韻 + ]], + + ['宕江攝', [ + ['三等', [ + ['脣音', 白讀 ? 'iong' : 'ong'], + ['莊組', 'ong'], + ['開口', 'iong'], // (>ong/翹舌_) + ['合口', 'uong'], // (>ong/輕脣_) + ]], + ['一二等', [ + ['江攝 或 脣音 或 開口', 'ong'], // 例外: 窗雙 ung + ['', 'uong'], // (>ong/輕脣_) + ]], + ]], + + ['梗曾攝', [ + ['三等', [ + ['曾攝', [ + ['莊組', 'en'], + ['', 'in'], + ]], + ['梗攝', [ + ['清韻 或 庚韻 (脣音 或 開口)', 白讀 ? 'iang' : 'in'], // 例外: 盟省 en、碧 ed + ['', 白讀 ? 'iung' : 'un'], // 例外: 憬 in + ]], + ]], + ['四等', [ + ['端見組 或 來母', [ + ['舒聲', 'en'], + ['入聲', 'id'], + ]], + ['', 白讀 ? 'iang' : 'in'], // 例外: 星 en + ]], + ['二等', [ + ['耕韻 或 脣音 或 開口', 白讀 ? 'ang' : 'en'], // 例外: 拼莖 in + ['', 白讀 ? 'uang' : 'uen'], // (>白ang|文en/輕脣_) + ]], + ['一等', 'en'], // 例外: 國 ued + ]], + + ['流攝', [ + ['三四等', 'iu'], + ['一等', 'eu'], + ]], + + ['深攝', [ + ['莊組', 'em'], + ['', 'im'], + ]], + + ['咸攝', [ + ['一二等 或 脣音 C類', 'am'], // 例外: 鹹 eem; 減 iam; 夾插 iab + ['三等', 'iam'], // (>am/翹舌_) + ['四等', [ + ['端組 或 來母', 'eem'], + ['', 'iam'], // (>am/翹舌_) 例外: 黏驗 eem; 躡 eeb + ]], + ]], + ], '無韻母規則'); } function 聲調規則(白讀) { - if (is`平聲`) return is`全清 或 次清` ? '1' : '2'; - if (is`上聲` && 白讀) return is`次濁 或 全濁` ? '1' : '3'; - if (is`上聲` && !白讀) return is`全清 或 次清 或 次濁` ? '3' : '5'; - if (is`去聲`) return '5'; - if (is`入聲`) return is`全清 或 次清` ? '7' : '8'; - - throw new Error('無聲調規則'); + return when([ + ['清音', [ + ['平聲', '1'], + ['上聲', '3'], + ['去聲', '5'], + ['入聲', '7'], + ]], + ['濁音', [ + ['平聲', '2'], + ['上聲', [ + [白讀, '1'], + ['次濁', '3'], + ['全濁', '5'], + ]], + ['去聲', '5'], + ['入聲', '8'], + ]], + ], '無聲調規則'); } function 聲母處理(聲母, 韻母) { @@ -314,11 +276,10 @@ function 韻母預先處理(韻母) { function 韻母善後處理(聲母, 韻母) { // 先處理 i 相關韻母 - if (is`支脂之微韻 開口` && 韻母 === 'i' && 平舌或翹舌.includes(聲母)) { + if (is`止攝 開口` && 韻母 === 'i' && 平舌或翹舌.includes(聲母)) { 韻母 = 'ii'; } - if (is`魚虞韻` && 韻母 === 'i' && 翹舌.includes(聲母)) 韻母 = 'ii'; - if (is`祭韻 開口` && 韻母 === 'i' && 翹舌.includes(聲母)) 韻母 = 'ii'; + if (is`遇攝 或 祭韻 開口` && 韻母 === 'i' && 翹舌.includes(聲母)) 韻母 = 'ii'; // 處理一般情況 if (韻母.startsWith('ie') && 翹舌.includes(聲母)) { 韻母 = 'ee' + 韻母.slice(2); @@ -336,7 +297,7 @@ function 韻母善後處理(聲母, 韻母) { } // 依選項分別推導 -let 白讀音, 文讀音 = null; +let 白讀音 = null, 文讀音 = null; function 根據規則推導讀音(白讀) { let 讀音 = {