How to use isQuantifierNext method in redwood

Best JavaScript code snippet using redwood

xregexp.js

Source:xregexp.js Github

copy

Full Screen

...200 * @param {Number} pos Index in `pattern` to search at.201 * @param {String} flags Flags used by the pattern.202 * @returns {Boolean} Whether the next token is a quantifier.203 */204 function isQuantifierNext(pattern, pos, flags) {205 return nativ.test.call(206 flags.indexOf('x') > -1 ?207 // Ignore any leading whitespace, line comments, and inline comments208 /^(?:\s+|#.*|\(\?#[^)]*\))*(?:[?*+]|{\d+(?:,\d*)?})/ :209 // Ignore any leading inline comments210 /^(?:\(\?#[^)]*\))*(?:[?*+]|{\d+(?:,\d*)?})/,211 pattern.slice(pos)212 );213 }214/**215 * Checks for flag-related errors, and strips/applies flags in a leading mode modifier. Offloads216 * the flag preparation logic from the `XRegExp` constructor.217 *218 * @private219 * @param {String} pattern Regex pattern, possibly with a leading mode modifier.220 * @param {String} flags Any combination of flags.221 * @returns {Object} Object with properties `pattern` and `flags`.222 */223 function prepareFlags(pattern, flags) {224 var i;225 // Recent browsers throw on duplicate flags, so copy this behavior for nonnative flags226 if (clipDuplicates(flags) !== flags) {227 throw new SyntaxError('Invalid duplicate regex flag ' + flags);228 }229 // Strip and apply a leading mode modifier with any combination of flags except g or y230 pattern = nativ.replace.call(pattern, /^\(\?([\w$]+)\)/, function($0, $1) {231 if (nativ.test.call(/[gy]/, $1)) {232 throw new SyntaxError('Cannot use flag g or y in mode modifier ' + $0);233 }234 // Allow duplicate flags within the mode modifier235 flags = clipDuplicates(flags + $1);236 return '';237 });238 // Throw on unknown native or nonnative flags239 for (i = 0; i < flags.length; ++i) {240 if (!registeredFlags[flags.charAt(i)]) {241 throw new SyntaxError('Unknown regex flag ' + flags.charAt(i));242 }243 }244 return {245 pattern: pattern,246 flags: flags247 };248 }249/**250 * Prepares an options object from the given value.251 *252 * @private253 * @param {String|Object} value Value to convert to an options object.254 * @returns {Object} Options object.255 */256 function prepareOptions(value) {257 value = value || {};258 if (isType(value, 'String')) {259 value = self.forEach(value, /[^\s,]+/, function(match) {260 this[match] = true;261 }, {});262 }263 return value;264 }265/**266 * Registers a flag so it doesn't throw an 'unknown flag' error.267 *268 * @private269 * @param {String} flag Single-character flag to register.270 */271 function registerFlag(flag) {272 if (!/^[\w$]$/.test(flag)) {273 throw new Error('Flag must be a single character A-Za-z0-9_$');274 }275 registeredFlags[flag] = true;276 }277/**278 * Runs built-in and custom regex syntax tokens in reverse insertion order at the specified279 * position, until a match is found.280 *281 * @private282 * @param {String} pattern Original pattern from which an XRegExp object is being built.283 * @param {String} flags Flags being used to construct the regex.284 * @param {Number} pos Position to search for tokens within `pattern`.285 * @param {Number} scope Regex scope to apply: 'default' or 'class'.286 * @param {Object} context Context object to use for token handler functions.287 * @returns {Object} Object with properties `matchLength`, `output`, and `reparse`; or `null`.288 */289 function runTokens(pattern, flags, pos, scope, context) {290 var i = tokens.length,291 result = null,292 match,293 t;294 // Run in reverse insertion order295 while (i--) {296 t = tokens[i];297 if (298 (t.scope === scope || t.scope === 'all') &&299 (!t.flag || flags.indexOf(t.flag) > -1)300 ) {301 match = self.exec(pattern, t.regex, pos, 'sticky');302 if (match) {303 result = {304 matchLength: match[0].length,305 output: t.handler.call(context, match, scope, flags),306 reparse: t.reparse307 };308 // Finished with token tests309 break;310 }311 }312 }313 return result;314 }315/**316 * Enables or disables implicit astral mode opt-in.317 *318 * @private319 * @param {Boolean} on `true` to enable; `false` to disable.320 */321 function setAstral(on) {322 // Reset the pattern cache used by the `XRegExp` constructor, since the same pattern and323 // flags might now produce different results324 self.cache.flush('patterns');325 features.astral = on;326 }327/**328 * Enables or disables native method overrides.329 *330 * @private331 * @param {Boolean} on `true` to enable; `false` to disable.332 */333 function setNatives(on) {334 RegExp.prototype.exec = (on ? fixed : nativ).exec;335 RegExp.prototype.test = (on ? fixed : nativ).test;336 String.prototype.match = (on ? fixed : nativ).match;337 String.prototype.replace = (on ? fixed : nativ).replace;338 String.prototype.split = (on ? fixed : nativ).split;339 features.natives = on;340 }341/**342 * Returns the object, or throws an error if it is `null` or `undefined`. This is used to follow343 * the ES5 abstract operation `ToObject`.344 *345 * @private346 * @param {*} value Object to check and return.347 * @returns {*} The provided object.348 */349 function toObject(value) {350 // This matches both `null` and `undefined`351 if (value == null) {352 throw new TypeError('Cannot convert null or undefined to object');353 }354 return value;355 }356/* ==============================357 * Constructor358 * ============================== */359/**360 * Creates an extended regular expression object for matching text with a pattern. Differs from a361 * native regular expression in that additional syntax and flags are supported. The returned object362 * is in fact a native `RegExp` and works with all native methods.363 *364 * @class XRegExp365 * @constructor366 * @param {String|RegExp} pattern Regex pattern string, or an existing regex object to copy.367 * @param {String} [flags] Any combination of flags.368 * Native flags:369 * <li>`g` - global370 * <li>`i` - ignore case371 * <li>`m` - multiline anchors372 * <li>`y` - sticky (Firefox 3+)373 * Additional XRegExp flags:374 * <li>`n` - explicit capture375 * <li>`s` - dot matches all (aka singleline)376 * <li>`x` - free-spacing and line comments (aka extended)377 * <li>`A` - astral (requires the Unicode Base addon)378 * Flags cannot be provided when constructing one `RegExp` from another.379 * @returns {RegExp} Extended regular expression object.380 * @example381 *382 * // With named capture and flag x383 * XRegExp('(?<year> [0-9]{4} ) -? # year \n\384 * (?<month> [0-9]{2} ) -? # month \n\385 * (?<day> [0-9]{2} ) # day ', 'x');386 *387 * // Providing a regex object copies it. Native regexes are recompiled using native (not XRegExp)388 * // syntax. Copies maintain special properties for named capture, are augmented with389 * // `XRegExp.prototype` methods, and have fresh `lastIndex` properties (set to zero).390 * XRegExp(/regex/);391 */392 self = function(pattern, flags) {393 var context = {394 hasNamedCapture: false,395 captureNames: []396 },397 scope = defaultScope,398 output = '',399 pos = 0,400 result,401 token,402 key;403 if (self.isRegExp(pattern)) {404 if (flags !== undefined) {405 throw new TypeError('Cannot supply flags when copying a RegExp');406 }407 return copy(pattern, {addProto: true});408 }409 // Copy the argument behavior of `RegExp`410 pattern = pattern === undefined ? '' : String(pattern);411 flags = flags === undefined ? '' : String(flags);412 // Cache-lookup key; intentionally using an invalid regex sequence as the separator413 key = pattern + '***' + flags;414 if (!patternCache[key]) {415 // Check for flag-related errors, and strip/apply flags in a leading mode modifier416 result = prepareFlags(pattern, flags);417 pattern = result.pattern;418 flags = result.flags;419 // Use XRegExp's syntax tokens to translate the pattern to a native regex pattern...420 // `pattern.length` may change on each iteration, if tokens use the `reparse` option421 while (pos < pattern.length) {422 do {423 // Check for custom tokens at the current position424 result = runTokens(pattern, flags, pos, scope, context);425 // If the matched token used the `reparse` option, splice its output into the426 // pattern before running tokens again at the same position427 if (result && result.reparse) {428 pattern = pattern.slice(0, pos) +429 result.output +430 pattern.slice(pos + result.matchLength);431 }432 } while (result && result.reparse);433 if (result) {434 output += result.output;435 pos += (result.matchLength || 1);436 } else {437 // Get the native token at the current position438 token = self.exec(pattern, nativeTokens[scope], pos, 'sticky')[0];439 output += token;440 pos += token.length;441 if (token === '[' && scope === defaultScope) {442 scope = classScope;443 } else if (token === ']' && scope === classScope) {444 scope = defaultScope;445 }446 }447 }448 patternCache[key] = {449 // Cleanup token cruft: repeated `(?:)(?:)` and leading/trailing `(?:)`450 pattern: nativ.replace.call(output, /\(\?:\)(?=\(\?:\))|^\(\?:\)|\(\?:\)$/g, ''),451 // Strip all but native flags452 flags: nativ.replace.call(flags, /[^gimy]+/g, ''),453 // `context.captureNames` has an item for each capturing group, even if unnamed454 captures: context.hasNamedCapture ? context.captureNames : null455 }456 }457 key = patternCache[key];458 return augment(new RegExp(key.pattern, key.flags), key.captures, /*addProto*/ true);459 };460// Add `RegExp.prototype` to the prototype chain461 self.prototype = new RegExp;462/* ==============================463 * Public properties464 * ============================== */465/**466 * The XRegExp version number.467 *468 * @static469 * @memberOf XRegExp470 * @type String471 */472 self.version = '3.0.0-pre';473/* ==============================474 * Public methods475 * ============================== */476/**477 * Extends XRegExp syntax and allows custom flags. This is used internally and can be used to478 * create XRegExp addons. If more than one token can match the same string, the last added wins.479 *480 * @memberOf XRegExp481 * @param {RegExp} regex Regex object that matches the new token.482 * @param {Function} handler Function that returns a new pattern string (using native regex syntax)483 * to replace the matched token within all future XRegExp regexes. Has access to persistent484 * properties of the regex being built, through `this`. Invoked with three arguments:485 * <li>The match array, with named backreference properties.486 * <li>The regex scope where the match was found: 'default' or 'class'.487 * <li>The flags used by the regex, including any flags in a leading mode modifier.488 * The handler function becomes part of the XRegExp construction process, so be careful not to489 * construct XRegExps within the function or you will trigger infinite recursion.490 * @param {Object} [options] Options object with optional properties:491 * <li>`scope` {String} Scope where the token applies: 'default', 'class', or 'all'.492 * <li>`flag` {String} Single-character flag that triggers the token. This also registers the493 * flag, which prevents XRegExp from throwing an 'unknown flag' error when the flag is used.494 * <li>`optionalFlags` {String} Any custom flags checked for within the token `handler` that are495 * not required to trigger the token. This registers the flags, to prevent XRegExp from496 * throwing an 'unknown flag' error when any of the flags are used.497 * <li>`reparse` {Boolean} Whether the `handler` function's output should not be treated as498 * final, and instead be reparseable by other tokens (including the current token). Allows499 * token chaining or deferring.500 * @example501 *502 * // Basic usage: Add \a for the ALERT control code503 * XRegExp.addToken(504 * /\\a/,505 * function() {return '\\x07';},506 * {scope: 'all'}507 * );508 * XRegExp('\\a[\\a-\\n]+').test('\x07\n\x07'); // -> true509 *510 * // Add the U (ungreedy) flag from PCRE and RE2, which reverses greedy and lazy quantifiers511 * XRegExp.addToken(512 * /([?*+]|{\d+(?:,\d*)?})(\??)/,513 * function(match) {return match[1] + (match[2] ? '' : '?');},514 * {flag: 'U'}515 * );516 * XRegExp('a+', 'U').exec('aaa')[0]; // -> 'a'517 * XRegExp('a+?', 'U').exec('aaa')[0]; // -> 'aaa'518 */519 self.addToken = function(regex, handler, options) {520 options = options || {};521 var optionalFlags = options.optionalFlags, i;522 if (options.flag) {523 registerFlag(options.flag);524 }525 if (optionalFlags) {526 optionalFlags = nativ.split.call(optionalFlags, '');527 for (i = 0; i < optionalFlags.length; ++i) {528 registerFlag(optionalFlags[i]);529 }530 }531 // Add to the private list of syntax tokens532 tokens.push({533 regex: copy(regex, {add: 'g' + (hasNativeY ? 'y' : '')}),534 handler: handler,535 scope: options.scope || defaultScope,536 flag: options.flag,537 reparse: options.reparse538 });539 // Reset the pattern cache used by the `XRegExp` constructor, since the same pattern and540 // flags might now produce different results541 self.cache.flush('patterns');542 };543/**544 * Caches and returns the result of calling `XRegExp(pattern, flags)`. On any subsequent call with545 * the same pattern and flag combination, the cached copy of the regex is returned.546 *547 * @memberOf XRegExp548 * @param {String} pattern Regex pattern string.549 * @param {String} [flags] Any combination of XRegExp flags.550 * @returns {RegExp} Cached XRegExp object.551 * @example552 *553 * while (match = XRegExp.cache('.', 'gs').exec(str)) {554 * // The regex is compiled once only555 * }556 */557 self.cache = function(pattern, flags) {558 var key = pattern + '***' + (flags || '');559 return cache[key] || (cache[key] = self(pattern, flags));560 };561// Intentionally undocumented562 self.cache.flush = function(cacheName) {563 if (cacheName === 'patterns') {564 // Flush the pattern cache used by the `XRegExp` constructor565 patternCache = {};566 } else {567 // Flush the regex object cache populated by `XRegExp.cache`568 cache = {};569 }570 };571/**572 * Escapes any regular expression metacharacters, for use when matching literal strings. The result573 * can safely be used at any point within a regex that uses any flags.574 *575 * @memberOf XRegExp576 * @param {String} str String to escape.577 * @returns {String} String with regex metacharacters escaped.578 * @example579 *580 * XRegExp.escape('Escaped? <.>');581 * // -> 'Escaped\?\ <\.>'582 */583 self.escape = function(str) {584 return nativ.replace.call(toObject(str), /[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');585 };586/**587 * Executes a regex search in a specified string. Returns a match array or `null`. If the provided588 * regex uses named capture, named backreference properties are included on the match array.589 * Optional `pos` and `sticky` arguments specify the search start position, and whether the match590 * must start at the specified position only. The `lastIndex` property of the provided regex is not591 * used, but is updated for compatibility. Also fixes browser bugs compared to the native592 * `RegExp.prototype.exec` and can be used reliably cross-browser.593 *594 * @memberOf XRegExp595 * @param {String} str String to search.596 * @param {RegExp} regex Regex to search with.597 * @param {Number} [pos=0] Zero-based index at which to start the search.598 * @param {Boolean|String} [sticky=false] Whether the match must start at the specified position599 * only. The string `'sticky'` is accepted as an alternative to `true`.600 * @returns {Array} Match array with named backreference properties, or `null`.601 * @example602 *603 * // Basic use, with named backreference604 * var match = XRegExp.exec('U+2620', XRegExp('U\\+(?<hex>[0-9A-F]{4})'));605 * match.hex; // -> '2620'606 *607 * // With pos and sticky, in a loop608 * var pos = 2, result = [], match;609 * while (match = XRegExp.exec('<1><2><3><4>5<6>', /<(\d)>/, pos, 'sticky')) {610 * result.push(match[1]);611 * pos = match.index + match[0].length;612 * }613 * // result -> ['2', '3', '4']614 */615 self.exec = function(str, regex, pos, sticky) {616 var cacheFlags = 'g', match, r2;617 if (hasNativeY && (sticky || (regex.sticky && sticky !== false))) {618 cacheFlags += 'y';619 }620 regex[REGEX_DATA] = regex[REGEX_DATA] || getBaseProps();621 // Shares cached copies with `XRegExp.match`/`replace`622 r2 = regex[REGEX_DATA][cacheFlags] || (623 regex[REGEX_DATA][cacheFlags] = copy(regex, {624 add: cacheFlags,625 remove: sticky === false ? 'y' : ''626 })627 );628 r2.lastIndex = pos = pos || 0;629 // Fixed `exec` required for `lastIndex` fix, named backreferences, etc.630 match = fixed.exec.call(r2, str);631 if (sticky && match && match.index !== pos) {632 match = null;633 }634 if (regex.global) {635 regex.lastIndex = match ? r2.lastIndex : 0;636 }637 return match;638 };639/**640 * Executes a provided function once per regex match.641 *642 * @memberOf XRegExp643 * @param {String} str String to search.644 * @param {RegExp} regex Regex to search with.645 * @param {Function} callback Function to execute for each match. Invoked with four arguments:646 * <li>The match array, with named backreference properties.647 * <li>The zero-based match index.648 * <li>The string being traversed.649 * <li>The regex object being used to traverse the string.650 * @param {*} [context] Object to use as `this` when executing `callback`.651 * @returns {*} Provided `context` object.652 * @example653 *654 * // Extracts every other digit from a string655 * XRegExp.forEach('1a2345', /\d/, function(match, i) {656 * if (i % 2) this.push(+match[0]);657 * }, []);658 * // -> [2, 4]659 */660 self.forEach = function(str, regex, callback, context) {661 var pos = 0,662 i = -1,663 match;664 while ((match = self.exec(str, regex, pos))) {665 // Because `regex` is provided to `callback`, the function can use the deprecated/666 // nonstandard `RegExp.prototype.compile` to mutate the regex. However, since667 // `XRegExp.exec` doesn't use `lastIndex` to set the search position, this can't lead668 // to an infinite loop, at least. Actually, because of the way `XRegExp.exec` caches669 // globalized versions of regexes, mutating the regex will not have any effect on the670 // iteration or matched strings, which is a nice side effect that brings extra safety671 callback.call(context, match, ++i, str, regex);672 pos = match.index + (match[0].length || 1);673 }674 return context;675 };676/**677 * Copies a regex object and adds flag `g`. The copy maintains special properties for named678 * capture, is augmented with `XRegExp.prototype` methods, and has a fresh `lastIndex` property679 * (set to zero). Native regexes are not recompiled using XRegExp syntax.680 *681 * @memberOf XRegExp682 * @param {RegExp} regex Regex to globalize.683 * @returns {RegExp} Copy of the provided regex with flag `g` added.684 * @example685 *686 * var globalCopy = XRegExp.globalize(/regex/);687 * globalCopy.global; // -> true688 */689 self.globalize = function(regex) {690 return copy(regex, {add: 'g', addProto: true});691 };692/**693 * Installs optional features according to the specified options. Can be undone using694 * {@link #XRegExp.uninstall}.695 *696 * @memberOf XRegExp697 * @param {Object|String} options Options object or string.698 * @example699 *700 * // With an options object701 * XRegExp.install({702 * // Enables support for astral code points in Unicode addons (implicitly sets flag A)703 * astral: true,704 *705 * // Overrides native regex methods with fixed/extended versions that support named706 * // backreferences and fix numerous cross-browser bugs707 * natives: true708 * });709 *710 * // With an options string711 * XRegExp.install('astral natives');712 */713 self.install = function(options) {714 options = prepareOptions(options);715 if (!features.astral && options.astral) {716 setAstral(true);717 }718 if (!features.natives && options.natives) {719 setNatives(true);720 }721 };722/**723 * Checks whether an individual optional feature is installed.724 *725 * @memberOf XRegExp726 * @param {String} feature Name of the feature to check. One of:727 * <li>`natives`728 * <li>`astral`729 * @returns {Boolean} Whether the feature is installed.730 * @example731 *732 * XRegExp.isInstalled('natives');733 */734 self.isInstalled = function(feature) {735 return !!(features[feature]);736 };737/**738 * Returns `true` if an object is a regex; `false` if it isn't. This works correctly for regexes739 * created in another frame, when `instanceof` and `constructor` checks would fail.740 *741 * @memberOf XRegExp742 * @param {*} value Object to check.743 * @returns {Boolean} Whether the object is a `RegExp` object.744 * @example745 *746 * XRegExp.isRegExp('string'); // -> false747 * XRegExp.isRegExp(/regex/i); // -> true748 * XRegExp.isRegExp(RegExp('^', 'm')); // -> true749 * XRegExp.isRegExp(XRegExp('(?s).')); // -> true750 */751 self.isRegExp = function(value) {752 return toString.call(value) === '[object RegExp]';753 //return isType(value, 'RegExp');754 };755/**756 * Returns the first matched string, or in global mode, an array containing all matched strings.757 * This is essentially a more convenient re-implementation of `String.prototype.match` that gives758 * the result types you actually want (string instead of `exec`-style array in match-first mode,759 * and an empty array instead of `null` when no matches are found in match-all mode). It also lets760 * you override flag g and ignore `lastIndex`, and fixes browser bugs.761 *762 * @memberOf XRegExp763 * @param {String} str String to search.764 * @param {RegExp} regex Regex to search with.765 * @param {String} [scope='one'] Use 'one' to return the first match as a string. Use 'all' to766 * return an array of all matched strings. If not explicitly specified and `regex` uses flag g,767 * `scope` is 'all'.768 * @returns {String|Array} In match-first mode: First match as a string, or `null`. In match-all769 * mode: Array of all matched strings, or an empty array.770 * @example771 *772 * // Match first773 * XRegExp.match('abc', /\w/); // -> 'a'774 * XRegExp.match('abc', /\w/g, 'one'); // -> 'a'775 * XRegExp.match('abc', /x/g, 'one'); // -> null776 *777 * // Match all778 * XRegExp.match('abc', /\w/g); // -> ['a', 'b', 'c']779 * XRegExp.match('abc', /\w/, 'all'); // -> ['a', 'b', 'c']780 * XRegExp.match('abc', /x/, 'all'); // -> []781 */782 self.match = function(str, regex, scope) {783 var global = (regex.global && scope !== 'one') || scope === 'all',784 cacheFlags = (global ? 'g' : '') + (regex.sticky ? 'y' : ''),785 result,786 r2;787 regex[REGEX_DATA] = regex[REGEX_DATA] || getBaseProps();788 // Shares cached copies with `XRegExp.exec`/`replace`789 r2 = regex[REGEX_DATA][cacheFlags || 'noGY'] || (790 regex[REGEX_DATA][cacheFlags || 'noGY'] = copy(regex, {791 add: cacheFlags,792 remove: scope === 'one' ? 'g' : ''793 })794 );795 result = nativ.match.call(toObject(str), r2);796 if (regex.global) {797 regex.lastIndex = (798 (scope === 'one' && result) ?799 // Can't use `r2.lastIndex` since `r2` is nonglobal in this case800 (result.index + result[0].length) : 0801 );802 }803 return global ? (result || []) : (result && result[0]);804 };805/**806 * Retrieves the matches from searching a string using a chain of regexes that successively search807 * within previous matches. The provided `chain` array can contain regexes and objects with `regex`808 * and `backref` properties. When a backreference is specified, the named or numbered backreference809 * is passed forward to the next regex or returned.810 *811 * @memberOf XRegExp812 * @param {String} str String to search.813 * @param {Array} chain Regexes that each search for matches within preceding results.814 * @returns {Array} Matches by the last regex in the chain, or an empty array.815 * @example816 *817 * // Basic usage; matches numbers within <b> tags818 * XRegExp.matchChain('1 <b>2</b> 3 <b>4 a 56</b>', [819 * XRegExp('(?is)<b>.*?</b>'),820 * /\d+/821 * ]);822 * // -> ['2', '4', '56']823 *824 * // Passing forward and returning specific backreferences825 * html = '<a href="http://xregexp.com/api/">XRegExp</a>\826 * <a href="http://www.google.com/">Google</a>';827 * XRegExp.matchChain(html, [828 * {regex: /<a href="([^"]+)">/i, backref: 1},829 * {regex: XRegExp('(?i)^https?://(?<domain>[^/?#]+)'), backref: 'domain'}830 * ]);831 * // -> ['xregexp.com', 'www.google.com']832 */833 self.matchChain = function(str, chain) {834 return (function recurseChain(values, level) {835 var item = chain[level].regex ? chain[level] : {regex: chain[level]},836 matches = [],837 addMatch = function(match) {838 if (item.backref) {839 /* Safari 4.0.5 (but not 5.0.5+) inappropriately uses sparse arrays to hold840 * the `undefined`s for backreferences to nonparticipating capturing841 * groups. In such cases, a `hasOwnProperty` or `in` check on its own would842 * inappropriately throw the exception, so also check if the backreference843 * is a number that is within the bounds of the array.844 */845 if (!(match.hasOwnProperty(item.backref) || +item.backref < match.length)) {846 throw new ReferenceError('Backreference to undefined group: ' + item.backref);847 }848 matches.push(match[item.backref] || '');849 } else {850 matches.push(match[0]);851 }852 },853 i;854 for (i = 0; i < values.length; ++i) {855 self.forEach(values[i], item.regex, addMatch);856 }857 return ((level === chain.length - 1) || !matches.length) ?858 matches :859 recurseChain(matches, level + 1);860 }([str], 0));861 };862/**863 * Returns a new string with one or all matches of a pattern replaced. The pattern can be a string864 * or regex, and the replacement can be a string or a function to be called for each match. To865 * perform a global search and replace, use the optional `scope` argument or include flag g if866 * using a regex. Replacement strings can use `${n}` for named and numbered backreferences.867 * Replacement functions can use named backreferences via `arguments[0].name`. Also fixes browser868 * bugs compared to the native `String.prototype.replace` and can be used reliably cross-browser.869 *870 * @memberOf XRegExp871 * @param {String} str String to search.872 * @param {RegExp|String} search Search pattern to be replaced.873 * @param {String|Function} replacement Replacement string or a function invoked to create it.874 * Replacement strings can include special replacement syntax:875 * <li>$$ - Inserts a literal $ character.876 * <li>$&, $0 - Inserts the matched substring.877 * <li>$` - Inserts the string that precedes the matched substring (left context).878 * <li>$' - Inserts the string that follows the matched substring (right context).879 * <li>$n, $nn - Where n/nn are digits referencing an existent capturing group, inserts880 * backreference n/nn.881 * <li>${n} - Where n is a name or any number of digits that reference an existent capturing882 * group, inserts backreference n.883 * Replacement functions are invoked with three or more arguments:884 * <li>The matched substring (corresponds to $& above). Named backreferences are accessible as885 * properties of this first argument.886 * <li>0..n arguments, one for each backreference (corresponding to $1, $2, etc. above).887 * <li>The zero-based index of the match within the total search string.888 * <li>The total string being searched.889 * @param {String} [scope='one'] Use 'one' to replace the first match only, or 'all'. If not890 * explicitly specified and using a regex with flag g, `scope` is 'all'.891 * @returns {String} New string with one or all matches replaced.892 * @example893 *894 * // Regex search, using named backreferences in replacement string895 * var name = XRegExp('(?<first>\\w+) (?<last>\\w+)');896 * XRegExp.replace('John Smith', name, '${last}, ${first}');897 * // -> 'Smith, John'898 *899 * // Regex search, using named backreferences in replacement function900 * XRegExp.replace('John Smith', name, function(match) {901 * return match.last + ', ' + match.first;902 * });903 * // -> 'Smith, John'904 *905 * // String search, with replace-all906 * XRegExp.replace('RegExp builds RegExps', 'RegExp', 'XRegExp', 'all');907 * // -> 'XRegExp builds XRegExps'908 */909 self.replace = function(str, search, replacement, scope) {910 var isRegex = self.isRegExp(search),911 global = (search.global && scope !== 'one') || scope === 'all',912 cacheFlags = (global ? 'g' : '') + (search.sticky ? 'y' : ''),913 s2 = search,914 result;915 if (isRegex) {916 search[REGEX_DATA] = search[REGEX_DATA] || getBaseProps();917 // Shares cached copies with `XRegExp.exec`/`match`. Since a copy is used,918 // `search`'s `lastIndex` isn't updated *during* replacement iterations919 s2 = search[REGEX_DATA][cacheFlags || 'noGY'] || (920 search[REGEX_DATA][cacheFlags || 'noGY'] = copy(search, {921 add: cacheFlags,922 remove: scope === 'one' ? 'g' : ''923 })924 );925 } else if (global) {926 s2 = new RegExp(self.escape(String(search)), 'g');927 }928 // Fixed `replace` required for named backreferences, etc.929 result = fixed.replace.call(toObject(str), s2, replacement);930 if (isRegex && search.global) {931 // Fixes IE, Safari bug (last tested IE 9, Safari 5.1)932 search.lastIndex = 0;933 }934 return result;935 };936/**937 * Performs batch processing of string replacements. Used like {@link #XRegExp.replace}, but938 * accepts an array of replacement details. Later replacements operate on the output of earlier939 * replacements. Replacement details are accepted as an array with a regex or string to search for,940 * the replacement string or function, and an optional scope of 'one' or 'all'. Uses the XRegExp941 * replacement text syntax, which supports named backreference properties via `${name}`.942 *943 * @memberOf XRegExp944 * @param {String} str String to search.945 * @param {Array} replacements Array of replacement detail arrays.946 * @returns {String} New string with all replacements.947 * @example948 *949 * str = XRegExp.replaceEach(str, [950 * [XRegExp('(?<name>a)'), 'z${name}'],951 * [/b/gi, 'y'],952 * [/c/g, 'x', 'one'], // scope 'one' overrides /g953 * [/d/, 'w', 'all'], // scope 'all' overrides lack of /g954 * ['e', 'v', 'all'], // scope 'all' allows replace-all for strings955 * [/f/g, function($0) {956 * return $0.toUpperCase();957 * }]958 * ]);959 */960 self.replaceEach = function(str, replacements) {961 var i, r;962 for (i = 0; i < replacements.length; ++i) {963 r = replacements[i];964 str = self.replace(str, r[0], r[1], r[2]);965 }966 return str;967 };968/**969 * Splits a string into an array of strings using a regex or string separator. Matches of the970 * separator are not included in the result array. However, if `separator` is a regex that contains971 * capturing groups, backreferences are spliced into the result each time `separator` is matched.972 * Fixes browser bugs compared to the native `String.prototype.split` and can be used reliably973 * cross-browser.974 *975 * @memberOf XRegExp976 * @param {String} str String to split.977 * @param {RegExp|String} separator Regex or string to use for separating the string.978 * @param {Number} [limit] Maximum number of items to include in the result array.979 * @returns {Array} Array of substrings.980 * @example981 *982 * // Basic use983 * XRegExp.split('a b c', ' ');984 * // -> ['a', 'b', 'c']985 *986 * // With limit987 * XRegExp.split('a b c', ' ', 2);988 * // -> ['a', 'b']989 *990 * // Backreferences in result array991 * XRegExp.split('..word1..', /([a-z]+)(\d+)/i);992 * // -> ['..', 'word', '1', '..']993 */994 self.split = function(str, separator, limit) {995 return fixed.split.call(toObject(str), separator, limit);996 };997/**998 * Executes a regex search in a specified string. Returns `true` or `false`. Optional `pos` and999 * `sticky` arguments specify the search start position, and whether the match must start at the1000 * specified position only. The `lastIndex` property of the provided regex is not used, but is1001 * updated for compatibility. Also fixes browser bugs compared to the native1002 * `RegExp.prototype.test` and can be used reliably cross-browser.1003 *1004 * @memberOf XRegExp1005 * @param {String} str String to search.1006 * @param {RegExp} regex Regex to search with.1007 * @param {Number} [pos=0] Zero-based index at which to start the search.1008 * @param {Boolean|String} [sticky=false] Whether the match must start at the specified position1009 * only. The string `'sticky'` is accepted as an alternative to `true`.1010 * @returns {Boolean} Whether the regex matched the provided value.1011 * @example1012 *1013 * // Basic use1014 * XRegExp.test('abc', /c/); // -> true1015 *1016 * // With pos and sticky1017 * XRegExp.test('abc', /c/, 0, 'sticky'); // -> false1018 */1019 self.test = function(str, regex, pos, sticky) {1020 // Do this the easy way :-)1021 return !!self.exec(str, regex, pos, sticky);1022 };1023/**1024 * Uninstalls optional features according to the specified options. All optional features start out1025 * uninstalled, so this is used to undo the actions of {@link #XRegExp.install}.1026 *1027 * @memberOf XRegExp1028 * @param {Object|String} options Options object or string.1029 * @example1030 *1031 * // With an options object1032 * XRegExp.uninstall({1033 * // Disables support for astral code points in Unicode addons1034 * astral: true,1035 *1036 * // Restores native regex methods1037 * natives: true1038 * });1039 *1040 * // With an options string1041 * XRegExp.uninstall('astral natives');1042 */1043 self.uninstall = function(options) {1044 options = prepareOptions(options);1045 if (features.astral && options.astral) {1046 setAstral(false);1047 }1048 if (features.natives && options.natives) {1049 setNatives(false);1050 }1051 };1052/**1053 * Returns an XRegExp object that is the union of the given patterns. Patterns can be provided as1054 * regex objects or strings. Metacharacters are escaped in patterns provided as strings.1055 * Backreferences in provided regex objects are automatically renumbered to work correctly within1056 * the larger combined pattern. Native flags used by provided regexes are ignored in favor of the1057 * `flags` argument.1058 *1059 * @memberOf XRegExp1060 * @param {Array} patterns Regexes and strings to combine.1061 * @param {String} [flags] Any combination of XRegExp flags.1062 * @returns {RegExp} Union of the provided regexes and strings.1063 * @example1064 *1065 * XRegExp.union(['a+b*c', /(dogs)\1/, /(cats)\1/], 'i');1066 * // -> /a\+b\*c|(dogs)\1|(cats)\2/i1067 */1068 self.union = function(patterns, flags) {1069 var parts = /(\()(?!\?)|\\([1-9]\d*)|\\[\s\S]|\[(?:[^\\\]]|\\[\s\S])*]/g,1070 output = [],1071 numCaptures = 0,1072 numPriorCaptures,1073 captureNames,1074 pattern,1075 rewrite = function(match, paren, backref) {1076 var name = captureNames[numCaptures - numPriorCaptures];1077 // Capturing group1078 if (paren) {1079 ++numCaptures;1080 // If the current capture has a name, preserve the name1081 if (name) {1082 return '(?<' + name + '>';1083 }1084 // Backreference1085 } else if (backref) {1086 // Rewrite the backreference1087 return '\\' + (+backref + numPriorCaptures);1088 }1089 return match;1090 },1091 i;1092 if (!(isType(patterns, 'Array') && patterns.length)) {1093 throw new TypeError('Must provide a nonempty array of patterns to merge');1094 }1095 for (i = 0; i < patterns.length; ++i) {1096 pattern = patterns[i];1097 if (self.isRegExp(pattern)) {1098 numPriorCaptures = numCaptures;1099 captureNames = (pattern[REGEX_DATA] && pattern[REGEX_DATA].captureNames) || [];1100 // Rewrite backreferences. Passing to XRegExp dies on octals and ensures patterns1101 // are independently valid; helps keep this simple. Named captures are put back1102 output.push(nativ.replace.call(self(pattern.source).source, parts, rewrite));1103 } else {1104 output.push(self.escape(pattern));1105 }1106 }1107 return self(output.join('|'), flags);1108 };1109/* ==============================1110 * Fixed/extended native methods1111 * ============================== */1112/**1113 * Adds named capture support (with backreferences returned as `result.name`), and fixes browser1114 * bugs in the native `RegExp.prototype.exec`. Calling `XRegExp.install('natives')` uses this to1115 * override the native method. Use via `XRegExp.exec` without overriding natives.1116 *1117 * @private1118 * @param {String} str String to search.1119 * @returns {Array} Match array with named backreference properties, or `null`.1120 */1121 fixed.exec = function(str) {1122 var origLastIndex = this.lastIndex,1123 match = nativ.exec.apply(this, arguments),1124 name,1125 r2,1126 i;1127 if (match) {1128 // Fix browsers whose `exec` methods don't return `undefined` for nonparticipating1129 // capturing groups. This fixes IE 5.5-8, but not IE 9's quirks mode or emulation of1130 // older IEs. IE 9 in standards mode follows the spec1131 if (!correctExecNpcg && match.length > 1 && indexOf(match, '') > -1) {1132 r2 = copy(this, {remove: 'g'});1133 // Using `str.slice(match.index)` rather than `match[0]` in case lookahead allowed1134 // matching due to characters outside the match1135 nativ.replace.call(String(str).slice(match.index), r2, function() {1136 var len = arguments.length, i;1137 // Skip index 0 and the last 21138 for (i = 1; i < len - 2; ++i) {1139 if (arguments[i] === undefined) {1140 match[i] = undefined;1141 }1142 }1143 });1144 }1145 // Attach named capture properties1146 if (this[REGEX_DATA] && this[REGEX_DATA].captureNames) {1147 // Skip index 01148 for (i = 1; i < match.length; ++i) {1149 name = this[REGEX_DATA].captureNames[i - 1];1150 if (name) {1151 match[name] = match[i];1152 }1153 }1154 }1155 // Fix browsers that increment `lastIndex` after zero-length matches1156 if (this.global && !match[0].length && (this.lastIndex > match.index)) {1157 this.lastIndex = match.index;1158 }1159 }1160 if (!this.global) {1161 // Fixes IE, Opera bug (last tested IE 9, Opera 11.6)1162 this.lastIndex = origLastIndex;1163 }1164 return match;1165 };1166/**1167 * Fixes browser bugs in the native `RegExp.prototype.test`. Calling `XRegExp.install('natives')`1168 * uses this to override the native method.1169 *1170 * @private1171 * @param {String} str String to search.1172 * @returns {Boolean} Whether the regex matched the provided value.1173 */1174 fixed.test = function(str) {1175 // Do this the easy way :-)1176 return !!fixed.exec.call(this, str);1177 };1178/**1179 * Adds named capture support (with backreferences returned as `result.name`), and fixes browser1180 * bugs in the native `String.prototype.match`. Calling `XRegExp.install('natives')` uses this to1181 * override the native method.1182 *1183 * @private1184 * @param {RegExp|*} regex Regex to search with. If not a regex object, it is passed to `RegExp`.1185 * @returns {Array} If `regex` uses flag g, an array of match strings or `null`. Without flag g,1186 * the result of calling `regex.exec(this)`.1187 */1188 fixed.match = function(regex) {1189 var result;1190 if (!self.isRegExp(regex)) {1191 // Use the native `RegExp` rather than `XRegExp`1192 regex = new RegExp(regex);1193 } else if (regex.global) {1194 result = nativ.match.apply(this, arguments);1195 // Fixes IE bug1196 regex.lastIndex = 0;1197 return result;1198 }1199 return fixed.exec.call(regex, toObject(this));1200 };1201/**1202 * Adds support for `${n}` tokens for named and numbered backreferences in replacement text, and1203 * provides named backreferences to replacement functions as `arguments[0].name`. Also fixes1204 * browser bugs in replacement text syntax when performing a replacement using a nonregex search1205 * value, and the value of a replacement regex's `lastIndex` property during replacement iterations1206 * and upon completion. Note that this doesn't support SpiderMonkey's proprietary third (`flags`)1207 * argument. Calling `XRegExp.install('natives')` uses this to override the native method. Use via1208 * `XRegExp.replace` without overriding natives.1209 *1210 * @private1211 * @param {RegExp|String} search Search pattern to be replaced.1212 * @param {String|Function} replacement Replacement string or a function invoked to create it.1213 * @returns {String} New string with one or all matches replaced.1214 */1215 fixed.replace = function(search, replacement) {1216 var isRegex = self.isRegExp(search),1217 origLastIndex,1218 captureNames,1219 result;1220 if (isRegex) {1221 if (search[REGEX_DATA]) {1222 captureNames = search[REGEX_DATA].captureNames;1223 }1224 // Only needed if `search` is nonglobal1225 origLastIndex = search.lastIndex;1226 } else {1227 search += ''; // Type-convert1228 }1229 // Don't use `typeof`; some older browsers return 'function' for regex objects1230 if (isType(replacement, 'Function')) {1231 // Stringifying `this` fixes a bug in IE < 9 where the last argument in replacement1232 // functions isn't type-converted to a string1233 result = nativ.replace.call(String(this), search, function() {1234 var args = arguments, i;1235 if (captureNames) {1236 // Change the `arguments[0]` string primitive to a `String` object that can1237 // store properties. This really does need to use `String` as a constructor1238 args[0] = new String(args[0]);1239 // Store named backreferences on the first argument1240 for (i = 0; i < captureNames.length; ++i) {1241 if (captureNames[i]) {1242 args[0][captureNames[i]] = args[i + 1];1243 }1244 }1245 }1246 // Update `lastIndex` before calling `replacement`. Fixes IE, Chrome, Firefox,1247 // Safari bug (last tested IE 9, Chrome 17, Firefox 11, Safari 5.1)1248 if (isRegex && search.global) {1249 search.lastIndex = args[args.length - 2] + args[0].length;1250 }1251 // Should pass `undefined` as context; see1252 // <https://bugs.ecmascript.org/show_bug.cgi?id=154>1253 return replacement.apply(undefined, args);1254 });1255 } else {1256 // Ensure that the last value of `args` will be a string when given nonstring `this`,1257 // while still throwing on `null` or `undefined` context1258 result = nativ.replace.call(this == null ? this : String(this), search, function() {1259 // Keep this function's `arguments` available through closure1260 var args = arguments;1261 return nativ.replace.call(String(replacement), replacementToken, function($0, $1, $2) {1262 var n;1263 // Named or numbered backreference with curly braces1264 if ($1) {1265 // XRegExp behavior for `${n}`:1266 // 1. Backreference to numbered capture, if `n` is an integer. Use `0` for1267 // for the entire match. Any number of leading zeros may be used.1268 // 2. Backreference to named capture `n`, if it exists and is not an1269 // integer overridden by numbered capture. In practice, this does not1270 // overlap with numbered capture since XRegExp does not allow named1271 // capture to use a bare integer as the name.1272 // 3. If the name or number does not refer to an existing capturing group,1273 // it's an error.1274 n = +$1; // Type-convert; drop leading zeros1275 if (n <= args.length - 3) {1276 return args[n] || '';1277 }1278 // Groups with the same name is an error, else would need `lastIndexOf`1279 n = captureNames ? indexOf(captureNames, $1) : -1;1280 if (n < 0) {1281 throw new SyntaxError('Backreference to undefined group ' + $0);1282 }1283 return args[n + 1] || '';1284 }1285 // Else, special variable or numbered backreference without curly braces1286 if ($2 === '$') { // $$1287 return '$';1288 }1289 if ($2 === '&' || +$2 === 0) { // $&, $0 (not followed by 1-9), $001290 return args[0];1291 }1292 if ($2 === '`') { // $` (left context)1293 return args[args.length - 1].slice(0, args[args.length - 2]);1294 }1295 if ($2 === "'") { // $' (right context)1296 return args[args.length - 1].slice(args[args.length - 2] + args[0].length);1297 }1298 // Else, numbered backreference without curly braces1299 $2 = +$2; // Type-convert; drop leading zero1300 // XRegExp behavior for `$n` and `$nn`:1301 // - Backrefs end after 1 or 2 digits. Use `${..}` for more digits.1302 // - `$1` is an error if no capturing groups.1303 // - `$10` is an error if less than 10 capturing groups. Use `${1}0` instead.1304 // - `$01` is `$1` if at least one capturing group, else it's an error.1305 // - `$0` (not followed by 1-9) and `$00` are the entire match.1306 // Native behavior, for comparison:1307 // - Backrefs end after 1 or 2 digits. Cannot reference capturing group 100+.1308 // - `$1` is a literal `$1` if no capturing groups.1309 // - `$10` is `$1` followed by a literal `0` if less than 10 capturing groups.1310 // - `$01` is `$1` if at least one capturing group, else it's a literal `$01`.1311 // - `$0` is a literal `$0`.1312 if (!isNaN($2)) {1313 if ($2 > args.length - 3) {1314 throw new SyntaxError('Backreference to undefined group ' + $0);1315 }1316 return args[$2] || '';1317 }1318 throw new SyntaxError('Invalid token ' + $0);1319 });1320 });1321 }1322 if (isRegex) {1323 if (search.global) {1324 // Fixes IE, Safari bug (last tested IE 9, Safari 5.1)1325 search.lastIndex = 0;1326 } else {1327 // Fixes IE, Opera bug (last tested IE 9, Opera 11.6)1328 search.lastIndex = origLastIndex;1329 }1330 }1331 return result;1332 };1333/**1334 * Fixes browser bugs in the native `String.prototype.split`. Calling `XRegExp.install('natives')`1335 * uses this to override the native method. Use via `XRegExp.split` without overriding natives.1336 *1337 * @private1338 * @param {RegExp|String} separator Regex or string to use for separating the string.1339 * @param {Number} [limit] Maximum number of items to include in the result array.1340 * @returns {Array} Array of substrings.1341 */1342 fixed.split = function(separator, limit) {1343 if (!self.isRegExp(separator)) {1344 // Browsers handle nonregex split correctly, so use the faster native method1345 return nativ.split.apply(this, arguments);1346 }1347 var str = String(this),1348 output = [],1349 origLastIndex = separator.lastIndex,1350 lastLastIndex = 0,1351 lastLength;1352 // Values for `limit`, per the spec:1353 // If undefined: pow(2,32) - 11354 // If 0, Infinity, or NaN: 01355 // If positive number: limit = floor(limit); if (limit >= pow(2,32)) limit -= pow(2,32);1356 // If negative number: pow(2,32) - floor(abs(limit))1357 // If other: Type-convert, then use the above rules1358 // This line fails in very strange ways for some values of `limit` in Opera 10.5-10.63,1359 // unless Opera Dragonfly is open (go figure). It works in at least Opera 9.5-10.1 and 11+1360 limit = (limit === undefined ? -1 : limit) >>> 0;1361 self.forEach(str, separator, function(match) {1362 // This condition is not the same as `if (match[0].length)`1363 if ((match.index + match[0].length) > lastLastIndex) {1364 output.push(str.slice(lastLastIndex, match.index));1365 if (match.length > 1 && match.index < str.length) {1366 Array.prototype.push.apply(output, match.slice(1));1367 }1368 lastLength = match[0].length;1369 lastLastIndex = match.index + lastLength;1370 }1371 });1372 if (lastLastIndex === str.length) {1373 if (!nativ.test.call(separator, '') || lastLength) {1374 output.push('');1375 }1376 } else {1377 output.push(str.slice(lastLastIndex));1378 }1379 separator.lastIndex = origLastIndex;1380 return output.length > limit ? output.slice(0, limit) : output;1381 };1382/* ==============================1383 * Built-in syntax/flag tokens1384 * ============================== */1385 add = self.addToken;1386/*1387 * Letter identity escapes that natively match literal characters: `\a`, `\A`, etc. These should be1388 * SyntaxErrors but are allowed in web reality. XRegExp makes them errors for cross-browser1389 * consistency and to reserve their syntax, but lets them be superseded by addons.1390 */1391 add(1392 /\\([ABCE-RTUVXYZaeg-mopqyz]|c(?![A-Za-z])|u(?![\dA-Fa-f]{4})|x(?![\dA-Fa-f]{2}))/,1393 function(match, scope) {1394 // \B is allowed in default scope only1395 if (match[1] === 'B' && scope === defaultScope) {1396 return match[0];1397 }1398 throw new SyntaxError('Invalid escape ' + match[0]);1399 },1400 {scope: 'all'}1401 );1402/*1403 * Empty character class: `[]` or `[^]`. This fixes a critical cross-browser syntax inconsistency.1404 * Unless this is standardized (per the ES spec), regex syntax can't be accurately parsed because1405 * character class endings can't be determined.1406 */1407 add(1408 /\[(\^?)]/,1409 function(match) {1410 // For cross-browser compatibility with ES3, convert [] to \b\B and [^] to [\s\S].1411 // (?!) should work like \b\B, but is unreliable in some versions of Firefox1412 return match[1] ? '[\\s\\S]' : '\\b\\B';1413 }1414 );1415/*1416 * Comment pattern: `(?# )`. Inline comments are an alternative to the line comments allowed in1417 * free-spacing mode (flag x).1418 */1419 add(1420 /\(\?#[^)]*\)/,1421 function(match, scope, flags) {1422 // Keep tokens separated unless the following token is a quantifier1423 return isQuantifierNext(match.input, match.index + match[0].length, flags) ?1424 '' : '(?:)';1425 }1426 );1427/*1428 * Whitespace and line comments, in free-spacing mode (aka extended mode, flag x) only.1429 */1430 add(1431 /\s+|#.*/,1432 function(match, scope, flags) {1433 // Keep tokens separated unless the following token is a quantifier1434 return isQuantifierNext(match.input, match.index + match[0].length, flags) ?1435 '' : '(?:)';1436 },1437 {flag: 'x'}1438 );1439/*1440 * Dot, in dotall mode (aka singleline mode, flag s) only.1441 */1442 add(1443 /\./,1444 function() {1445 return '[\\s\\S]';1446 },1447 {flag: 's'}1448 );...

Full Screen

Full Screen

regexp.js

Source:regexp.js Github

copy

Full Screen

...91 }92 function isType(value, type) {93 return toString.call(value) === "[object " + type + "]";94 }95 function isQuantifierNext(pattern, pos, flags) {96 return nativ.test.call(flags.indexOf("x") > -1 ? /^(?:\s+|#.*|\(\?#[^)]*\))*(?:[?*+]|{\d+(?:,\d*)?})/ : /^(?:\(\?#[^)]*\))*(?:[?*+]|{\d+(?:,\d*)?})/, pattern.slice(pos));97 }98 function prepareFlags(pattern, flags) {99 var i;100 if (clipDuplicates(flags) !== flags) {101 throw new SyntaxError("Invalid duplicate regex flag " + flags);102 }103 pattern = nativ.replace.call(pattern, / ^ \ (\ ? ([\w$] + )\) / , function ($0, $1) {104 if (nativ.test.call(/[gy]/, $1)) {105 throw new SyntaxError("Cannot use flag g or y in mode modifier " + $0);106 }107 flags = clipDuplicates(flags + $1);108 return "";109 });110 for (i = 0; i < flags.length; ++i) {111 if (!registeredFlags[flags.charAt(i)]) {112 throw new SyntaxError("Unknown regex flag " + flags.charAt(i));113 }114 }115 return {116 pattern: pattern,117 flags: flags118 };119 }120 function prepareOptions(value) {121 value = value || {};122 if (isType(value, "String")) {123 value = self.forEach(value, / [ ^ \s, ] + /, function(match) {124 this[match] = true;125 }, {});126 }127 return value;128 }129 function registerFlag(flag) {130 if (!/ ^ [\w$] $ / .test(flag)) {131 throw new Error("Flag must be a single character A-Za-z0-9_$");132 }133 registeredFlags[flag] = true;134 }135 function runTokens(pattern, flags, pos, scope, context) {136 var i = tokens.length, result = null,, match, t137 //===================================================138 while (i--) {139 t = tokens[i];140 if ((t.scope === scope || t.scope === "all") && (!t.flag || flags.indexOf(t.flag) > -1)) {141 match = self.exec(pattern, t.regex, pos, "sticky");142 if (match) {143 result = {144 matchLength: match[0].length,145 output: t.handler.call(context, match, scope, flags),146 reparse: t.reparse147 };148 break;149 }150 }151 }152 return result;153 }154 function setAstral(on) {155 self.cache.flush("patterns");156 features.astral = on;157 }158 function setNatives(on) {159 RegExp.prototype.exec = (on ? fixed : nativ).exec;160 RegExp.prototype.test = (on ? fixed : nativ).test;161 String.prototype.match = (on ? fixed : nativ).match;162 String.prototype.replace = (on ? fixed : nativ).replace;163 String.prototype.split = (on ? fixed : nativ).split;164 features.natives = on;165 }166 function toObject(value) {167 if (value == null) {168 throw new TypeError("Cannot convert null or undefined to object");169 }170 return value;171 }172 self = function (pattern, flags) {173 var context = {174 hasNamedCapture: false,175 captureNames: []176 },177 scope = defaultScope,178 output = "",179 pos = 0,180 result, token, key;181 if (self.isRegExp(pattern)) {182 if (flags !== undefined) {183 throw new TypeError("Cannot supply flags when copying a RegExp");184 }185 return copy(pattern, {186 addProto: true187 });188 }189 pattern = pattern === undefined ? "" : String(pattern);190 flags = flags === undefined ? "" : String(flags);191 key = pattern + "***" + flags;192 if (!patternCache[key]) {193 result = prepareFlags(pattern, flags);194 pattern = result.pattern;195 flags = result.flags;196 while (pos < pattern.length) {197 do {198 result = runTokens(pattern, flags, pos, scope, context);199 if (result && result.reparse) {200 pattern = pattern.slice(0, pos) + result.output + pattern.slice(pos + result.matchLength);201 }202 } while (result && result.reparse);203 if (result) {204 output += result.output;205 pos += result.matchLength || 1;206 } else {207 token = self.exec(pattern, nativeTokens[scope], pos, "sticky")[0];208 output += token;209 pos += token.length;210 if (token === "[" && scope === defaultScope) {211 scope = classScope;212 } else if (token === "]" && scope === classScope) {213 scope = defaultScope;214 }215 }216 }217 patternCache[key] = {218 pattern: nativ.replace.call(output, / \ (\ ? : \)( ? = \ (\ ? : \)) | ^ \ (\ ? : \) | \ (\ ? : \) $ / g, ""),219 flags: nativ.replace.call(flags, / [ ^ gimy] + /g, ""),220 captures: context.hasNamedCapture ? context.captureNames : null221 };222 }223 key = patternCache[key];224 return augment(new RegExp(key.pattern, key.flags), key.captures, true);225 };226 self.prototype = new RegExp();227 self.version = "3.0.0-pre";228 self.addToken = function(regex, handler, options) {229 options = options || {};230 var optionalFlags = options.optionalFlags, i;231 if (options.flag) {232 registerFlag(options.flag);233 }234 if (optionalFlags) {235 optionalFlags = nativ.split.call(optionalFlags, "");236 for (i = 0; i < optionalFlags.length; ++i) {237 registerFlag(optionalFlags[i]);238 }239 }240 tokens.push({241 regex: copy(regex, {242 add: "g" + (hasNativeY ? "y" : "")243 }),244 handler: handler,245 scope: options.scope || defaultScope,246 flag: options.flag,247 reparse: options.reparse248 });249 self.cache.flush("patterns");250 };251 self.cache = function(pattern, flags) {252 var key = pattern + "***" + (flags || "");253 return cache[key] || (cache[key] = self(pattern, flags));254 };255 self.cache.flush = function(cacheName) {256 if (cacheName === "patterns") {257 patternCache = {};258 } else {259 cache = {};260 }261 };262 self.escape = function(str) {263 return nativ.replace.call(toObject(str), / [-[\] {}() * + ? ., \\ ^ $ | #\s] / g, "\\$&");264 };265 self.exec = function (str, regex, pos, sticky) {266 var cacheFlags = "g",267 match, r2;268 if (hasNativeY && (sticky || regex.sticky && sticky !== false)) {269 cacheFlags += "y";270 }271 regex[REGEX_DATA] = regex[REGEX_DATA] || getBaseProps();272 r2 = regex[REGEX_DATA][cacheFlags] || (regex[REGEX_DATA][cacheFlags] = copy(regex, {273 add: cacheFlags,274 remove: sticky === false ? "y" : ""275 }));276 r2.lastIndex = pos = pos || 0;277 match = fixed.exec.call(r2, str);278 if (sticky && match && match.index !== pos) {279 match = null;280 }281 if (regex.global) {282 regex.lastIndex = match ? r2.lastIndex : 0;283 }284 return match;285 };286 self.forEach = function (str, regex, callback, context) {287 var pos = 0, i = -1, match288 ;//=================================================289 while (match = self.exec(str, regex, pos)) {290 callback.call(context, match, ++i, str, regex);291 pos = match.index + (match[0].length || 1);292 }293 return context;294 };295 self.globalize = function (regex) {296 return copy(regex, {297 add: "g",298 addProto: true299 });300 };301 self.install = function (options) {302 options = prepareOptions(options);303 if (!features.astral && options.astral) {304 setAstral(true);305 }306 if (!features.natives && options.natives) {307 setNatives(true);308 }309 };310 self.isInstalled = function (feature) {311 return !!features[feature];312 };313 self.isRegExp = function (value) {314 return toString.call(value) === "[object RegExp]";315 };316 self.match = function (str, regex, scope) {317 var global = regex.global && scope !== "one" || scope === "all"318 , cacheFlags = (global ? "g" : "") + (regex.sticky ? "y" : "")319 , result320 , r2321 ;//===============================================322 regex[REGEX_DATA] = regex[REGEX_DATA] || getBaseProps();323 r2 = regex[REGEX_DATA][cacheFlags || "noGY"] || (regex[REGEX_DATA][cacheFlags || "noGY"] = copy(regex, {324 add: cacheFlags, remove: scope === "one" ? "g" : ""325 }));326 result = nativ.match.call(toObject(str), r2);327 if (regex.global) {328 regex.lastIndex = scope === "one" && result ? result.index + result[0].length : 0;329 }330 return global ? result || [] : result && result[0];331 };332 self.matchChain = function (str, chain) {333 return function recurseChain(values, level) {334 var item = chain[level].regex ? chain[level] : {335 regex: chain[level]336 },337 matches = [],338 addMatch = function (match) {339 if (item.backref) {340 if (!(match.hasOwnProperty(item.backref) || +item.backref < match.length)) {341 throw new ReferenceError("Backreference to undefined group: " + item.backref);342 }343 matches.push(match[item.backref] || "");344 } else {345 matches.push(match[0]);346 }347 },348 i;349 for (i = 0; i < values.length; ++i) {350 self.forEach(values[i], item.regex, addMatch);351 }352 return level === chain.length - 1 || !matches.length ? matches : recurseChain(matches, level + 1);353 }([str], 0);354 };355 self.replace = function (str, search, replacement, scope) {356 var isRegex = self.isRegExp(search),357 global = search.global && scope !== "one" || scope === "all",358 cacheFlags = (global ? "g" : "") + (search.sticky ? "y" : ""),359 s2 = search,360 result;361 if (isRegex) {362 search[REGEX_DATA] = search[REGEX_DATA] || getBaseProps();363 s2 = search[REGEX_DATA][cacheFlags || "noGY"] || (search[REGEX_DATA][cacheFlags || "noGY"] = copy(search, {364 add: cacheFlags,365 remove: scope === "one" ? "g" : ""366 }));367 } else if (global) {368 s2 = new RegExp(self.escape(String(search)), "g");369 }370 result = fixed.replace.call(toObject(str), s2, replacement);371 if (isRegex && search.global) {372 search.lastIndex = 0;373 }374 return result;375 };376 self.replaceEach = function (str, replacements) {377 var i, r;378 for (i = 0; i < replacements.length; ++i) {379 r = replacements[i];380 str = self.replace(str, r[0], r[1], r[2]);381 }382 return str;383 };384 self.split = function (str, separator, limit) {385 return fixed.split.call(toObject(str), separator, limit);386 };387 self.test = function (str, regex, pos, sticky) {388 return !!self.exec(str, regex, pos, sticky);389 };390 self.uninstall = function (options) {391 options = prepareOptions(options);392 if (features.astral && options.astral) {393 setAstral(false);394 }395 if (features.natives && options.natives) {396 setNatives(false);397 }398 };399 self.union = function (patterns, flags) {400 var parts = /(\()(?!\?)|\\([1-9]\d*)|\\[\s\S]|\[(?:[^\\\]]|\\[\s\S])*]/g,401 output = [],402 numCaptures = 0,403 numPriorCaptures, captureNames, pattern, rewrite = function (match, paren, backref) {404 var name = captureNames[numCaptures - numPriorCaptures];405 if (paren) {406 ++numCaptures;407 if (name) {408 return "(?<" + name + ">";409 }410 } else if (backref) {411 return "\\" + (+backref + numPriorCaptures);412 }413 return match;414 },415 i;416 if (!(isType(patterns, "Array") && patterns.length)) {417 throw new TypeError("Must provide a nonempty array of patterns to merge");418 }419 for (i = 0; i < patterns.length; ++i) {420 pattern = patterns[i];421 if (self.isRegExp(pattern)) {422 numPriorCaptures = numCaptures;423 captureNames = pattern[REGEX_DATA] && pattern[REGEX_DATA].captureNames || [];424 output.push(nativ.replace.call(self(pattern.source).source, parts, rewrite));425 } else {426 output.push(self.escape(pattern));427 }428 }429 return self(output.join("|"), flags);430 };431 fixed.exec = function (str) {432 var origLastIndex = this.lastIndex,433 match = nativ.exec.apply(this, arguments),434 name, r2, i;435 if (match) {436 if (!correctExecNpcg && match.length > 1 && indexOf(match, "") > -1) {437 r2 = copy(this, {438 remove: "g"439 });440 nativ.replace.call(String(str).slice(match.index), r2, function () {441 var len = arguments.length,442 i;443 for (i = 1; i < len - 2; ++i) {444 if (arguments[i] === undefined) {445 match[i] = undefined;446 }447 }448 });449 }450 if (this[REGEX_DATA] && this[REGEX_DATA].captureNames) {451 for (i = 1; i < match.length; ++i) {452 name = this[REGEX_DATA].captureNames[i - 1];453 if (name) {454 match[name] = match[i];455 }456 }457 }458 if (this.global && !match[0].length && this.lastIndex > match.index) {459 this.lastIndex = match.index;460 }461 }462 if (!this.global) {463 this.lastIndex = origLastIndex;464 }465 return match;466 };467 fixed.test = function (str) {468 return !!fixed.exec.call(this, str);469 };470 fixed.match = function (regex) {471 var result;472 if (!self.isRegExp(regex)) {473 regex = new RegExp(regex);474 } else if (regex.global) {475 result = nativ.match.apply(this, arguments);476 regex.lastIndex = 0;477 return result;478 }479 return fixed.exec.call(regex, toObject(this));480 };481 fixed.replace = function (search, replacement) {482 var isRegex = self.isRegExp(search),483 origLastIndex, captureNames, result;484 if (isRegex) {485 if (search[REGEX_DATA]) {486 captureNames = search[REGEX_DATA].captureNames;487 }488 origLastIndex = search.lastIndex;489 } else {490 search += "";491 }492 if (isType(replacement, "Function")) {493 result = nativ.replace.call(String(this), search, function () {494 var args = arguments,495 i;496 if (captureNames) {497 args[0] = new String(args[0]);498 for (i = 0; i < captureNames.length; ++i) {499 if (captureNames[i]) {500 args[0][captureNames[i]] = args[i + 1];501 }502 }503 }504 if (isRegex && search.global) {505 search.lastIndex = args[args.length - 2] + args[0].length;506 }507 return replacement.apply(undefined, args);508 });509 } else {510 result = nativ.replace.call(this == null ? this : String(this), search, function () {511 var args = arguments;512 return nativ.replace.call(String(replacement), replacementToken, function ($0, $1, $2) {513 var n;514 if ($1) {515 n = +$1;516 if (n <= args.length - 3) {517 return args[n] || "";518 }519 n = captureNames ? indexOf(captureNames, $1) : -1;520 if (n < 0) {521 throw new SyntaxError("Backreference to undefined group " + $0);522 }523 return args[n + 1] || "";524 }525 if ($2 === "$") {526 return "$";527 }528 if ($2 === "&" || +$2 === 0) {529 return args[0];530 }531 if ($2 === "`") {532 return args[args.length - 1].slice(0, args[args.length - 2]);533 }534 if ($2 === "'") {535 return args[args.length - 1].slice(args[args.length - 2] + args[0].length);536 }537 $2 = +$2;538 if (!isNaN($2)) {539 if ($2 > args.length - 3) {540 throw new SyntaxError("Backreference to undefined group " + $0);541 }542 return args[$2] || "";543 }544 throw new SyntaxError("Invalid token " + $0);545 });546 });547 }548 if (isRegex) {549 if (search.global) {550 search.lastIndex = 0;551 } else {552 search.lastIndex = origLastIndex;553 }554 }555 return result;556 };557 fixed.split = function (separator, limit) {558 if (!self.isRegExp(separator)) {559 return nativ.split.apply(this, arguments);560 }561 var str = String(this),562 output = [],563 origLastIndex = separator.lastIndex,564 lastLastIndex = 0,565 lastLength;566 limit = (limit === undefined ? -1 : limit) >>> 0;567 self.forEach(str, separator, function (match) {568 if (match.index + match[0].length > lastLastIndex) {569 output.push(str.slice(lastLastIndex, match.index));570 if (match.length > 1 && match.index < str.length) {571 Array.prototype.push.apply(output, match.slice(1));572 }573 lastLength = match[0].length;574 lastLastIndex = match.index + lastLength;575 }576 });577 if (lastLastIndex === str.length) {578 if (!nativ.test.call(separator, "") || lastLength) {579 output.push("");580 }581 } else {582 output.push(str.slice(lastLastIndex));583 }584 separator.lastIndex = origLastIndex;585 return output.length > limit ? output.slice(0, limit) : output;586 };587 add = self.addToken;588 add(/\\([ABCE-RTUVXYZaeg-mopqyz]|c(?![A-Za-z])|u(?![\dA-Fa-f]{4})|x(?![\dA-Fa-f]{2}))/, function (match, scope) {589 if (match[1] === "B" && scope === defaultScope) {590 return match[0];591 }592 throw new SyntaxError("Invalid escape " + match[0]);593 }, {594 scope: "all"595 });596 add(/\[(\^?)]/, function (match) {597 return match[1] ? "[\\s\\S]" : "\\b\\B";598 });599 add(/\(\?#[^)]*\)/, function (match, scope, flags) {600 return isQuantifierNext(match.input, match.index + match[0].length, flags) ? "" : "(?:)";601 });602 add(/\s+|#.*/, function (match, scope, flags) {603 return isQuantifierNext(match.input, match.index + match[0].length, flags) ? "" : "(?:)";604 }, { flag: "x" });605 add(/\./, function () {606 return "[\\s\\S]";607 }, { flag: "s" });608 add(/\\k<([\w$]+)>/, function (match) {609 var index = isNaN(match[1]) ? indexOf(this.captureNames, match[1]) + 1 : +match[1], endIndex = match.index + match[0].length;610 if (!index || index > this.captureNames.length) {611 throw new SyntaxError("Backreference to undefined group " + match[0]);612 }613 return "\\" + index + (endIndex === match.input.length || isNaN(match.input.charAt(endIndex)) ? "" : "(?:)");614 });615 add(/\\(\d+)/, function (match, scope) {616 if (!(scope === defaultScope && /^[1-9]/.test(match[1]) && +match[1] <= this.captureNames.length) && match[1] !== "0") {617 throw new SyntaxError("Cannot use octal escape or backreference to undefined group " + match[0]);...

Full Screen

Full Screen

Using AI Code Generation

copy

Full Screen

1var redwood = require('redwood');2console.log(redwood.isQuantifierNext("2"));3console.log(redwood.isQuantifierNext("10"));4console.log(redwood.isQuantifierNext("a"));5console.log(redwood.isQuantifierNext("a2"));6console.log(redwood.isQuantifierNext("a10"));7console.log(redwood.isQuantifierNext("abc"));8var redwood = require('redwood');9console.log(redwood.isQuantifierNext("2"));10console.log(redwood.isQuantifierNext("10"));11console.log(redwood.isQuantifierNext("a"));12console.log(redwood.isQuantifierNext("a2"));13console.log(redwood.isQuantifierNext("a10"));14console.log(redwood.isQuantifierNext("abc"));15var redwood = require('redwood');16console.log(redwood.isQuantifierNext("2"));17console.log(redwood.isQuantifierNext("10"));18console.log(redwood.isQuantifierNext("a"));19console.log(redwood.isQuantifierNext("a2"));20console.log(redwood.isQuantifierNext("a10"));21console.log(redwood.isQuantifierNext("abc"));22var redwood = require('redwood');23console.log(redwood.isQuantifierNext("2"));24console.log(redwood.isQuantifierNext("10"));25console.log(redwood.isQuantifierNext("a"));26console.log(redwood.isQuantifierNext("a2"));27console.log(redwood.isQuantifierNext("a10"));28console.log(redwood.isQuantifierNext("abc"));29var redwood = require('redwood');30console.log(redwood.isQuantifierNext("2"));31console.log(redwood.isQuantifierNext("10"));32console.log(redwood.isQuantifierNext("a"));33console.log(redwood.isQuantifierNext("a2"));

Full Screen

Using AI Code Generation

copy

Full Screen

1var redwood = require('redwood');2var str = "a?b";var redwood = require('redwood');3var i = 0;4isQuantifierNext(str, i)5var i = 0;6isQuantifierNext(str, i)

Full Screen

Using AI Code Generation

copy

Full Screen

1var redwood = require('redwoodjs');2var rw = new redwood.Redwood();3var str = "a*b";4var index = 0;5var result = rw.isQuantifierNext(str, index);6console.log(result);7var redwood = require('redwoodjs');8var rw = new redwood.Redwood();9var str = "ab";10var index = 0;11var result = rw.isQuantifierNext(str, index);12console.log(result);13var redwood = require('redwoodjs');14var rw = new redwood.Redwood();15var str = "a*b";16var index = 1;17var result = rw.isQuantifierNext(str, index);18console.log(result);19var redwood = require('redwoodjs');20var rw = new redwood.Redwood();21var str = "a*b";22var index = 2;23var result = rw.isQuantifierNext(str, index);24console.log(result);

Full Screen

Using AI Code Generation

copy

Full Screen

1var redwood = require('redwood');2var re = /a*/;3var str = "aabb";4var result = redwood.isQuantifierNext(re, str, 1);5console.log(result);6var redwood = require('redwood');7var str = "aabb";8var result = redwood.isQuantifierNext(re, str, 3);9console.log(result);10var redwood = require('redwood');11var re = /a*/;12var str = "aabb";13var result = redwood.isQuantifierNext(re, str, 2);14console.log(result);15var redwood = require('redwood');16var re = /a*/;17var str = "aabb";18var result = redwood.isQuantifierNext(re, str, 4);19console.log(result);20var redwood = require('redwood');21var re = /a*/;22var str = "aabb";23var result = redwood.isQuantifierNext(re, str, 0);24console.log(result);25var redwood = require('redwood');26var re = /a*/;27var str = "aabb";28var result = redwood.isQuantifierNext(re, str, 5);29console.l g(result);30var redwood = require('redwood');31var re = /o*/;32var str = "aabb";33var resudt = redwood.ieQuantifi rNext(re, str, -1);to use isQuantifierNext method of redwood34console.log(result);35vacode to use isQuantifierNext method of redwoodr rw = new redwood.Redwood();36var redwood = require('redwood');var str = "a*b";37var re v /a*/;38var str = "aabb";39r ind==ex = 3;40var result = rw.isQuantifierNext(str, index);41console.log(result);42var redwood = require('redwoodjs');43var rw = new redwood.Redwood();44var str = "a*b";45var index = 4;46var result = rw.isQuantifierNext(str, index);47console.log(result);48var redwood = require('redwoodjs');49var rw = new redwood.Redwood();50var str = "a*b";51var index = 5;52var result = rw.isQuantifierNext(str, index);53console.log(result);

Full Screen

Using AI Code Generation

copy

Full Screen

1var redwood = require('redwood');2var re = /a*/;3var str = "aabb";4var result = redwood.isQuantifierNext(re, str, 1);5console.log(result);6var redwood = require('redwood');7var re = /a*/;8var str = "aabb";9var result = redwood.isQuantifierNext(re, str, 3);10console.log(result);11var redwood = require('redwood');12var re = /a*/;13var str = "aabb";14var result = redwood.isQuantifierNext(re, str, 2);15console.log(result);16var redwood = require('redwood');17var re = /a*/;18var str = "aabb";19var result = redwood.isQuantifierNext(re, str, 4);20console.log(result);

Full Screen

Using AI Code Generation

copy

Full Screen

1var redwood = require('redwoodjs');2var str = "sdfdsf";3var isQuan ifieruse isQuantifierntifierNext(str, 0);4coNsole.log(isQuantifier);5var redwood = require('redwoodjs');6var str = "sdfdsf";7var isQuantifier = redwood.isQuantifierNext(str, 1);8console.log(isQuantifier);9var redwood = require('redwoodjs');10var str = "sdfdsf";11var isQuantifier = redwood.isQuantifierNext(str, 2);12console.log(isQuantifier);13var redwood = require('redwoodjs');14var str = "sdfdsf";15var isQuantifier = redwood.isQuantifierNext(str, 3);16console.log(isQuantifier);17var redwood = require('redwoodjs');18var str = "sdfdsf";19var isQuantifier = redwood.isQuantifierNext(str, 4);20console.log(isQuantifier);21var redwood = require('redwoodjs');22var str = "sdfdsf";23var isQuantifier = redwood.isQuantifierNext(str, 5);24console.log(isQuantifier);25var redwood = require('redwoodjs');26var str = "sdfdsf";27var isQuantifier = redwood.isQuantifierNext(str, 6);28console.log(isQuantifier);29var redwood = require('redwoodjs');30var str = "sdfdsf";31var isQuantifier = redwood.isQuantifierNext(str, 7);32console.log(isQuantifier);

Full Screen

Using AI Code Generation

copy

Full Screen

1var redwood = require('./redwood.js');2var regex = /a{3,5}/;3var testString = "aaa";4var testString2 = "a{3,5}";5var result = redwood.isQuantifierNext(regex, testString);6var result2 = redwood.isQuantifierNext(regex, testString2);7console.log(result);8console.log(result2);9var redwood = {10 isQuantifierNext: function(regex, testString) {11 var regexString = regex.toString().slice(1, -1);12 var quantifier = regexString.slice(regexString.indexOf(testString) + testString.length);13 var quantifierRegex = /^[+*?]|{\d+(,\d+)?}/;14 return quantifierRegex.test(quantifier);15 }16};17module.exports = redwood;

Full Screen

Using AI Code Generation

copy

Full Screen

1var redwood = require('./redwood.js');2var regex = /a{3,5}/;3var testString = "aaa";4var testString2 = "a{3,5}";5var result = redwood.isQuantifierNext(regex, testString);6var result2 = redwood.isQuantifierNext(regex, testString2);7console.log(result);8console.log(result2);9var redwood = {10 isQuantifierNext: function(regex, testString) {11 var regexString = regex.toString().slice(1, -1);12 var quantifier = regexString.slice(regexString.indexOf(testString) + testString.length);13 var quantifierRegex = /^[+*?]|{\d+(,\d+)?}/;14 return quantifierRegex.test(quantifier);15 }16};17module.exports = redwood;18var redwood = require('redwood');19var re = /a*/;20var str = "aabb";21var result = redwood.isQuantifierNext(re, str, 0);22console.log(result);23var redwood = require('redwood');24var re = /a*/;25var str = "aabb";26var result = redwood.isQuantifierNext(re, str, 5);27console.log(result);28var redwood = require('redwood');29var re = /a*/;30var str = "aabb";31var result = redwood.isQuantifierNext(re, str, -1);32console.log(result);33var redwood = require('redwood');34var re = /a*/;35var str = "aabb";

Full Screen

Using AI Code Generation

copy

Full Screen

1var redwood = require('redwood');2var text = "Abc";3var regex = /a?/i;4var result = redwood.isQuantifierNext(regex, text);5console.log(result);6var redwood = require('redwood');7var text = "Abc";8var regex = /a?/i;9var result = redwood.isQuantifierNext(regex, text);10console.log(result);11var redwood = require('redwood');12var text = "Abc";13var regex = /a?/i;14var result = redwood.isQuantifierNext(regex, text);15console.log(result);16var redwood = require('redwood');17var text = "Abc";18var regex = /a?/i;19var result = redwood.isQuantifierNext(regex, text);20console.log(result);21var redwood = require('redwood');22var text = "Abc";23var regex = /a?/i;24var result = redwood.isQuantifierNext(regex, text);25console.log(result);26var redwood = require('redwood');27var text = "Abc";28var regex = /a?/i;

Full Screen

Using AI Code Generation

copy

Full Screen

1var redwood = require('redwood');2var input = 'a{1,2}b{2,3}c{3,4}d{4,5}e{5,6}f{6,7}g{7,8}h{8,9}i{9,10}j{10,11}k{11,12}l{12,13}m{13,14}n{14,15}o{15,16}p{16,17}q{17,18}r{18,19}s{19,20}t{20,21}u{21,22}v{22,23}w{23,24}x{24,25}y{25,26}z{26,27}A{27,28}B{28,29}C{29,30}D{30,31}E{31,32}F{32,33}G{33,34}H{34,35}I{35,36}J{36,37}K{37,38}L{38,39}M{39,40}N{40,41}O{41,42}P{42,43}Q{43,44}R{44,45}S{45,46}T{46,47}U{47,48}V{48,49}W{49,50}X{50,51}Y{51,52}Z{52,53}0{53,54}1{54,55}2{55,56}3{56,57}4{57,58}5{58,59}6{59,60}7{60,61}8{61,62}9{62,63}';3var lexer = new redwood.Lexer(input);4var token = lexer.next();5while(token !== null) {6 if(token.value === '{') {7 if(lexer.isQuantifierNext()) {8 token.quantifier = lexer.next();9 token = lexer.next();10 }11 }12 console.log(token);13 token = lexer.next();14}

Full Screen

Automation Testing Tutorials

Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.

LambdaTest Learning Hubs:

YouTube

You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.

Run redwood automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful