2017-05-24 4 views
1

私はいくつかの軽い正規表現を使って特定のトークンを検出する構文解析ステートマシンを構築しています。私は大きな文字列の任意の位置を見て、正規表現がその位置から厳密に一致するかどうかを判断できるようにしたい。私は解析している文字列は任意に大きくなる可能性がありますと私は潜在的に文字列のスライスを取って、非グローバル正規表現^と一致すると非常に非効率的です(私は思う? numberRe.exec(longString.slice(numberRe.lastIndex))が持っているであろうように、a/g Javascript正規表現の残りの部分をマッチさせることは可能ですか?

var longString = 'abc123defghi45jk...'; 
var numberRe = /\d+/g; 

numberRe.lastIndex = 3; 
var match = numberRe.exec(longString); 

console.log(match); 

numberRe.lastIndexが正規表現に一致する部分文字列の上にあるときにのみ正規表現マッチを持っている:私はこのような何か行うことができているのが好きでした何

同じ結果。

これは可能ですか?

+0

あなたの表現が単純な場合は、すべての正規表現を使用しないほうが良いと独自のトークナイザを書き込むことができます。 – plalx

+0

これは最小限の例です – ayoon

+0

再帰的な降下トークナイザは実際には非常に書きやすいです。 – plalx

答えて

1

sticky (y) flagはまさにその、最近JavaScriptの標準(それはもともとMozillaの拡張だった)にそれを作ったん:あなたはサポートせずにエンジンをターゲットに設定している場合、あなたはのindexプロパティを使用することができます

> var digit = /\d/y; 
> digit.exec('12x3') 
[ '1', index: 0, input: '12x3' ] 
> digit.exec('12x3') 
[ '2', index: 1, input: '12x3' ] 
> digit.exec('12x3') 
null 

(スライスを繰り返しおそらく現代のエンジンの上に文字列のおかげで遅くなることはありません

function stickyMatch(regex, string) { 
    var expectedIndex = regex.lastIndex; 
    var match = regex.exec(string); 

    if (!match || match.index !== expectedIndex) { 
     regex.lastIndex = 0; 
     return null; 
    } 

    return match; 
} 

var digit = /\d/g; 

console.log(stickyMatch(digit, '12x3')); 
console.log(stickyMatch(digit, '12x3')); 
console.log(stickyMatch(digit, '12x3')); 

:正規表現のlastIndexの以前の値と必ずそれ行を一致して作りますoptimizations¹が、これはとにかくよりよいです。)

¹*波の手精力的に*

+0

ブリリアント。従来のテクニックは、正規表現が否定的な結論に達する前に、潜在的に長い文字列と疎な文字列を前向きに検索するため、非効率的です。ありがたいことに私は古いプラットフォームについて心配していません。 – ayoon

関連する問題