日記 (2017 年 3 月 31 日)

ZpDIC では ver 1.7.0 から akrantiain が実行できますが、 実装はオリジナルのものとは異なります。 ということで、 特に変換規則の適用について、 どういう実装になっているかを簡単に解説しておこうと思います。 オリジナルの実装の解説は、 こちらを参照してください。 以下は、 ver 1.7.1 より少し後 (コミット c058cc8) の実装の解説です。 ver 1.7.1 は左右条件のチェックを手抜きしているので、 以下の説明とは少し違います。

まず、 入力を 1 文字ずつ分割して Stat (1 文字と null の対のリスト, AkrantiainElementGroup クラスで管理) に変換します。 Stat を構成する各 Stat 素 (1 文字と null の対, AkrantiainElement クラスで管理) には、 順にインデックスを振っておきます。 以下、 「インデックス」 と言ったら、 Stat 素のインデックスを指し、 入力文字列のインデックスではないことに注意してください (Stat 素の fst が 2 文字以上になることがあるので両者は一般に一致しない)。 この Stat に対して変換規則を順に適用していく点は、 オリジナルの実装と同じです。

変換規則は、 マッチ可能オブジェクト (AkrantiainMatchable インターフェースで管理) のリストと Phoneme のリストの集まりとして考えます。 !vowel "a" ("k"|"g") -> /A/ $ という規則なら、 !vowel, "a", ("k"|"g") がマッチ可能オブジェクトです。 マッチ可能オブジェクトは、 Stat とマッチ開始位置インデックスを受け取り、 その位置から右方向にマッチするかどうかを調べ、 マッチしたならばマッチ範囲の右端のインデックスを返し、 マッチしないなら null を返すメソッド (matchRight メソッド) をもちます。 また、 受け取った開始位置インデックスから左方向にマッチするかどうかを調べるメソッド (matchLeft メソッド) ももちます。

変換規則の適用には、 以下の処理をするメソッド (applyOnce メソッド) を用います。 このメソッドは、 Stat と調査開始位置インデックスを受け取り、 そのインデックスから規則がマッチするか調べ、 マッチしたならさらに変換も施し、 マッチ範囲の右端のインデックスとマッチ範囲のみを変換してできた Stat 素のリストを返します。 マッチしないなら null を返します。 applyOnce メソッドの処理は以下のように行われます。

まず、 調査中インデックス (I とおく) を受け取った調査開始インデックスに設定し、 変換結果の Stat 素を格納しておくために空のリスト (L とおく) を用意します。 規則が左条件をもつならば、 matchLeft メソッドを用いて、 I の位置から左方向に左条件がマッチするかを調べ、 マッチすれば次に進みます。 規則の Select (左条件でも右条件でもないもの) たちの最初の Select を取り出し、 matchRight メソッドを用いて、 I の位置から右方向にマッチするかを調べ、 マッチしたら返り値であるマッチ範囲の右端インデックスを I に新たに設定します。 さらに、 マッチ箇所を 1 つの Stat 素にまとめたものを用意して、 その snd に変換先の Phoneme の値を設定し、 L に追加します。 この処理を Select たちに対して順番に行います。 全ての Select がマッチしたならば、 最後に右条件のチェックを行います。 規則が右条件をもつならば、 matchRight メソッドを用いて、 I の位置から右方向に右条件がマッチするかを調べ、 マッチしたら次に進みます。 ここまでマッチに失敗することなく辿り着いたならば、 マッチ範囲の右端インデックスとして I を返し、 変換してできた Stat 素のリストとして L を返します。 途中でマッチに失敗したならば null を返します。

変換規則の適用は、 この applyOnce メソッドを用いて以下のように行われます。

まず、 調査開始インデックス (J とおく) を 0 に設定し、 変換結果の Stat を格納しておくための空の Stat (S とおく) を用意します。 Stat と JapplyOnce メソッドに渡します。 その結果が null ならば、 その位置でのマッチ失敗なので、 Stat の J 番目の Stat 素をそのまま S に追加し、 J の値を 1 増やします。 結果が null でなければ、 返り値の変換後 Stat 素リストの要素を全て S に追加し、 マッチ範囲の右端インデックスを J に新たに設定します。 この処理を、 J がもとの Stat のサイズに達するまで繰り返します。 繰り返しが終わったら、 S がその規則の適用結果となります。

以上の処理を、 全ての変換規則に対して順番に行います。 最後に得られた Stat の snd を全て繋げれば、 出力の完成です。