feat!: properly handle predicates used on quantified captures
This commit is contained in:
parent
a0cf0a7104
commit
09ac28c77d
3 changed files with 218 additions and 63 deletions
|
|
@ -841,7 +841,13 @@ class Language {
|
|||
}
|
||||
const operator = steps[0].value;
|
||||
let isPositive = true;
|
||||
let matchAll = true;
|
||||
switch (operator) {
|
||||
case 'any-not-eq?':
|
||||
isPositive = false;
|
||||
matchAll = false;
|
||||
case 'any-eq?':
|
||||
matchAll = false;
|
||||
case 'not-eq?':
|
||||
isPositive = false;
|
||||
case 'eq?':
|
||||
|
|
@ -855,28 +861,36 @@ class Language {
|
|||
const captureName1 = steps[1].name;
|
||||
const captureName2 = steps[2].name;
|
||||
textPredicates[i].push(function(captures) {
|
||||
let node1, node2
|
||||
let nodes_1 = [];
|
||||
let nodes_2 = [];
|
||||
for (const c of captures) {
|
||||
if (c.name === captureName1) node1 = c.node;
|
||||
if (c.name === captureName2) node2 = c.node;
|
||||
if (c.name === captureName1) nodes_1.push(c.node);
|
||||
if (c.name === captureName2) nodes_2.push(c.node);
|
||||
}
|
||||
if(node1 === undefined || node2 === undefined) return true;
|
||||
return (node1.text === node2.text) === isPositive;
|
||||
return matchAll
|
||||
? nodes_1.every(n1 => nodes_2.some(n2 => n1.text === n2.text)) === isPositive
|
||||
: nodes_1.some(n1 => nodes_2.some(n2 => n1.text === n2.text)) === isPositive;
|
||||
});
|
||||
} else {
|
||||
const captureName = steps[1].name;
|
||||
const stringValue = steps[2].value;
|
||||
textPredicates[i].push(function(captures) {
|
||||
let nodes = [];
|
||||
for (const c of captures) {
|
||||
if (c.name === captureName) {
|
||||
return (c.node.text === stringValue) === isPositive;
|
||||
};
|
||||
if (c.name === captureName) nodes.push(c.node);
|
||||
}
|
||||
return true;
|
||||
return matchAll
|
||||
? nodes.every(n => n.text === stringValue) === isPositive
|
||||
: nodes.some(n => n.text === stringValue) === isPositive;
|
||||
});
|
||||
}
|
||||
break;
|
||||
|
||||
case 'not-any-match?':
|
||||
isPositive = false;
|
||||
matchAll = false;
|
||||
case 'any-match?':
|
||||
matchAll = false;
|
||||
case 'not-match?':
|
||||
isPositive = false;
|
||||
case 'match?':
|
||||
|
|
@ -892,10 +906,14 @@ class Language {
|
|||
const captureName = steps[1].name;
|
||||
const regex = new RegExp(steps[2].value);
|
||||
textPredicates[i].push(function(captures) {
|
||||
const nodes = [];
|
||||
for (const c of captures) {
|
||||
if (c.name === captureName) return regex.test(c.node.text) === isPositive;
|
||||
if (c.name === captureName) nodes.push(c.node.text);
|
||||
}
|
||||
return true;
|
||||
if (nodes.length === 0) return !isPositive;
|
||||
return matchAll
|
||||
? nodes.every(text => regex.test(text)) === isPositive
|
||||
: nodes.some(text => regex.test(text)) === isPositive;
|
||||
});
|
||||
break;
|
||||
|
||||
|
|
@ -923,6 +941,32 @@ class Language {
|
|||
properties[i][steps[1].value] = steps[2] ? steps[2].value : null;
|
||||
break;
|
||||
|
||||
case 'not-any-of?':
|
||||
isPositive = false;
|
||||
case 'any-of?':
|
||||
if (steps.length < 2) throw new Error(
|
||||
`Wrong number of arguments to \`#${operator}\` predicate. Expected at least 1. Got ${steps.length - 1}.`
|
||||
);
|
||||
if (steps[1].type !== 'capture') throw new Error(
|
||||
`First argument of \`#${operator}\` predicate must be a capture. Got "${steps[1].value}".`
|
||||
);
|
||||
for (let i = 2; i < steps.length; i++) {
|
||||
if (steps[i].type !== 'string') throw new Error(
|
||||
`Arguments to \`#${operator}\` predicate must be a strings.".`
|
||||
);
|
||||
}
|
||||
captureName = steps[1].name;
|
||||
const values = steps.slice(2).map(s => s.value);
|
||||
textPredicates[i].push(function(captures) {
|
||||
const nodes = [];
|
||||
for (const c of captures) {
|
||||
if (c.name === captureName) nodes.push(c.node.text);
|
||||
}
|
||||
if (nodes.length === 0) return !isPositive;
|
||||
return nodes.every(text => values.includes(text)) === isPositive;
|
||||
});
|
||||
break;
|
||||
|
||||
default:
|
||||
predicates[i].push({operator, operands: steps.slice(1)});
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue