2012-04-30 42 views
1

JavaScriptソースコードに適用すると有効な文字列リテラル("say \"Hello\""など)と正規表現リテラル(たとえば/and\/or/)が一致する包括的な正規表現が存在しますか?この式は、改行やエスケープシーケンスなど、すべてのエッジケースをカバーする必要があります。文字列または正規表現のリテラルにない正規表現と一致する正規表現

また、の文字列と正規表現リテラルの外側にあるのパターンと一致する正規表現を知っている人はいますか?

私の目標は、デリメータのマクロ(たとえば{{@foo.bar}}または#@foo.bar#)をプリプロセッサで展開できるようにする、単純なJavaScriptシンタックス拡張を実装することです。しかし、私はマクロを処理したいのですが外部ののリテラルです。

今のところ、私は既存のJavaScriptレクサー/パーサーを増やすことなく、文字列の置換だけでこれを達成しようとしています。

このJavaScriptプリプロセッサ自体は、JavaScriptで実装されます。

+0

これは正規表現にはあまりにも多いと思います。文字列、コメント、正規表現のリテラルはどこで始まり、終わるのですか? –

+0

@TimPietzcker、私はあなたのことを思っています。コメントは正解です。あなたはここで本格的なパーサーを実装することはできません。答えとしてコメントを投稿すると、私はそれを受け入れます(私はマクロの決定を終わり、特定の変数命名規則、私は純粋なJavaScript構文を使用しています。) – kpozin

答えて

0

これはregexesにはあまりにも多いと思います。

var foo = "//" // /"(?:\\.|[^"])*"/を考えてください。文字列、コメント、正規表現のリテラルはどこから始まり、終わりですか?すべてのエッジケースをカバーする完全なJavaScriptパーサーを作成する必要があります。もちろん、パーサーは正規表現を使用しています...

1

これは、引用符で囲まれた文字列にマッチさせるために使用している正規表現です。バックトラックやバックリファレンス、またはそのブードゥーを必要としないため、ほぼすべてのエンジンで動作するはずです。これは、すべてのテキストINSIDEリテラルに一致します。

"(\\.|[^"])*" 

エンジンによっては、非キャプチャグループをサポートしている可能性があります。その場合は

"(?:\\.|[^"])*" 

を使用することができます。

+1

+1のような無効な入力に対する保護の手段として、否定文字クラス '"(?:\\。| [^ \\ "])*" "にバックスラッシュを含めることは良い考えです。 "\\\" 'また、' [\ s \ S] 'はおそらくドットを置き換えるので、バックスラッシュでエスケープされた改行を含む複数行の文字列は正しく解析されます。もちろん、この解決法もコメントや正規表現のリテラル文字列の中に正規表現のリテラルとスラッシュの中で引用符をつけることができるときには難しくなります... –

+0

はい、実際に文字列の内容を理解するためにスクリプトを実際に解析する必要があります。あなたがコメントであるかどうかを判断する際に優先する他の式を持つレキシングの場合 – Dervall

+0

'/([" '\〜\ /])(\\\ 1 | [^ \ 1])* \ 1/g'は別のオプションですが、 '{{this}}'や '[this]'のように開閉のペアを機能させません。 – inhan

0

おそらく次のようなことをするつもりです。しかし、特定の可能な条件のために改善する必要があります。

var str = '"aaa \"sss \\t bbb" sss #3 ss# ((t sdsds)) ff '; 
str += '/gg sdfd \/dsds/ {aaa bbb} {{ss}} {#sdsd#}'; 

var repeating = ['"','\\\'','/','\\~','\\#']; 
// "example" 'example' /example/ ~example~ #example# 
var enclosing = []; 
enclosing.push(['\\{','\\}']); 
enclosing.push(['\\{\\{','\\}\\}']); 
enclosing.push(['\\[','\\]']); 
enclosing.push(['\\(\\(','\\)\\)']); 
// {example} {{example}} [example] ((example)) 

for (var forEnclosing='',i = 0 ; i < enclosing.length; i++) { 
    var e = enclosing[i]; 
    var r = e[0]+'(\\\\['+e[0]+e[1]+']|[^'+e[0]+e[1]+'])*'+e[1]; 
    forEnclosing += r + (i < enclosing.length-1 ? '|' : ''); 
} 
for (var forRepeating='',i = 0; i < repeating.length; i++) { 
    var e = repeating[i]; 
    var r = e+'(\\'+e+'|[^'+e+'])*'+e; 
    forRepeating += r + (i < repeating.length-1 ? '|' : ''); 
} 

var rx = new RegExp('('+forEnclosing+'|'+forRepeating+')','g'); 
var m = str.match(rx); 
try { for (var i = 0; i < m.length; i++) console.log(m[i]) } 
catch(e) {} 

出力:

"aaa "sss \t bbb" 
#3 ss# 
((t sdsds)) 
/gg sdfd /dsds/ 
{aaa bbb} 
{{ss}} 
{#sdsd#} 
0

あなたが正規表現で取得することができ、最も近いリテラル(単一または二重引用符で囲まれた)文字列や正規表現やコメント(いずれも一致するもの正規表現を持つことですOR偽の一致)ORマクロ鮫の1含まれている場合があります任意の他:グループ#1は、試合後に何が含まれている場合

"[^"\\]*(?:\\.[^"\\]*)*" 
| 
'[^'\\]*(?:\\.[^'\\]*)*' 
| 
/[^/\\]*(?:\\.[^/\\]*)*/[gim]* 
| 
/\*[^*]*(?:\*(?!/)[^*]*)*\*/ 
| 
#@(\w+\.\w+)# 

を、それはあなたが探しているものでなければなりません。それ以外の場合は、この一致を無視して次の一致に進みます。

関連する問題