UNPKG

regexplus

Version:

RegExp Plus

103 lines (97 loc) 2.77 kB
var RE_PLUS = /\((\?<=|\?<!|\?<\w+>|.)/g; var RE_NAMED = /\(\?<(\w+)>/g; // 命名分组。 var RE_REV_PRE = /\(\?<=/g; // 反向预搜索。 var RE_REV_PRE_NOT = /\(\?<!/g; // 反向预搜索不匹配。 function RegExplus(source, flags) { if (!flags) { flags = ''; } this.source = source; this._plus = [null]; this._reverse_pre_search = []; this._reverse_pre_search_not_match = []; var _source = source.replace(RE_PLUS, function($0, flag, subreg) { if (flag === '?:') { // unmatched group. return $0; } else if (flag === '?=') { // 正向预搜索。 return $0; } else if (flag === '?=') { // 正向预搜索不匹配。 return $0; } else if (flag === '?<=') { // 反向预搜索。 this._plus.push({ type: 'reverse-match', regexp: new RegExp(subreg, flags), }); } else if (flag === '?<!') { // 反向预搜索不匹配。 this._plus.push({ type: 'reverse-mismatch', regexp: new RegExp(subreg, flags), }); } else if (flag.startsWith('?<') && flag.endsWith('>')) { // 命名分组。 this._plus.push({ type: 'named-group', name: flag.substring(2, flag.length - 1), }); } else {// 普通分组。 this._plus.push({ type: 'group', }); return $0; } return '('; }.bind(this)); this._regexp = new RegExp(_source, flags); this.lastIndex = 0; this.global = flags.indexOf('g') >= 0; this.multiline = flags.indexOf('m') >= 0; this.ignoreCase = flags.indexOf('i') >= 0; } RegExplus.prototype = { exec: function(string) { var matched = this._regexp.exec(string); if (!matched) { return null; } // named group. for (var i=1, l=matched.length; i<l; i++) { switch(this._plus[i].type){ case 'group': break; case 'named-group': matched[ this._plus[i].name ] = matched[i]; break; case 'reverse-match': if (this._plus[i].regexp.test(matched[i])) { matched.splice(i, 1); } else { return null; } break; case 'reverse-mismatch': if (!this._plus[i].regexp.test(matched[i])) { matched.splice(i, 1); } else { return null; } break; default: // TODO: 反向预搜索 throw new Error("Unknow type."); } } return matched; }, test: function(string) { return this.exec(string) !== null; }, valueOf: function() { return this._regexp; }, toString: function() { return '/' + this.source + '/' + (this.ignoreCase ? 'i' : '') + (this.multiline ? 'm' : '') + (this.global ? 'g' : ''); }, }; module.exports = RegExplus;