例えば、JavaScriptのリテラル文字列では \ と改行のシークェンスは空文字を意味している。つまりこういうこと
var str = "空白を含まない\ ひとつながりの文字列です";
このシークェンスを認めるように、ダブルクォーテーション文字列の終了条件として次のようなものを shjs/lang/sh_javascript.js に含めてみたがうまくいかなかった。
[ // "string" { // \\ と \" と \(改行) を 1つのシークェンスとして // 食べてしまう。終了位置を見誤らないためであって、 // 特に何をするということもない。/\\(.|$)/gm でも構わない。 regex: /\\(?:[\\"]|$)/gm }, { // エスケープされていない " に出会ったら "~" の中に // いるという状態(state)から exitする。 // " がないまま行末に達したら、終端されていない不正な // 文字列だと判断して、やはり exitする。 exit: true, regex: /"|$/gm } ],
少し前に「行末に達した時点でマッチングを打ち切っていたのが間違い。$は空文字列にもマッチする。全てのマッチに失敗するまで続ける必要があった(20080513p01)」と自分のミスを書いて、これを修正したのだが、shjs-0.4.2はもちろん正しく、全てのマッチが失敗するまで続けている。
そうすると何が起こるか。/\\$/gm にマッチした後でも /"|$/gm のマッチに成功してしまい、結果、行末に \ があろうがなかろうが exitしてしまう。
もちろん行末に達したからといってすぐにマッチングを打ち切っては 20080513p01と同じ間違いを犯すことになるので、同一 state内で*二回以上*行末にマッチすることがないように sh_main.jsを変更した。
内の方のループの、頻繁に実行される部分に if が増えたのが気に入らないものの、悪影響のある非互換でもないし、首尾は上々だし(冒頭の文字列のハイライト結果が見本)、悪くない。
var str = "終端されていない 不正な文字列です";
var str = "終端されていない\" 不正な文字列です";
*たまたま*行末にある \" にマッチしたことで、終了条件である行末の検出がスキップされて、次の行までが文字列だと判断されている*。\" とのマッチは \$ と違い行末を要求していないから、この場合は一行目で exitしてほしい。
* 20080530p01で修正したので文章とハイライト結果が食い違っているかもしれない。