function isAlwaysZeroWidth(element) {
switch (element.type) {
case 'Assertion':
return true;
case 'Quantifier':
return element.max === 0 || isAlwaysZeroWidth(element.element);
case 'CapturingGroup':
case 'Group':
return element.alternatives.every(alt => alt.elements.every(isAlwaysZeroWidth));
case 'Backreference':
return isAlwaysZeroWidth(element.resolved);
default:
return false;
}
}
function isFirstMatch(element) {
const parent = element.parent;
switch (parent.type) {
case 'Alternative':
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}'.`);
}
}
function underAStar(node) {
if (node.type === "Quantifier" && node.max > 10) {
return true;
} else if (node.parent) {
return underAStar(node.parent);
} else {
return false;
}
}
function firstOf(iter) {
for (const item of iter) {
return item;
}
return undefined;
}
module.exports = { firstOf, underAStar, isFirstMatch, isAlwaysZeroWidth};