Skip to content

Implement 音韻地位.合法性 #5

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 12 commits into
base: feat-0.5.x
Choose a base branch
from
52 changes: 52 additions & 0 deletions src/QieyunEncoder/_音位配列規則表.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# -*- coding: utf-8 -*-


from enum import IntEnum

class 合法性等級(IntEnum):
無效, 強非法, 弱非法, 弱合法, 稀有合法, 強合法 = range(6)

@property
def 字符串(self) -> str:
return self.name


# 以下規則只適用於更優音韻地位
# (合法性等級, 禁止的情況, 排除的情況)
音位配列規則表 = [
(合法性等級.無效, '陰聲韻 入聲', None),
(合法性等級.無效, '邪章昌船書常日以羣母 一二四等', None),
(合法性等級.無效, '端組 二三等', None), # 地打
(合法性等級.強非法, '次入韻', '去聲'),
(合法性等級.強非法, '幫組 之韻', None),
(合法性等級.強非法, '陽唐庚耕清青蒸登韻 銳音 合口', '以母 清韻'),
(合法性等級.強非法, '四等 合口 銳音', None),
(合法性等級.強非法, '云母 開口', '宵侵鹽韻'),
(合法性等級.強非法, '麻韻 三等', '銳音 開口'),
(合法性等級.強非法, '侵鹽韻 重紐A類', '影母'),
(合法性等級.強非法, '俟母', '之韻'),
(合法性等級.弱非法, '來母 二等', None),
(合法性等級.弱非法, '歌韻 三等', '見影組 平聲'),
(合法性等級.弱非法, '痕韻 銳音', None),
(合法性等級.弱非法, '幫組 蕭添韻', None),
(合法性等級.弱非法, '祭韻 見影組 重紐A類', '影母'),
(合法性等級.弱非法, '祭韻 幫組 重紐B類', None),
(合法性等級.弱合法, '冬韻 鈍音 舒聲', None),
(合法性等級.弱合法, '船母 尤之東陽祭宵鹽韻', None),
(合法性等級.弱合法, '麻韻 三等 知組', None),
(合法性等級.弱合法, '蒸韻 合口 舒聲', None),
(合法性等級.弱合法, '東韻 三等 上聲', None),
(合法性等級.弱合法, '佳麻皆夬韻 合口 知組', None),
(合法性等級.弱合法, '山刪韻 合口 舒聲 知組', None),
(合法性等級.稀有合法, '銜韻 知組', None),
(合法性等級.稀有合法, '云母 鍾韻', None),
(合法性等級.稀有合法, '脂仙宵韻 見影組 開口 重紐A類', '影母'),
(合法性等級.稀有合法, '幫組 咸覃銜談韻', None),
(合法性等級.稀有合法, '脂韻 莊組', '生母'),
(合法性等級.稀有合法, '真臻韻 莊組 合口', '生母 入聲'),
(合法性等級.稀有合法, '蒸韻 上聲', None),
(合法性等級.稀有合法, '登韻 合口 上去聲', None),
(合法性等級.稀有合法, '冬韻 上聲', None),
(合法性等級.稀有合法, '皆韻 上聲', '見影組 開口'),
(合法性等級.稀有合法, '邪母 虞東宵韻', None),
]
131 changes: 124 additions & 7 deletions src/QieyunEncoder/音韻地位.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
.. hint::

不要與中古後期三十六字母混淆。

中古後期三十六字母:

<table class="big-table">
Expand Down Expand Up @@ -158,6 +158,7 @@

from .常量 import 常量
from ._母對應的標準等 import 母對應的標準等
from ._音位配列規則表 import 合法性等級, 音位配列規則表
from .工具.母到清濁 import 母到清濁
from .工具.母到組 import 母到組
from .工具.母到音 import 母到音
Expand Down Expand Up @@ -475,7 +476,7 @@ def equal聲(聲: str) -> bool:
@staticmethod
def 驗證(母: str, 呼: Optional[str], 等: str, 重紐: Optional[str], 韻: str, 聲: str):
'''
驗證給定的音韻地位六要素是否合法
初步驗證給定的音韻地位六要素是否合法
'''
assert len(母) == 1 and 母 in 常量.所有母, 'Unexpected 母: ' + repr(母)
assert len(等) == 1 and 等 in 常量.所有等, 'Unexpected 等: ' + repr(等)
Expand Down Expand Up @@ -612,13 +613,129 @@ def from描述(描述: str):

return 音韻地位(母, 呼, 等, 重紐, 韻, 聲)

def is_normal(self):
def 合法性(self) -> tuple[str, Optional['音韻地位']]:
'''
是 normal 的音韻地位。

例如,端母二等不是 normal 的音韻地位。
聲、韻、調組合的合法性。
如果有等價但更優的音韻地位能作爲替代,那麼也返回更優音韻地位,合法性取原地位和更優地位中的較差者。
'''
return self.等 in 母對應的標準等[self.母]
母 = self.母
呼 = self.呼
等 = self.等
重紐 = self.重紐
韻 = self.韻
聲 = self.聲
音韻地位.驗證(母, 呼, 等, 重紐, 韻, 聲)

