diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/paca.mjs | 36 |
1 files changed, 33 insertions, 3 deletions
diff --git a/src/paca.mjs b/src/paca.mjs index 0625d5c..77a7a4b 100644 --- a/src/paca.mjs +++ b/src/paca.mjs @@ -623,14 +623,44 @@ const zeroOrOne = nfa => { }; }; +const compareRange = (lhs, rhs) => + lhs[0] !== rhs[0] ? lhs[0] - rhs[0] : lhs[1] - rhs[1]; + +const compressRangeStep = (ranges, [from, to]) => { + const curr = last(ranges); + if (!curr) { + return [[from, to]]; + } + return from <= curr[1] + ? butlast(ranges).concat([[curr[0], max(to, curr[1])]]) + : ranges.concat([[from, to]]); +}; + +const compressCharacterRanges = ranges => + ranges.toSorted(compareRange).reduce(compressRangeStep, []); + +const inRange = (ranges, char) => { + const code = char.charCodeAt(0); + const froms = Object.keys(ranges).map(Number).filter( + from => from <= code, + ); + return froms.some(from => code <= ranges[from]); +}; + const characterClass = ({ set, caret }, id) => { const start = id + 0; const end = id + 1; const nextID = id + 2; const { string, object } = Object.groupBy(set, x => typeof x); - const matches = new Set(string); - const ranges = Object.fromEntries(object.map( - ({ from, to }) => [ from.charCodeAt(0), to.charCodeAt(0) ], + const ranges = Object.fromEntries( + compressCharacterRanges((object || []).map( + ({ from, to }) => [ + from.charCodeAt(0), to.charCodeAt(0) + ], + ), + )); + const matches = new Set((string || []).filter( + char => !inRange(ranges, char), )); return { start, |
