Skip to content

Commit

Permalink
Merge pull request #1681 from blackflux/dev
Browse files Browse the repository at this point in the history
[Gally]: master <- dev
  • Loading branch information
simlu committed Jun 8, 2022
2 parents 608943d + 8043e1a commit b2c9c91
Show file tree
Hide file tree
Showing 7 changed files with 78 additions and 69 deletions.
37 changes: 24 additions & 13 deletions src/core/compiler.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ const markLeaf = (input, match, readonly) => defineProperty(input, LEAF, match,
export const isLeaf = (input) => LEAF in input;
export const isMatch = (input) => input !== undefined && input[LEAF] === true;

const ROOTS = Symbol('roots');
const setRoots = (input, roots) => defineProperty(input, ROOTS, roots);
export const getRoots = (input) => input[ROOTS];

const HAS_MATCHES = Symbol('has-matches');
const setHasMatches = (input) => defineProperty(input, HAS_MATCHES, true);
export const hasMatches = (input) => input[HAS_MATCHES] === true;
Expand Down Expand Up @@ -58,11 +62,11 @@ const setValues = (input, entries) => defineProperty(input, VALUES, entries);
export const getValues = (input) => input[VALUES];

export const matchedBy = (searches) => Array
.from(new Set([].concat(...searches.map((e) => getLeafNeedlesMatch(e)))));
.from(new Set(searches.flatMap((e) => getLeafNeedlesMatch(e))));
export const excludedBy = (searches) => Array
.from(new Set([].concat(...searches.map((e) => getLeafNeedlesExclude(e)))));
.from(new Set(searches.flatMap((e) => getLeafNeedlesExclude(e))));
export const traversedBy = (searches) => Array
.from(new Set([].concat(...searches.map((e) => getNeedles(e)))));
.from(new Set(searches.flatMap((e) => getNeedles(e))));

export const isLastLeafMatch = (searches) => {
let maxLeafIndex = Number.MIN_SAFE_INTEGER;
Expand Down Expand Up @@ -106,7 +110,7 @@ const iterate = (tower, needle, tree, { onAdd, onFin }) => {
} else {
stack[stack.length - 1]
.filter(([cur]) => cur !== tower)
.forEach(([cur, parent]) => onFin(cur, wc[wc.length - 1], parent, excluded));
.forEach(([cur, parent]) => onFin(cur, parent, wc[wc.length - 1], excluded));
}
});
};
Expand Down Expand Up @@ -139,13 +143,11 @@ const applyNeedle = (tower, needle, tree, ctx) => {
next(cur);
}
},
onFin: (cur, wc, parent, excluded) => {
if (ctx.strict) {
if (wc.isSimpleStarRec) {
const unnecessary = Object.keys(parent).filter((k) => !['**', ''].includes(k));
if (unnecessary.length !== 0) {
throw new Error(`Needle Target Invalidated: "${parent[unnecessary[0]][NEEDLES][0]}" by "${needle}"`);
}
onFin: (cur, parent, wc, excluded) => {
if (ctx.strict && wc.isSimpleStarRec) {
const unnecessary = Object.keys(parent).filter((k) => !['**', ''].includes(k));
if (unnecessary.length !== 0) {
throw new Error(`Needle Target Invalidated: "${parent[unnecessary[0]][NEEDLES][0]}" by "${needle}"`);
}
}
addNeedle(cur, needle);
Expand All @@ -165,7 +167,7 @@ const applyNeedle = (tower, needle, tree, ctx) => {
});
};

const finalizeTower = (tower) => {
const finalizeTower = (tower, ctx) => {
const matches = [];
let lastDepth = -1;

Expand All @@ -183,6 +185,15 @@ const finalizeTower = (tower) => {
lastDepth = depth;
}
});

if (ctx.useArraySelector === false) {
const roots = [];
if ('' in tower) {
roots.push(tower['']);
}
roots.push(...getValues(tower).filter((e) => getWildcard(e).isStarRec));
setRoots(tower, roots);
}
};

export const compile = (needles, ctx) => {
Expand All @@ -194,6 +205,6 @@ export const compile = (needles, ctx) => {
applyNeedle(tower, needle, tree, ctx);
}
setWildcard(tower, new Wildcard('*', false));
finalizeTower(tower);
finalizeTower(tower, ctx);
return tower;
};
12 changes: 4 additions & 8 deletions src/core/find.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import assert from 'assert';
import {
getWildcard, excludedBy, traversedBy,
hasMatches, matchedBy, isLastLeafMatch,
getValues, getOrder
getValues, getOrder, getRoots
} from './compiler.js';
import Result from './find-result.js';
import { toPath } from '../generic/helper.js';
Expand Down Expand Up @@ -165,17 +165,13 @@ export default (haystack_, searches_, ctx) => {
const searchesOut = [];
if (autoTraverseArray) {
searchesOut.push(...searches);
if (path.length === 0) {
if ('' in searches[0]) {
searchesOut.push(searches[0]['']);
}
searchesOut.push(...getValues(searches[0])
.filter((v) => getWildcard(v).isStarRec));
if (depth === 0) {
searchesOut.push(...getRoots(searches[0]));
}
} else {
for (let sIdx = 0, sLen = searches.length; sIdx !== sLen; sIdx += 1) {
const search = searches[sIdx];
if (getWildcard(search).anyMatch(key)) {
if (getWildcard(search).recMatch(key)) {
searchesOut.push(search);
}
const values = getValues(search);
Expand Down
14 changes: 8 additions & 6 deletions src/core/parser-result.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,14 @@ export default (input) => {
}
inArray = flag;
},
finishElement: (idx, { err, fins, finReq = false }) => {
finishElement: (idx, err, fins, { finReq = false } = {}) => {
const isFinished = cursor === idx;
if (isFinished && !fins.includes(input[idx - 1] || null)) {
throwError(err, input, { char: idx });
}
if (!isFinished) {
if (isFinished) {
if (!fins.includes(input[idx - 1] || null)) {
throwError(err, input, { char: idx });
}
cursor += 1;
} else {
if (finReq) {
throwError(err, input, { char: idx });
}
Expand All @@ -73,8 +75,8 @@ export default (input) => {
}
cResult.push(new Wildcard(inArray ? `[${ele}]` : ele, excludeNext));
excludeNext = false;
cursor = idx + 1;
}
cursor = idx + 1;
},
startExclusion: (idx) => {
if (excludeNext !== false) {
Expand Down
74 changes: 37 additions & 37 deletions src/core/parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,43 +18,43 @@ const parse = (input, ctx) => {

for (let idx = 0; idx < inputLength; idx += 1) {
const char = input[idx];
if (escaped === false && bracketDepth === 0) {
switch (char) {
case '.':
result.finishElement(idx, { err: 'Bad Path Separator', fins: [']', '}'] });
break;
case '[':
if (!ctx.useArraySelector) {
throwError('Forbidden Array Selector', input, { char: idx });
}
result.finishElement(idx, { err: 'Bad Array Start', fins: [null, '!', '{', ',', '}', ']'] });
result.setInArray(true, idx);
break;
case ']':
result.finishElement(idx, { err: 'Bad Array Terminator', fins: ['}'] });
result.setInArray(false, idx);
break;
case '{':
result.finishElement(idx, { err: 'Bad Group Start', fins: [null, '!', '.', '[', '{', ','], finReq: true });
result.startGroup();
break;
case ',':
result.finishElement(idx, { err: 'Bad Group Separator', fins: [']', '}'] });
result.newGroupElement();
break;
case '}':
result.finishElement(idx, { err: 'Bad Group Terminator', fins: [']', '}'] });
result.finishGroup(idx);
break;
case '!':
result.finishElement(idx, { err: 'Bad Exclusion', fins: [null, '.', ',', '{', '['], finReq: true });
result.startExclusion(idx);
break;
default:
break;
}
}
if (escaped === false) {
if (bracketDepth === 0) {
switch (char) {
case '.':
result.finishElement(idx, 'Bad Path Separator', [']', '}']);
break;
case '[':
if (!ctx.useArraySelector) {
throwError('Forbidden Array Selector', input, { char: idx });
}
result.finishElement(idx, 'Bad Array Start', [null, '!', '{', ',', '}', ']']);
result.setInArray(true, idx);
break;
case ']':
result.finishElement(idx, 'Bad Array Terminator', ['}']);
result.setInArray(false, idx);
break;
case '{':
result.finishElement(idx, 'Bad Group Start', [null, '!', '.', '[', '{', ','], { finReq: true });
result.startGroup();
break;
case ',':
result.finishElement(idx, 'Bad Group Separator', [']', '}']);
result.newGroupElement();
break;
case '}':
result.finishElement(idx, 'Bad Group Terminator', [']', '}']);
result.finishGroup(idx);
break;
case '!':
result.finishElement(idx, 'Bad Exclusion', [null, '.', ',', '{', '['], { finReq: true });
result.startExclusion(idx);
break;
default:
break;
}
}
switch (char) {
case '(':
bracketDepth += 1;
Expand All @@ -79,7 +79,7 @@ const parse = (input, ctx) => {
throwError('Unterminated Parentheses', input);
}

result.finishElement(inputLength, { err: 'Bad Terminator', fins: [']', '}'] });
result.finishElement(inputLength, 'Bad Terminator', [']', '}']);
return result.finalizeResult();
};
export default { parse };
2 changes: 1 addition & 1 deletion src/core/wildcard.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ export class Wildcard {
this.isAnyObjTarget = value === '*';
}

anyMatch(key) {
recMatch(key) {
if (!this.isRec) {
return false;
}
Expand Down
4 changes: 2 additions & 2 deletions test/bulk.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import generateDataset from './helper/generate-dataset.js';
import generateNeedles from './helper/generate-needles.js';
import objectScan from '../src/index.js';

const Tester = () => {
const Tester = (seed = null) => {
const generateTestSet = ({ useArraySelector, modify }) => {
const { rng, haystack, paths } = generateDataset();
const { rng, haystack, paths } = generateDataset(seed);
const needles = generateNeedles({
rng,
paths,
Expand Down
4 changes: 2 additions & 2 deletions test/core/parser.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -210,11 +210,11 @@ describe('Testing Parser', () => {
checkError('{1,2,}', 'Bad Group Terminator: {1,2,}, char 5');
});

it('Testing Group Stars After Element', () => {
it('Testing Group Starts After Element', () => {
checkError('\\.{2,3}', 'Bad Group Start: \\.{2,3}, char 2');
});

it('Testing Group Stars After Group', () => {
it('Testing Group Starts After Group', () => {
checkError('{1,2}{2,3}', 'Bad Group Start: {1,2}{2,3}, char 5');
});
});
Expand Down

0 comments on commit b2c9c91

Please sign in to comment.