32 hid the tail of common readings: きょう has 41 kanji, 구 has 352 hanja. 128 covers every kanji entry and the hanja dictionary now keeps that many per reading.
81 lines
2.3 KiB
Python
Executable File
81 lines
2.3 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""Write hanja.dict from a one-Hanja-per-row UTF-8 source."""
|
|
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
|
|
SOURCE = Path(__file__).with_name("hanja.src")
|
|
MAXCANDIDATES = 128
|
|
|
|
|
|
def ishangul(s):
|
|
return len(s) == 1 and 0xAC00 <= ord(s) <= 0xD7A3
|
|
|
|
|
|
def ishanja(s):
|
|
if len(s) != 1:
|
|
return False
|
|
c = ord(s)
|
|
return (0x3400 <= c <= 0x4DBF
|
|
or 0x4E00 <= c <= 0x9FFF
|
|
or 0xF900 <= c <= 0xFAFF)
|
|
|
|
|
|
def read(path):
|
|
comments = []
|
|
table = {}
|
|
seen = set()
|
|
leading = True
|
|
with path.open(encoding="utf-8") as src:
|
|
for lineno, raw in enumerate(src, 1):
|
|
line = raw.rstrip("\r\n")
|
|
if not line:
|
|
continue
|
|
if line.startswith("#"):
|
|
if leading:
|
|
comments.append(";;" + line[1:])
|
|
continue
|
|
leading = False
|
|
fields = line.split("\t")
|
|
if len(fields) != 2:
|
|
raise ValueError(f"{path}:{lineno}: need Hanja<TAB>reading")
|
|
hanja, reading = fields
|
|
if not ishanja(hanja):
|
|
raise ValueError(f"{path}:{lineno}: need one BMP Hanja character")
|
|
if not ishangul(reading):
|
|
raise ValueError(f"{path}:{lineno}: need one Hangul syllable")
|
|
pair = (hanja, reading)
|
|
if pair in seen:
|
|
raise ValueError(f"{path}:{lineno}: duplicate Hanja reading")
|
|
seen.add(pair)
|
|
table.setdefault(reading, []).append(hanja)
|
|
if not seen:
|
|
raise ValueError(f"{path}: no Hanja readings")
|
|
return comments, table
|
|
|
|
|
|
def main():
|
|
sys.stdout.reconfigure(encoding="utf-8")
|
|
sys.stderr.reconfigure(encoding="utf-8")
|
|
if len(sys.argv) > 2:
|
|
print(f"usage: {sys.argv[0]} [hanja.src]", file=sys.stderr)
|
|
return 2
|
|
path = Path(sys.argv[1]) if len(sys.argv) == 2 else SOURCE
|
|
try:
|
|
comments, table = read(path)
|
|
for line in comments:
|
|
print(line)
|
|
if comments:
|
|
print()
|
|
for reading, candidates in table.items():
|
|
print(f"{reading}\t{' '.join(candidates[:MAXCANDIDATES])}")
|
|
except (OSError, UnicodeError, ValueError) as error:
|
|
print(error, file=sys.stderr)
|
|
return 1
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|