合法性 = 合法性等級.強合法

類隔 = {
'四': dict(zip('知徹澄孃莊初崇生俟云', '端透定泥精清從心邪匣')),
'一': dict(zip('知徹澄孃莊初崇生俟云', '端透定泥精清從心邪匣')),
'二': dict(zip('端透定泥精清從心邪云', '知徹澄孃莊初崇生俟匣')),
'三': dict(zip('端透定泥匣', '知徹澄孃云')),
}
開合分韻 = dict(zip(
'魚咍痕殷嚴',
'虞灰魂文凡'
))
銳音分韻 = dict(zip(
# 銳音不能拼第一行韻,而第二行相應的韻是其更優音韻地位
# 注意第一行韻不都是 C₁ 類三等韻,例外是恰恰相反的幽/尤之分
'微廢文殷元歌幽嚴凡',
'脂祭真真仙麻尤鹽鹽'
))
莊三化二韻 = {
# 有對應二等韻的三等韻拼莊組時以二等韻作爲更優音韻地位
None: {'鍾': '江'},
'開': dict(zip(
'支祭仙宵庚麻清鹽',
'佳皆山肴庚麻庚咸'
)),
'合': dict(zip(
'祭仙宵庚麻清鹽',
'夬刪肴庚麻庚咸'
)),
}

# TODO: 銳音移入常量後移除
銳音 = '端透定泥來知徹澄孃精清從心邪莊初崇生俟章昌常書船日以'

# 首先生成等價但更優的音韻地位

if 母 in 類隔[等]:
母 = 類隔[等][母]
合法性 = min(合法性, 合法性等級.無效)

if 母到組(母) == '幫' and 韻 in 開合分韻:
韻 = 開合分韻[韻]
合法性 = min(合法性, 合法性等級.強非法)
elif 母到組(母) != '幫' and 韻 == '凡':
韻 = '嚴'
呼 = '開'
合法性 = min(合法性, 合法性等級.強非法)

if 母 in 銳音 and 等 == '三' and 韻 in 銳音分韻:
韻 = 銳音分韻[韻]
合法性 = min(合法性, 合法性等級.強非法)

if 母到組(母) == '莊':
if 韻 in 莊三化二韻[呼] and 等 == '三':
if 韻 in '鍾宵麻清':
# 此四韻無字,視爲非法
合法性 = min(合法性, 合法性等級.強非法)
elif 韻 == '鹽':
# 鹽韻字少
合法性 = min(合法性, 合法性等級.弱合法)
韻 = 莊三化二韻[呼][韻]
等 = '二'
elif 韻 == '佳' and 呼 == '合':
韻 = '支'
等 = '三'
合法性 = min(合法性, 合法性等級.強非法)
# 真臻之分也在此處理
elif 韻 == '真' and 呼 == '開':
韻 = '臻'
合法性 = min(合法性, 合法性等級.弱非法)
# 臻韻合口已被 驗證() 攔截,無需處理
else:
if 韻 == '臻':
# 莊組以外聲母不能拼臻韻,屬於無效組合。這裡以真B韻作爲更優音韻地位
韻 = '真'
if 母 in 常量.重紐母:
重紐 = 'B'
合法性 = min(合法性, 合法性等級.無效)

# 庚三清之分
if 韻 == '清' and (重紐 == 'B' or 母 == '云'):
韻 = '庚'
重紐 = None
合法性 = min(合法性, 合法性等級.無效)
elif 韻 == '庚' and 等 == '三' and 母 in 銳音 and 母到組(母) != '莊':
韻 = '清'
合法性 = min(合法性, 合法性等級.無效)

更優音韻地位 = 音韻地位(母, 呼, 等, 重紐, 韻, 聲)

# 接下來對更優音韻地位適用音位配列規則,檢驗其合法性
for 音位配列規則 in 音位配列規則表:
# TODO: 音韻表達式增加陰聲韻、銳鈍音之後移除以下部分
音位配列規則 = list(音位配列規則)
for i in (1, 2):
if not 音位配列規則[i]:
continue
音位配列規則[i] = 音位配列規則[i].replace(
'陰聲韻', '支脂之微魚虞模齊祭泰佳皆夬灰咍廢蕭宵肴豪歌麻尤侯幽韻').replace(
'次入韻', '祭泰夬廢韻').replace(
'鈍音', '幫滂並明見溪羣疑影曉匣云母').replace(
'銳音', '端透定泥來知徹澄孃精清從心邪莊初崇生俟章昌常書船日以母')
# TODO: 音韻表達式增加陰聲韻、銳鈍音之後移除以上部分

if 更優音韻地位.屬於(音位配列規則[1]) and not (音位配列規則[2] and 更優音韻地位.屬於(音位配列規則[2])):
合法性 = min(合法性, 音位配列規則[0])
break
if 更優音韻地位 == self:
更優音韻地位 = None
return 合法性.字符串, 更優音韻地位

def __repr__(self) -> str:
return '<音韻地位 ' + self.描述 + '>'
Expand Down