/** * Returns whether the given element will always have zero width meaning that it doesn't consume characters. * * @param {Element} element * @returns {boolean} */ function isAlwaysZeroWidth(element) { switch (element.type) { case 'Assertion': // assertions == ^, $, \b, lookarounds return true; case 'Quantifier': return element.max === 0 || isAlwaysZeroWidth(element.element); case 'CapturingGroup': case 'Group': // every element in every alternative has to be of zero length return element.alternatives.every(alt => alt.elements.every(isAlwaysZeroWidth)); case 'Backreference': // on if the group referred to is of zero length return isAlwaysZeroWidth(element.resolved); default: return false; // what's left are characters } } /** * Returns whether the given element will always at the start of the whole match. * * @param {Element} element * @returns {boolean} */ function isFirstMatch(element) { const parent = element.parent; switch (parent.type) { case 'Alternative': // all elements before this element have to of zero length if (!parent.elements.slice(0, parent.elements.indexOf(element)).every(isAlwaysZeroWidth)) { return false; } const grandParent = parent.parent; if (grandParent.type === 'Pattern') { return true; } else { return isFirstMatch(grandParent); } case 'Quantifier': if (parent.max >= 2) { return false; } else { return isFirstMatch(parent); } default: throw new Error(`Internal error: The given node should not be a '${element.type}'.`); } } /** * Returns whether the given node either is or is a child of what is effectively a Kleene star. * * @param {import("regexpp/ast").Node} node * @returns {boolean} */ function underAStar(node) { if (node.type === "Quantifier" && node.max > 10) { return true; } else if (node.parent) { return underAStar(node.parent); } else { return false; } } /** * @param {Iterable} iter * @returns {T | undefined} * @template T */ function firstOf(iter) { for (const item of iter) { return item; } return undefined; } module.exports = { firstOf, underAStar, isFirstMatch, isAlwaysZeroWidth};