* Creates an extended regular expression object for matching text with a pattern. Differs from a * native regular expression in that additional syntax and flags are supported. The returned object * is in fact a native `RegExp` and works with all native methods. * * @class XRegExp * @constructor
(pattern, flags)
| 139469 | * XRegExp(/regex/); |
| 139470 | */ |
| 139471 | function XRegExp(pattern, flags) { |
| 139472 | if (XRegExp.isRegExp(pattern)) { |
| 139473 | if (flags !== undefined) { |
| 139474 | throw new TypeError('Cannot supply flags when copying a RegExp'); |
| 139475 | } |
| 139476 | return copyRegex(pattern); |
| 139477 | } |
| 139478 | |
| 139479 | // Copy the argument behavior of `RegExp` |
| 139480 | pattern = pattern === undefined ? '' : String(pattern); |
| 139481 | flags = flags === undefined ? '' : String(flags); |
| 139482 | |
| 139483 | if (XRegExp.isInstalled('astral') && !(flags.indexOf('A') !== -1)) { |
| 139484 | // This causes an error to be thrown if the Unicode Base addon is not available |
| 139485 | flags += 'A'; |
| 139486 | } |
| 139487 | |
| 139488 | if (!patternCache[pattern]) { |
| 139489 | patternCache[pattern] = {}; |
| 139490 | } |
| 139491 | |
| 139492 | if (!patternCache[pattern][flags]) { |
| 139493 | var context = { |
| 139494 | hasNamedCapture: false, |
| 139495 | captureNames: [] |
| 139496 | }; |
| 139497 | var scope = defaultScope; |
| 139498 | var output = ''; |
| 139499 | var pos = 0; |
| 139500 | var result = void 0; |
| 139501 | |
| 139502 | // Check for flag-related errors, and strip/apply flags in a leading mode modifier |
| 139503 | var applied = prepareFlags(pattern, flags); |
| 139504 | var appliedPattern = applied.pattern; |
| 139505 | var appliedFlags = applied.flags; |
| 139506 | |
| 139507 | // Use XRegExp's tokens to translate the pattern to a native regex pattern. |
| 139508 | // `appliedPattern.length` may change on each iteration if tokens use `reparse` |
| 139509 | while (pos < appliedPattern.length) { |
| 139510 | do { |
| 139511 | // Check for custom tokens at the current position |
| 139512 | result = runTokens(appliedPattern, appliedFlags, pos, scope, context); |
| 139513 | // If the matched token used the `reparse` option, splice its output into the |
| 139514 | // pattern before running tokens again at the same position |
| 139515 | if (result && result.reparse) { |
| 139516 | appliedPattern = appliedPattern.slice(0, pos) + result.output + appliedPattern.slice(pos + result.matchLength); |
| 139517 | } |
| 139518 | } while (result && result.reparse); |
| 139519 | |
| 139520 | if (result) { |
| 139521 | output += result.output; |
| 139522 | pos += result.matchLength || 1; |
| 139523 | } else { |
| 139524 | // Get the native token at the current position |
| 139525 | var token = XRegExp.exec(appliedPattern, nativeTokens[scope], pos, 'sticky')[0]; |
| 139526 | output += token; |
| 139527 | pos += token.length; |
| 139528 | if (token === '[' && scope === defaultScope) { |
no test coverage detected