summaryrefslogtreecommitdiff
path: root/src/paca.mjs
diff options
context:
space:
mode:
Diffstat (limited to 'src/paca.mjs')
-rw-r--r--src/paca.mjs36
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,