-
Notifications
You must be signed in to change notification settings - Fork 14
/
Copy pathhigh_tang.js
175 lines (154 loc) · 6.78 KB
/
high_tang.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
/* 推導盛唐(平水韻)擬音
*
* 盛唐通用語沒有直接描述音系的材料,但有詩韻(「平水韻」)和日語漢音作爲緊密相關的材料
*
* 來源:「平水韻」擬音
* https://phesoca.com/aws/351/ 或
* https://www.bilibili.com/read/cv37390491/ 或
* https://zhuanlan.zhihu.com/p/681190661
*
* @author unt
*/
/** @type { 音韻地位['屬於'] } */
const is = (...x) => 音韻地位.屬於(...x);
/** @type { 音韻地位['判斷'] } */
const when = (...x) => 音韻地位.判斷(...x);
const 非組字典 = {
'f': { 幫: 'f', 滂: 'fʰ', 並: 'v', 明: 'ɱ' },
'pf': { 幫: 'pf', 滂: 'pfʰ', 並: 'bv', 明: 'ɱ' },
};
function get選單(音類列表, 音標列表s, 音類音標連接符 = ' ', 音類連接符 = ' | ') {
return 音標列表s.map(音標列表 => ({
value: 音標列表.join(','),
text: 音標列表.map((音標, i) => 音類列表[i] + 音類音標連接符 + 音標).join(音類連接符),
}));
}
if (!音韻地位) return [
'聲',
['非組', [1, ...Object.keys(非組字典)]],
[`等類記法
j 代表聲母腭化、ɣ 代表聲母軟腭化,不是介音;
非組和莊章組後總是不寫等類記號`, [1, ...get選單(
['三A', '三BC', '一二四'],
[['j', 'ɣ', ''], ['ʲ', 'ˠ', '']],
' C',
)]],
['見組非三等簡寫作軟腭音', false],
'韻',
['低元音', [2, ...get選單(['前', '後'], [['æ', 'a'], ['æ', 'ɑ'], ['a', 'ɑ']])]],
['後高元音\n微韻開口總爲 ɨj,不受本選項影響', [1, ...get選單(['閉音節', '魚韻'], [['ɨ', 'ɨ'], ['ə', 'ɨ'], ['ə', 'ɯ']])]],
['支脂合併', false],
['咍泰合併', false],
['覃談合併', true],
['東一冬合併', false],
['輕脣東鍾合併', false],
['部分蟹攝二等入假攝', false],
['部分流攝脣音入遇攝', false],
'調',
['聲調', [2, '五度符號', '附加符號', '調類數字']],
['全濁上歸去', false],
];
function 調整音韻地位() {
function 調整(表達式, 調整屬性, 字頭串 = null) {
if (typeof (字頭串) === 'string' && !字頭串.includes(字頭)) return;
if (is(表達式)) 音韻地位 = 音韻地位.調整(調整屬性);
}
// 輕唇化例外
調整('明母 尤韻', { 等: '一', 類: null, 韻: '侯' });
調整('明母 東韻', { 等: '一', 類: null });
// [慧琳反切體現的, 唐代用韻體現的, 據今音推測的]
const 蟹攝二等入假攝字 = ['崖咼(呙)扠涯搋派差絓畫(画)罣罷(罢)', '佳鼃娃解釵(钗)卦柴', '哇洼蛙灑蝸話(话)掛挂查叉杈衩'].join('');
const 流攝脣音入遇攝字 = ['浮戊母罦罘蜉矛茂覆懋拇某負(负)阜', '謀(谋)部畝(亩)畮婦(妇)不否桴富牟缶', '復複(复)副牡'].join('');
if (選項.部分蟹攝二等入假攝) 調整('蟹攝 二等', { 韻: '麻' }, 蟹攝二等入假攝字);
if (選項.部分流攝脣音入遇攝) 調整('幫組 尤侯韻', { 韻: is`尤韻` ? '虞' : '模' }, 流攝脣音入遇攝字);
}
調整音韻地位();
function get聲母() {
let 等類記法 = 選項.等類記法.split(',');
let 聲母 = when([
['幫組 C類', 非組字典[選項.非組][音韻地位.母]],
[!選項.見組非三等簡寫作軟腭音 && '見溪疑曉匣母 非 三等', {
見: 'q', 溪: 'qʰ', 疑: 'ɴ', 曉: 'χ', 匣: 'ʁ',
}[音韻地位.母]],
['', {
幫: 'p', 滂: 'pʰ', 並: 'b', 明: 'm',
端: 't', 透: 'tʰ', 定: 'd', 泥: 'n', 來: 'l',
知: 'ʈ', 徹: 'ʈʰ', 澄: 'ɖ', 孃: 'ɳ',
精: 'ts', 清: 'tsʰ', 從: 'dz', 心: 's', 邪: 'z',
莊: 'tʂ', 初: 'tʂʰ', 崇: 'dʐ', 生: 'ʂ', 俟: 'ʐ',
章: 'tɕ', 昌: 'tɕʰ', 常: 'dʑ', 書: 'ɕ', 船: 'ʑ', 日: 'ɲ', 以: 'j',
見: 'k', 溪: 'kʰ', 羣: 'ɡ', 疑: 'ŋ',
影: 'ʔ', 曉: 'x', 匣: 'ɣ', 云: '',
}[音韻地位.母]],
]) + when([
['幫組 C類', ''],
['莊章組 或 日以母', ''],
['三等 (A類 或 精組)', 等類記法[0]],
['三等', 等類記法[1]],
['', 等類記法[2]],
]);
聲母 = 聲母.replace(/ʰ([ʲˠ])/, '$1ʰ');
聲母 = 聲母.replace(/^ˠ/, 'ɰ');
return 聲母;
}
function get介音() {
return is`合口` ? 'w' : '';
}
function get韻基() {
let 韻基 = when([
[選項.支脂合併 === true && '脂之韻', 'i'],
[選項.咍泰合併 === true && '灰咍韻', 'ɑj'], // 不含廢韻
['脂之韻', 'ij'], ['微韻', [['開口', 'ɨj'], ['', 'uj']]],
['齊祭韻', 'ej'], ['灰咍廢韻', 'əj'],
['佳皆夬韻', 'æj'], ['泰韻', 'ɑj'],
['支佳韻', 'i'], ['魚韻', 'ɨ'], ['虞模韻', 'u'],
['麻韻', 'æ'], ['歌韻', 'ɑ'],
['尤侯幽韻', 'ɨw'],
['蕭宵韻', 'ew'],
['肴韻', 'æw'], ['豪韻', 'ɑw'],
['真臻韻', 'in'], ['殷韻', 'ɨn'], ['文韻', 'un'],
['先仙韻', 'en'], ['元魂痕韻', 'ən'],
['刪山韻', 'æn'], ['寒韻', 'ɑn'],
['侵韻', 'im'],
['鹽添韻', 'em'], ['嚴凡韻', 'əm'], [選項.覃談合併 === false && '覃韻', 'əm'],
['咸銜韻', 'æm'], ['覃談韻', 'ɑm'],
[選項.東一冬合併 === true && '冬韻', 'ɨwŋ'],
[選項.輕脣東鍾合併 === true && '通攝 幫組 C類', 'uŋ'],
['蒸登韻', 'ɨŋ'], ['東韻', 'ɨwŋ'], ['冬鍾韻', 'uŋ'],
['青韻', 'eŋ'],
['庚耕清韻', 'æŋ'], ['陽唐韻', 'ɑŋ'], ['江韻', 'æwŋ'],
]);
韻基 = 韻基.replace(/ɨ(?=$|[^j])/, 選項.後高元音.split(',')[+is`魚韻`]);
韻基 = 韻基.replace('æ', 選項.低元音.split(',')[0]);
韻基 = 韻基.replace('ɑ', 選項.低元音.split(',')[1]);
if (is`入聲`) [...'mnŋɴ'].forEach((v, i) => { 韻基 = 韻基.replace(v, 'ptkq'[i]); });
return 韻基;
}
function get聲調() {
const is陰 = is`全清 或 次清 或 次濁 上入聲`;
return {
五度符號: is陰 ?
{ 平: '˦˨', 上: '˦˥', 去: '˧˨˦', 入: '˦' } :
{ 平: '˨˩', 上: '˨˦', 去: '˨˨˦', 入: '˨' },
附加符號: { 平: '̀', 上: '́', 去: '̌', 入: '' },
調類數字: { 平: '¹', 上: '²', 去: '³', 入: '⁴' },
}[選項.聲調][選項.全濁上歸去 && is`全濁 上聲` ? '去' : 音韻地位.聲];
}
function get音節() {
const 音節 = {
聲母: get聲母(),
介音: get介音(),
韻基: get韻基(),
聲調: get聲調(),
};
if (音節.韻基[0] === 'i') 音節.聲母 = 音節.聲母.replace(/(?<!^)j/, '');
if (音節.介音 === 'w') 音節.聲母 = 音節.聲母.replace('ɰ', '');
if (音節.韻基[0] === 'u') 音節.介音 = 音節.介音.replace('w', '');
音節.韻母 = 音節.介音 + 音節.韻基;
音節.帶調韻基 = 選項.聲調 === '附加符號' ?
音節.韻基[0] + 音節.聲調 + 音節.韻基.slice(1) :
音節.韻基 + 音節.聲調;
return 音節;
}
const 音節 = get音節();
return 音節.聲母 + 音節.介音 + 音節.帶調韻基;