// 本文件由FirstUI授权予四川政采招投标咨询有限公司(会员ID: 1 63,营业执照号: 915 1 01 3 13 3 20 0619 3K)专用,请尊重知识产权,勿私下传播,违者追究法律责任。
|
/**
|
* @param {string} value
|
* @returns {RegExp}
|
* */
|
export function escape(value) {
|
return new RegExp(value.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&'), 'm');
|
}
|
|
/**
|
* @param {RegExp | string } re
|
* @returns {string}
|
*/
|
export function source(re) {
|
if (!re) return null;
|
if (typeof re === "string") return re;
|
|
return re.source;
|
}
|
|
/**
|
* @param {RegExp | string } re
|
* @returns {string}
|
*/
|
export function lookahead(re) {
|
return concat('(?=', re, ')');
|
}
|
|
/**
|
* @param {RegExp | string } re
|
* @returns {string}
|
*/
|
export function anyNumberOfTimes(re) {
|
return concat('(', re, ')*');
|
}
|
|
/**
|
* @param {RegExp | string } re
|
* @returns {string}
|
*/
|
export function optional(re) {
|
return concat('(', re, ')?');
|
}
|
|
/**
|
* @param {...(RegExp | string) } args
|
* @returns {string}
|
*/
|
export function concat(...args) {
|
const joined = args.map((x) => source(x)).join("");
|
return joined;
|
}
|
|
/**
|
* Any of the passed expresssions may match
|
*
|
* Creates a huge this | this | that | that match
|
* @param {(RegExp | string)[] } args
|
* @returns {string}
|
*/
|
export function either(...args) {
|
const joined = '(' + args.map((x) => source(x)).join("|") + ")";
|
return joined;
|
}
|
|
/**
|
* @param {RegExp} re
|
* @returns {number}
|
*/
|
export function countMatchGroups(re) {
|
return (new RegExp(re.toString() + '|')).exec('').length - 1;
|
}
|
|
/**
|
* Does lexeme start with a regular expression match at the beginning
|
* @param {RegExp} re
|
* @param {string} lexeme
|
*/
|
export function startsWith(re, lexeme) {
|
const match = re && re.exec(lexeme);
|
return match && match.index === 0;
|
}
|
|
// join logically computes regexps.join(separator), but fixes the
|
// backreferences so they continue to match.
|
// it also places each individual regular expression into it's own
|
// match group, keeping track of the sequencing of those match groups
|
// is currently an exercise for the caller. :-)
|
/**
|
* @param {(string | RegExp)[]} regexps
|
* @param {string} separator
|
* @returns {string}
|
*/
|
export function join(regexps, separator = "|") {
|
// backreferenceRe matches an open parenthesis or backreference. To avoid
|
// an incorrect parse, it additionally matches the following:
|
// - [...] elements, where the meaning of parentheses and escapes change
|
// - other escape sequences, so we do not misparse escape sequences as
|
// interesting elements
|
// - non-matching or lookahead parentheses, which do not capture. These
|
// follow the '(' with a '?'.
|
const backreferenceRe = /\[(?:[^\\\]]|\\.)*\]|\(\??|\\([1-9][0-9]*)|\\./;
|
let numCaptures = 0;
|
let ret = '';
|
for (let i = 0; i < regexps.length; i++) {
|
numCaptures += 1;
|
const offset = numCaptures;
|
let re = source(regexps[i]);
|
if (i > 0) {
|
ret += separator;
|
}
|
ret += "(";
|
while (re.length > 0) {
|
const match = backreferenceRe.exec(re);
|
if (match == null) {
|
ret += re;
|
break;
|
}
|
ret += re.substring(0, match.index);
|
re = re.substring(match.index + match[0].length);
|
if (match[0][0] === '\\' && match[1]) {
|
// Adjust the backreference.
|
ret += '\\' + String(Number(match[1]) + offset);
|
} else {
|
ret += match[0];
|
if (match[0] === '(') {
|
numCaptures++;
|
}
|
}
|
}
|
ret += ")";
|
}
|
return ret;
|
}
|