会社でKyoto.pmのハッカソンあったからハッカソンとは無関係に出社してPerl書いてた.
Perlのソースコードをパースした上でトークンを置換するのを作った.実行するとif
とunless
が入れ替わる.
こういうのやるとき,IDEを使うか,IDEがなかったらsedとかで雑に書き換えてしまう(たとえば,Gitリポジトリ内の特定の語を全て置換する #git #sed - Qiita)けど,正規表現でソースコードを操作するのはよくない.間違うと動かなくなるので,目視で確認する必要がある.
たとえば,単純にs/if/unless/g
とかすると,文字列中のifもunlessになってしまう.
逆に,パースしてから置換すると,コメント中のifはunlessにならないので,クラス名をパースした上で置換する場合に,コメント中のだけ古いクラス名が残る,ということになる.
それが困るようなら,コメントのトークンだけ取り出して,その中だけ正規表現で置換するとよいと思う.
PerlのIDEで,Padre, the Perl IDEっていうのがあるけど,素朴な感じで,変数名の置換くらいしかできなかった.すぐにクラッシュするし,おまけみたいな感じだった.
PPI::Transformっていうクラスでソースコードをパースした上で操作できるようになってたので,それを使った.
find('PPI::Token')
としてるけど,PPI::Token::Quote
とかやると特定のクラスのトークンだけ取れる.
説明
PPI::Transform
を継承してdocument
メソッドをオーバーライドする- 引数に
document
が渡ってくるので,トークンを操作して,書き換えた数を返す- 実装見ると真ならなんでもいいけどドキュメントにはReturns the numbers of changes made to the documentって書いてあった
- コンストラクタに渡したパラメータはblessされてるので勝手に使ってよい
参考
- PPI::Transform - search.cpan.org
- PPI::Transform
- PPI::Transform::UpdateCopyright - search.cpan.org
- PPI::Transformを使った例