前提
世は大パーサー時代なわけですが、Raccというパーサージェネレータを触っているときに内部で使うことの多いツールであるStringScannerについて改めて調べたので共有します。
StringScannerとは
StringScannerクラスは文字通り文字列をスキャンする機能を提供するクラスです。動作としては正規表現を利用したスキャンと現在位置の管理を同時に行うため、利用者はスキャンのロジックに集中できます。
重要なこととして、StringScannerはRubyの標準ライブラリの一部であり、
require 'strscan'
するだけで使うことができます。
主なメソッドとしてはscan
メソッドがありますが、他にも多くのメソッドを持つ非常に多機能なライブラリです。詳細はドキュメントを読むのが良いでしょう。
実装について
StringScannerは主にC言語で実装されています。これはライブラリの高速な動作(主な目的です)のために重要である反面、内部を読み解くのはかなり困難です。ここでRubyのみでの実装があればよいとは思いませんか?
…という理由とは一切無関係に、かつて私がRubyでStringScannerを再実装したコードがあります。
わずか200行程度のコードでほぼ全てのテストを通せています。Rubyすごい!
…速度は3分の1以下になってしまいましたが…
というのはまあさておき、このRubyコードを読むと内部的にポインタと文字列を管理している様子がわかりやすいのではないでしょうか。
使いどころについて
文字列をスキャンしたいときというのは、
- 文字列にある種の構造があり、
- かつそこから何らかの情報を得たいとき
になるかと思います。これは明らかにパーサーが該当しますが、例えばCSVのようなある種の構造化されたデータについても適用自体は可能でしょう(Rubyには優れたCSVライブラリが存在するのでそちらを使えばいいのですが)。
まとめ
ということでStringScannerクラスの紹介でした。実はこのライブラリ、GitHubから遡れる最古のコミットが20世紀であるという、Rubyの世界における古参ライブラリでもあります。
この記事がパーサーを触っているRubyistのお役に立てたら嬉しいです。