リポジトリ / emssr / independent_common_compiler
r2
| r2 emssr | 1 | # -*- coding: utf-8 -*- |
| r2 emssr | 2 | """採用語彙の表(`.dic`)を読む。見出しは be bo pa pi pu pe po の七音で綴り、中身はこの言語の文で書く。 |
| r2 emssr | 3 | |
| r2 emssr | 4 | pepe hu ka, he ka, no ka, he ka, no ka, he ka, no ka. |
| r2 emssr | 5 | popo pepe ka, ki hu ka, no ka. |
| r2 emssr | 6 | pupu =40 数だけの語は = で書ける(綴りは spell) |
| r2 emssr | 7 | |
| r2 emssr | 8 | 表を読むのは commonc で、この module は行を並べるだけになる(16 式 1.5: Lex ⊆ Σ* × C)。 |
| r2 emssr | 9 | `=N` の行は数を綴った文へ置き換えて渡す。`#` の行と空行は落とす。 |
| r2 emssr | 10 | |
| r2 emssr | 11 | 辞書の語は全部 I → D で、番地を机に一つ置く。値にするのは文の中の mi、 |
| r2 emssr | 12 | 書くのは 値 ka, 番地 ka, mu ka になる。Python が観測を語へ写すときの番地は |
| r2 emssr | 13 | addresses() の表から取る。 |
| r2 emssr | 14 | """ |
| r2 emssr | 15 | |
| r2 emssr | 16 | import re |
| r2 emssr | 17 | |
| r2 emssr | 18 | LETTERS = ("be", "bo", "pa", "pi", "pu", "pe", "po") |
| r2 emssr | 19 | |
| r2 emssr | 20 | |
| r2 emssr | 21 | def spell(n): |
| r2 emssr | 22 | """整数を基準の音節で綴る。二進の Horner: 上の桁から「もういちど、あわせる」で倍にし、 |
| r2 emssr | 23 | 桁が 1 なら「ひとつ、あわせる」を足す。""" |
| r2 emssr | 24 | if n < 0: |
| r2 emssr | 25 | return spell(-n) + ", ha ka" |
| r2 emssr | 26 | if n == 0: |
| r2 emssr | 27 | return "hu ka, he ka, ki ha ka, no ka" |
| r2 emssr | 28 | out = ["hu ka"] |
| r2 emssr | 29 | for bit in bin(n)[3:]: |
| r2 emssr | 30 | out.append("he ka, no ka") |
| r2 emssr | 31 | if bit == "1": |
| r2 emssr | 32 | out.append("ki hu ka, no ka") |
| r2 emssr | 33 | return ", ".join(out) |
| r2 emssr | 34 | |
| r2 emssr | 35 | |
| r2 emssr | 36 | def spelled(name): |
| r2 emssr | 37 | return len(name) % 2 == 0 and all(name[i:i + 2] in LETTERS for i in range(0, len(name), 2)) |
| r2 emssr | 38 | |
| r2 emssr | 39 | |
| r2 emssr | 40 | def entries(dic): |
| r2 emssr | 41 | """(行番号, 見出し, 文) の列。# 行と空行は飛ばす。=N は綴った文にする""" |
| r2 emssr | 42 | out = [] |
| r2 emssr | 43 | for n, line in enumerate(open(dic, encoding="utf-8"), 1): |
| r2 emssr | 44 | line = line.rstrip("\n") |
| r2 emssr | 45 | if not line.strip() or line.lstrip().startswith("#"): |
| r2 emssr | 46 | continue |
| r2 emssr | 47 | name, _, body = line.partition("\t") |
| r2 emssr | 48 | name, body = name.strip(), body.strip() |
| r2 emssr | 49 | if not spelled(name): |
| r2 emssr | 50 | raise ValueError("%s:%d: 見出し %s は be bo pa pi pu pe po で綴る" % (dic, n, name)) |
| r2 emssr | 51 | if body.startswith("="): |
| r2 emssr | 52 | body = spell(int(body[1:])) + "." |
| r2 emssr | 53 | out.append((n, name, body)) |
| r2 emssr | 54 | return out |
| r2 emssr | 55 | |
| r2 emssr | 56 | |
| r2 emssr | 57 | def lexicon(dic): |
| r2 emssr | 58 | """commonc へ渡す表の文字列。一行が 見出し ⟨tab⟩ 文 ⟨改行⟩""" |
| r2 emssr | 59 | return "".join(name + "\t" + body + "\n" for _, name, body in entries(dic)) |
| r2 emssr | 60 | |
| r2 emssr | 61 | |
| r2 emssr | 62 | def addresses(dic): |
| r2 emssr | 63 | """数だけの語(=N)の表 {見出し: N}""" |
| r2 emssr | 64 | out = {} |
| r2 emssr | 65 | for line in open(dic, encoding="utf-8"): |
| r2 emssr | 66 | line = line.rstrip("\n") |
| r2 emssr | 67 | if not line.strip() or line.lstrip().startswith("#"): |
| r2 emssr | 68 | continue |
| r2 emssr | 69 | name, _, body = line.partition("\t") |
| r2 emssr | 70 | if body.strip().startswith("="): |
| r2 emssr | 71 | out[name.strip()] = int(body.strip()[1:]) |
| r2 emssr | 72 | return out |
| r2 emssr | 73 | |
| r2 emssr | 74 | |
| r2 emssr | 75 | _TOKEN = re.compile(r"[a-z]+") |
| r2 emssr | 76 | |
| r2 emssr | 77 | |
| r2 emssr | 78 | def expanded_syllables(dic, body): |
| r2 emssr | 79 | """表を展開した後の音節の数。commonc の配列の刻み B を決めるためだけに数える""" |
| r2 emssr | 80 | size = {} |
| r2 emssr | 81 | for _, name, text in entries(dic): |
| r2 emssr | 82 | size[name] = _count(text, size) |
| r2 emssr | 83 | return _count(body, size) |
| r2 emssr | 84 | |
| r2 emssr | 85 | |
| r2 emssr | 86 | def _count(text, size): |
| r2 emssr | 87 | total = 0 |
| r2 emssr | 88 | for tok in _TOKEN.findall(text): |
| r2 emssr | 89 | if tok in size: |
| r2 emssr | 90 | total += size[tok] |
| r2 emssr | 91 | else: |
| r2 emssr | 92 | total += (len(tok) + 1) // 2 |
| r2 emssr | 93 | return total |