swi-prologから、形態素解析のjumanを実行する

swi-prologに知識そのものを乗せることになるのだが、だとすると、それに対するアクセスのために、prologから、自然言語解析のツールを利用できた方がいいと考えた。

そこで、さしあたって、swi-prologで、jumanを利用した形態素解析をさせるプログラムを作成した。swi-prologのlibrary(process)マニュアルにあるサンプルを利用している。

jumanをサーバーモードで立ち上げる方が、効率的だが、その場合はswi-prologでクライアントを作成するという問題になる。が、ここでは直接jumanを起動する方法をとる。prologから外部コマンドを実行するのが、どのような手続きで実現するのかを確認する意味も込めている。

jumanには、pathが通っていなければ起動できない。

juman(String, Lines) :-
        setup_call_cleanup(
            process_create(path(juman), [  ],
                [ stdout(pipe(Out)), stdin(pipe(In))
                ]),
            proc_stream(In, Out, String, Lines),
            close(Out)).

proc_stream(In, Out, String, Lines) :-
        write(In,String),
        close(In),
        read_line_to_codes(Out, Line1),
        read_morpheme(Line1, Out, Lines).

read_morpheme(end_of_file, _, []) :- !.
read_morpheme(Codes, Out, [Line|Lines]) :-
        atom_codes(Line, Codes),
        read_line_to_codes(Out, Line2),
        read_morpheme(Line2, Out, Lines).

jumanは、標準入力から解析対象の文章を受け取るので、process_createのオプションにstdinを加えた。proc_streamでは、標準入力と標準出力を受け取って、まず、標準入力に文章を書き込む、それを閉じて、標準出力から結果を受け取る。read_morphemeは、end_of_fileまで一行ずつ受け取る(再帰的に繰り返す)。

実行結果は次のようになる。juman.swiが上に示したプログラムファイルである。

?- ['juman.swi'].
true.

?- juman(今日はいい天気ですね,Lines).
Lines = ['今日 きょう 今日 名詞 6 時相名詞 10 * 0 * 0 "代表表記:今日/きょう カテゴリ:時間"', '@ 今日 こんにち 今日 名詞 6 時相名詞 10 * 0 * 0 "代表表記:今日/こんにち カテゴリ:時間"', 'は は は 助詞 9 副助詞 2 * 0 * 0 NIL', 'いい いい いい 形容詞 3 * 0 イ形容詞イ段 19 基本形 2 "代表表記:良い/よい 反義:形容詞:悪い/わるい"', '天気 てんき 天気 名詞 6 普通名詞 1 * 0 * 0 "代表表記:天気/てんき カテゴリ:抽象物"', 'です です だ 判定詞 4 * 0 判定詞 25 デス列基本形 27 NIL', 'ね ね ね 助詞 9 終助詞 4 * 0 * 0 NIL', 'EOS'].

出力がリストで獲得できる。