miau's blog?

萌ディタの Lex 周り

前回に引き続き萌ディタの話。

それじゃいっちょ Perl の定義ファイルを作ってみましょうか、ということで C の定義ファイルを元に Perl の定義ファイルを軽く作ってみて。
じゃあ今度は client-side PerlScript のために <script language="PerlScript">〜</script> な部分を Perl として認識できるようにしてみましょうか、と思ったのはいいんだけど・・・各 Lex(字句解析器)の動作がいまいちわかりにくかったり。

そんなわけで、ちょっと遠回りして NFA の状態遷移図を描くためのマクロを作ってみました。
たぶん 色分け リファレンス を読んだことない人には意味不明なので、読み飛ばしてください。




で、出来上がったマクロ。

output_lex.javascript.txt

こんな感じの .png ファイルを出力します。

html.png
※ちょっと縮小してます

もっと複雑なやつだとこんな感じ。

html-script-tag.png

これだけ複雑だと Lex の定義見たほうがわかりやすいんじゃないか?という疑問もありますが、まあ所詮補助ですので。


■使う人いるのか知らないけど説明

WinGraphviz を使っています。マクロの実行前に入れておいてください。
・マクロの実行&対象の Lex を選択すると、moe.exe と同階層 PNG 形式で出力されます。
・OLE とか嫌いな方&.png 以外で出力したい方は .dot 形式で出力(スクリプトの一部を uncomment するだけです)してGraphviz で可視化してください。


■制限事項

本当は .ps や .svg で出力する方が好きなんですけど、
・.ps で出力すると gsview でちゃんと表示できない
・.svg で出力すると余計な HTMLEncode が入ってしまう
ということで、.png で出力しています。

あと、
・状態遷移の名称を表示
・各状態の名称を表示
なんてこともやりたかったんですが、そういう情報は取得できないようですので省きました。

さらに、
・遷移時のスタイル指定や DefaultStyle を元にした色分け
なんてのもやりたかったんですけど、
・なぜか Lex.DefaultStyle の値が取得できない
・exstyle で指定されている場合、.ini ファイルの解析が必要になる
ということで、これも諦めました。


■気づいた問題点とか

状態遷移図を出力したり、Perl 用の Lex を作る上で問題になったことを書いておきます。

○問題1 *return* の条件が外側から設定できない

萌ディタの Lex はよく考えて作られていると思うんだけど、ある Lex の終了条件を外側から指定できないのが不便だなー。なんてことを考えたり。
たとえば html-script-tag から PHP への遷移は「<? php」か「<script language="php">」の2種類があるんですけど(本当はもう1種類あるけど置いといて)。PHP の終了条件は前者の場合「?>」、後者の場合「</script>」ということで、それぞれのために別の状態を重複して定義しないといけないんですよね。
このへんは php の状態遷移図(php.png。見やすいように位置調整してます)を見ればわかりやすいと思います。

確かに state:+1 とかいう形で定義してやれば、ある程度楽にはなるんですけど・・・拡張性を考えると、やっぱり遷移元から指定してやれないと不便なんですよね。
対応策で
(1) 終了条件なしの Lex を定義しておく
(2) その Lex を元に、終了条件をそれぞれ指定した Lex を作成する
みたいな感じで対応できないかなー、なんてことも考えました。
コードで書くとこんな感じ。

lex1 = lex2 = lex;
lex1.Add(
'ret-from-short-tag',
'/\\?>|%>/i',
'exstyle:PHPコードの終了; transit:*return*');
lex2.Add(
'ret-from-tag',
'/<\\/script/',
'transit:*return*');

でもその外側にも終了条件があるような場合――たとえば HTML の外側にテンプレートファイル(.tpl だとか .ihtml だとか)を定義した場合――いきなり破綻してしまう気が。
そんなわけで、このあたりは萌ディタ側で対応してくれると嬉しいなと。

○問題2 状態遷移時の情報を、後から利用できない

PHP の設定ファイルにヒアドキュメントの情報があったりするんですけど、ヒアドキュメントの定義はこんな風になってます。

// here document
lex.DefaultStyle('4,14') = 'exstyle:ヒアドキュメント';
lex.Add(
'heredoc-start',
'1,11/<<<.+$/',
'state:+3');
lex.Add(
'heredoc-end',
'4,14/^.+;/',
'no-style; state:-3');

実はヒアドキュメントの終了条件が、開始文字と一致してません。
状態遷移時の情報を後から参照するための機構がないので仕方ないわけですけど。

できれば

lex.Add(
'heredoc-start',
'1,11/<<<(([0-9a-zA-z_$]+).+$/',
'state:+3;push');

みたいに、後方参照の結果をスタックに積める仕組み&次の状態遷移で使える仕組みがあればなー、とか思ったり。
あるいは萌ディタの特徴を活かして、状態遷移時のイベントを登録できるようにするか。
# 自分で実装する気がないので好き勝手言ってます


とりあえず Perl の定義ファイルは PHP のやつを元に作ったほうがよさそうなので、こちらを元に作り直そうと思います。
技術的に対応不能な点もいくつか見えてるもので、すでに挫折の気配も見えてますけど・・・。


(2009-04-06 追記)

NFA って書いたけど、これ DFA になってる気がする。
posted at 20:45:51 on 2006-05-06 by miau - Category: TextEditor No Trackbacks - Permalink

TrackBack

このエントリにトラックバックはありません
現在トラックバックは受け付けていません。

Comments

No comments yet

Add Comments

現在コメントは受け付けていません。
お手数ですが、 こちら のコメント欄にでも記載していただければと思います。