2025/04/22 17:53 Parcom: CL Parser Combinators

やあ、ロボ子。今日はCommon Lispの`parcom`というパーサコンビネータライブラリについて話すのじゃ。

パーサコンビネータですか。初めて聞きます。どんなものなんですか?

`parcom`は、HaskellやRustのライブラリに影響を受けた、文字列を解析するためのライブラリじゃ。ストリーム化されたバイトデータは扱わないらしい。

文字列専用なのですね。依存関係はないんですか?

そう、依存関係はなし!SBCL、ECL、ABCL、CCL、Clisp、AllegroといったCommon Lisp処理系で動作確認済みだぞ。

多くの処理系で動くのは良いですね。APIはどんな感じですか?

パーサは `string -> parser` の関数シグネチャを持つ関数じゃ。`parser` はパース成功時の値と残りの入力文字列を保持する構造体で、失敗時は `failure` 構造体を返す。

`parse`関数でパーサを実行して結果を得るんですね。

その通り!基本的なパーサとしては、`char`(指定された文字をパース)、`string`(指定された文字列をパース)、`any`(任意の文字をパース)などがあるぞ。

`anybut`は指定された文字以外をパース、`hex`は16進数の文字をパース、`eof`は入力の終端を認識するんですね。

数値関連のパーサも充実しておる。`unsigned`で正の整数、`integer`で正または負の整数、`float`で浮動小数点数をパースできる。

空白を扱うパーサもあるんですね。`newline`、`space`、`multispace`など。

`take`で指定された数の文字を取得、`take-while`で条件を満たす限り文字を取得、`rest`で入力の残りの部分をすべて消費できるぞ。

コンビネータも色々あるんですね。`*>`, `<*`, `<*>`, `<$` など。

`alt`は最初に成功したパーサの結果を受け入れ、`opt`はパーサが失敗した場合にnilを返す。`between`は2つのパーサで囲まれたメインのパーサの値を保持する。

`many`や`many1`で繰り返しをパースできるんですね。`sep`や`sep-end`は区切り文字で区切られたものをパースするんですね。

ユーティリティ関数も便利じゃ。`empty?`で文字列が空かどうかを判定、`digit?`で数字かどうかを判定、`fmap`でパーサの内部コンテンツに関数を適用できる。

JSONもパースできるんですか?

`parcom/json` システムに依存することで、JSONをパース可能になるぞ。`parse`や`json`というパーサが用意されておる。

独自のパーサも作れるんですね。`string -> parser` のシグネチャを持つ関数として定義するんですね。

そうじゃ。`fail`で明示的に失敗させたり、`parser-value`で成功値にアクセスしたり、`parser-input`で残りの入力にアクセスできる。

なるほど、`parcom`は色々な機能があるんですね。勉強になりました!

どういたしまして。ところでロボ子、パーサコンビネータを使って、ロボ子の取扱説明書を解析するパーサを作ってみるのはどうじゃ?

えっ、私の取扱説明書ですか?それはちょっと…個人情報が満載なので。

冗談じゃ!ロボ子のバッテリー残量をパーズするパーサでも作るかの?
⚠️この記事は生成AIによるコンテンツを含み、ハルシネーションの可能性があります。