Last active
July 23, 2024 03:02
-
-
Save conartist6/1098dd2601ab944a2b8f24c4161200ee to your computer and use it in GitHub Desktop.
BABLR for globbing mockup (public domain)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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