Skip to content

Instantly share code, notes, and snippets.

@conartist6
Last active July 23, 2024 03:02
Show Gist options
  • Save conartist6/1098dd2601ab944a2b8f24c4161200ee to your computer and use it in GitHub Desktop.
Save conartist6/1098dd2601ab944a2b8f24c4161200ee to your computer and use it in GitHub Desktop.
BABLR for globbing mockup (public domain)
import { test as nonbacktrackingTest } from '@bablr/regex-vm';
import * as bablrLanguage from '@bablr/language-regex-vm-pattern';
import { buildTag } from 'bablr';
import { printCSTML } from '@bablr/agast-helpers/tree';
const re = buildTag(bablrLanguage, 'Pattern');
const weakMemo = (fn) => {
const cache = new WeakMap();
return (arg) => {
if (cache.has(arg)) {
return cache.get(arg);
}
const returnValue = fn(arg);
cache.set(arg, returnValue);
return returnValue;
}
};
export const globASTToBABLRRegexCST = weakMemo((globAST) => {
switch(globAST.type) {
case 'GlobStar': return re`/.*?/`;
case 'Literal': return re.Literal([globAst[1]]);
default: throw new Error('unimplemented');
}
});
export const globPatternMightBacktrackCatastrophically = weakMemo((globPattern) => {
let globstars = 0;
// glob node iterator should assert that Object.isFrozen(node) for cacheability
for (const node of globASTIterator(globPattern)) {
if (node.type === 1) globstars++;
if (globstars === 2) break;
}
return globstars === 2;
});
export const globMatch = (globPattern, text) => {
const regexPatternTree = globASTToBABLRRegexCST(globPattern);
if (globPatternMightBacktrackCatastrophically(regexPatternTree)) {
return nonbacktrackingTest(regexPatternTree, text);
}
const printArr = (name, sep = '') => {
return patternTree.properties[name].map(node => printCSTML(node)).join(sep);
}
return new RegExp(printArr('alternatives', '|'), printArr('flags')).test(text);
}
globMatch('foo/**', 'foo/bar/abc'); // true
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment