Open tokuhirom opened 8 months ago
サロゲートペアを含む文字を https://github.com/oguna/yet-another-migemo-dict/releases/tag/v0.4 の migemo-dict から以下のスクリプトを利用して検出してみました。
import codecs
import sys
def is_surrogate_pair(char):
"""
Checks if a character is in the surrogate-pair range.
"""
return 0x010000 <= ord(char) <= 0x10FFFF
infile = sys.argv[1]
with codecs.open(infile, 'r') as file:
for line in file:
has_surrogate_pair = False
for char in line:
if is_surrogate_pair(char):
print("U+%X" % ord(char))
line = line.replace(char, f'**{char}**')
has_surrogate_pair = True
if has_surrogate_pair:
print(line)
出力は以下のようになります。
U+20B9F
しか 仕懸 仕掛 仕替 併 兪 叱 史家 呵 四角 始華 子夏 子華 市価 市花 師家 志嘉 志賀 歯科 死花 然
知客 確 確然 私家 糸価 紙価 紙花 緊 而 聢 芝河 詆 詞花 詞華 詩家 詩歌 賜暇 蹙 顰 飾
**𠮟**
U+20B9F
しっ 七 卓 叱 執 失 嫉 尻 悉 櫛 湿 漆 濕 疾 確 緊 質 **𠮟**
U+20B9F
しつ 七 仕付 仕詰 叱 喞 執 失 嫉 室 志都 悉 桎 湿 漆 濕 為付 為詰 瑟 疾 膝
蟋 貭 質 躾 隰 隲 **𠮟**
U+27631
ふき 不帰 不羈 不覊 不記 不諱 不軌 付記 吹 富喜 富貴 布岐 腐気 苳 葺 蕗 袘 附記 **𧘱**
該当する文字は、以下の2つであり、正直なところ、これらの文字を辞書に含めないということにしても、あまり困らないかな、という気もします。
https://www.compart.com/en/unicode/U+20B9F https://www.compart.com/en/unicode/U+27631
https://github.com/oguna/yet-another-migemo-dict/pull/3 こちらで、surrogate pair を含む文字を compact 辞書から除外する処理を実装してみました。
返事が遅れて申し訳ございません。 バグ報告ありがとうございます。
サロゲートペアについては深く考えずに作っていたため、サロゲートペアを含む文字でクラッシュを起こしてしまいました。 サロゲートペアを含む文字が辞書に含まれているとは思ってなかったのですが、誤って含まれていました。
さて、いろいろ調査をしていたのですが、プログラミング言語により、正規表現でのサロゲートペアの扱いが異なるようです。
例えば、JavaScriptでは、サロゲートペアの文字を2文字として受け入れます(u
フラグがない場合)。
上位のサロゲートペアが共通の場合、まとめて、下位のサロゲートペアを[...]
で囲めば、連続していないサロゲートペアであっても、正規表現にマッチします。
const re1 = new RegExp('\u{D842}[\u{DF9F}\u{DFB7}a]')
console.log('𠮟a', re1.exec('𠮟a'))
console.log('𠮷', re1.exec('𠮷'))
出力は以下です。
𠮟a [ '𠮟', index: 0, input: '𠮟a', groups: undefined ]
𠮷 [ '𠮷', index: 0, input: '𠮷', groups: undefined ]
Rustだと、以下のコードはエラーとなります。D842
というコードポイントの文字はないからです。
let re1 = Regex::new(r"\u{D842}[\u{DF9F}\u{DFB7}a]").unwrap();
println!("{:?}", re1.find("𠮟a"));
println!("{:?}", re1.find("𠮷"));
このように、プログラミング言語により正規表現の解釈が変わりますし、加えて、このツール、特にrustmigemoは、CLIで他のツール(例えばVim)に入力することを想定しているため、入力するツールでの影響も調査しなければなりません。 そのため、省メモリ版Migemoはサロゲートペア対応をうたってはいませんでした。
で、どうしたものかといろいろ考えていたのですが、
結論としてはサロゲートペアが含まれた辞書ファイルに対応しました。
正規表現を生成するregex_generator.rs
の内部で使う文字コードをUTF32とすることで解決しました。
問題なく動作するかお手数ですがご確認ください。
修正コミット: fe2079787bd7475a471404e996a217a1a36ca4c7
https://github.com/oguna/yet-another-migemo-dict/releases/tag/v0.4 で配布されている migemo-compact-dict.zip を利用して
と実行したときに、's' や 'h' などの特定のクエリを実行したときに、panic してしまいます。
のように printf debug をしますと、以下のようになります。
よって、意図しない 55362 によってエラーになっているようです。 コードの詳細は追っていないのですが、 55362 は十六進数で 0xD842 なのでUnicodeのHigh Surrogates (U+D842) だと思います。サロゲートペアに現在の rustmigemo が対応していないにもかかわらず、yet-another-migemo-dict には surrogate pair で表現されるような文字列が含まれているために発生しているのかなと想像しています。
などの対応策が考えられるのかなと思いました。
(なお、https://github.com/oguna/migemo-compact-dict-latest の辞書では問題なく動作しております)