ということで、Perl 用の拡張子クラス作りましたよ。
perl.javascript.zip
色分けは、だいたいこんな感じに。
拡大表示
以下、性能限界とか注意点とか。
■概要
php.javascript.txt をベースに、SciTE の色分け設定を取り入れて作った感じです。
定義墨の変数等はいいかげんにしか登録していません。SciTE がやっているように「配列メンバへのアクセスを配列の色で表示」みたいな器用なことができるわけでなし。
ちょっと工夫した点としては、ダブルクォート中でメタ文字を使った場合、太字表示するようにしています。
これは、"C:\WINDOWS\System32" とかやった場合に \W が一文字として扱われてしまって思わぬ動作するのを防ぐためです。
■動作の概要
○"perl" Lex
perl という名前 Lex が基本になっているんですが、それ以外にも Quote and Quote-like Operators を処理するために以下の 8 つの Lex を定義しています。
perl-q : q/〜/
perl-qq : qq/〜/
perl-qx : qx/〜/
perl-qw : qw/〜/
perl-m : m/〜/
perl-qr : qr/〜/
perl-s : s/〜/
perl-tr : tr/〜/、y/〜/
他の言語では文字列の部分を Lex 内で定義している場合が多いと思いますが、
・シングルクォート文字列→perl-q に遷移
・ダブルクォート文字列→perl-qq に遷移
という感じで実装しています。
そのため、この Lex 内で定義している状態は
1 : normal
2 : DATA section
3 : Plain Old Documentation(POD)
4 : HERE document("HERE")
こんな感じでかなり少ないです。
他の Lex への遷移をある程度端折って描画するとこんな感じです。
"perl" Lex
○"perl-m" Lex
m/〜/ みたいな表現を処理するための Lex です。
デリミタ毎に状態を用意する必要があるんですが、数が足りない(これも前回のアイテム参照)ため、閉じ括弧(「<」、「(」、「[」、「{」)をデリミタとして使った場合は色分けされません。
また、開き括弧(「>」、「)」、「]」、「}」)をデリミタとして使った場合、ネストを許すようにしています。
これを実現するため、「自分と同じ Lex に対して transit」という荒業(?)を使用しているのですが・・・途中で改行が入るとうまく色分けされないこともあるようですので、ご注意ください。
状態遷移図(これもかなり端折ってる)を書くとこんな感じ。
"perl-m" Lex
perl-q、perl-qq、perl-qx、perl-qw、perl-qr もほぼ同じ動作です。
ちなみに、
$str ~= m # ○○のマッチング
{
...
}x
と書いた場合、「#」以降はコメントと解釈されるのが正しいのですが、正規表現のデリミタとして色分けされてしまいます。
半端に回避することはできるんですが、今回はとりあえず無視の方向で。
あと、正規表現内の色分け(/x オプションがついていたら # 以降をコメントの色に、とか)もできたら面白いなー、と思ったけど原理上できないので未対応です。
○"perl-s" Lex
s/PATTERN/REPLACEMENT/ を処理するための Lex です。
色分け可能なデリミタは、「 / , | # ! : = $ ( [ < { 」の 12 個ですが、スペースを 2 個ぶん余らせてありますので、これ以外のデリミタを使用する場合は追加してください。
デリミタとして開き括弧を使った場合は REPLACEMENT 用のデリミタに別のものを使えるため、他のものとは多少違う遷移をするようになっています。
"perl-s" Lex
tr/〜/〜/ もほぼ同じ動作です。
■性能限界
○/〜/ による正規表現マッチングに関して
除算の演算子である「/」と区別するのが難しいので、まだ対応していません。
・次にスラッシュが来た場合に乗算演算子とみなす状態
・次にスラッシュが来た場合に正規表現とみなす状態
の区別が必要になって、ちょっぴり面倒なのです。
○ヒアドキュメントに関して
以前も書きましたが、マッチした文字を元にして次の遷移を決めるようなことはできません。
そのため、ヒアドキュメントはとりあえず「HERE」だけを色分けするようにしています。
他のものも色分け表示したい場合は、適当に追加してください。
C:\Perl 内でどれが一番多く使われてるか調べたけど、だいたいこんな感じで・・・どうにもまとまりが無いんですよね。
(同じファイル中に複数回含まれる場合も 1 回としてカウントしています)
EOT 22
END 16
EOF 6
MAKE_FRAG 6
CODE 4
EOM 4
EOP 4
HERE 4
MAKE 3
WARNING 3
DIAGNOSTIC 2
EOC 2
EOD 2
ESQ 2
MAKE_EXT 2
WHOA 2
○POD 内の formatting-codes に関して
C<<<< hoge <=> hoge >>>>
こんな感じで括弧の個数はいくらでも増やせるのが正しい動作なんですが、そういう柔軟なマッチングは表現できないようなので、括弧 2 つまでにしか対応していません。
■拡張子クラスを作る際の注意点
○正規表現
どういう正規表現エンジン使ってるかわかりませんが、ハマった点とか。
・\d は利用不可。[0-9] で対応。
・\b(単語境界)も利用不可。
\<(単語の開始)、\>(単語の終端)で対応。
・(?:〜) (グルーピングなしの括弧)も利用不可。
・hoge{m,n} (繰り返し回数指定)とかも不可。
あと、POD 内の verbatim paragraphs(字下げしておけばソースコードのように表示される)に対して別の色分けをやりたかったんだけど、正規表現中で行頭の空白文字 ^\s がマッチしてくれない。
インデントの部分は萌ディタで別処理されているのかも。
○style ファイルに関して
「正規表現」っていう exstyle 名は使えないっぽい。「表」の 2 バイト目が「\」だからだと思うけど。
■ちょっと思ったこと
萌ディタの特徴として、「language="javascript" と書いたら JavaScript で色分けして、language="vbscript" と書いたら VBScript で色分けする」なんてことができるんですけど。
これをヒアドキュメントに適用できたら面白いなー、なんてことを考えました。
たとえば、
my $sql = <
SELECT * FROM hoge WHERE id = ?
SQL
というように、「SQL がデリミタになっていれば SQL として色分けする」とかできればなーと。
ヒアドキュメントには、「デリミタとなる文字列で、文字列の性質を表すことができる」という特長があるわけで。これを色分けに活かさない手はないですよね。
でも、遷移元で遷移後の Lex に対して「SQL で始まる行があったら戻ってきてね」という指定ができない限り、手軽にこういうことはできないわけで。
そういう風に機能拡張してくれたらなぁ。
さらに言うと、他の Lex に遷移した場合、遷移元のスタイルも引き継いでくれると見やすいなー、なんてことを考えました。
上記の例だと、
・Perl 内での HERE ドキュメントのスタイル
・SQL 内での予約語のスタイル
を混ぜ合わせたような色で表示できると、もっと見やすくなるんだけど。
そういえば、今回状態遷移図を出力したらうまくいっていない部分があったので、
output_lex.javascript.txt をこっそり更新しました。