re2js 2.8.5 → 2.8.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +94 -104
- package/build/index.cjs +940 -732
- package/build/index.d.cts +284 -226
- package/build/index.d.ts +284 -226
- package/build/index.js +940 -732
- package/build/index.umd.js +940 -732
- package/package.json +30 -24
package/build/index.cjs
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
* re2js
|
|
3
3
|
* RE2JS is the JavaScript port of RE2, a regular expression engine that provides linear time matching
|
|
4
4
|
*
|
|
5
|
-
* @version v2.8.
|
|
5
|
+
* @version v2.8.7
|
|
6
6
|
* @author Oleksii Vasyliev
|
|
7
7
|
* @homepage https://github.com/le0pard/re2js#readme
|
|
8
|
-
* @repository
|
|
8
|
+
* @repository [object Object]
|
|
9
9
|
* @license MIT
|
|
10
10
|
*/
|
|
11
11
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
@@ -500,6 +500,10 @@ var UnicodeTables = class {
|
|
|
500
500
|
*/
|
|
501
501
|
var Unicode = class Unicode {
|
|
502
502
|
static MAX_RUNE = 1114111;
|
|
503
|
+
static RUNE_ERROR = 65533;
|
|
504
|
+
static isUnsearchable(r) {
|
|
505
|
+
return r === Unicode.RUNE_ERROR || r >= Unicode.MIN_HIGH_SURROGATE && r <= Unicode.MAX_LOW_SURROGATE;
|
|
506
|
+
}
|
|
503
507
|
static MAX_ASCII = 127;
|
|
504
508
|
static MAX_LATIN1 = 255;
|
|
505
509
|
static MAX_BMP = 65535;
|
|
@@ -602,7 +606,7 @@ var Utils = class Utils {
|
|
|
602
606
|
return [];
|
|
603
607
|
}
|
|
604
608
|
static isByteArray(input) {
|
|
605
|
-
return Array.isArray(input) || input
|
|
609
|
+
return Array.isArray(input) || Object.prototype.toString.call(input) === "[object Uint8Array]";
|
|
606
610
|
}
|
|
607
611
|
static isalnum(c) {
|
|
608
612
|
return Codepoint.CODES.get("0") <= c && c <= Codepoint.CODES.get("9") || Codepoint.CODES.get("a") <= c && c <= Codepoint.CODES.get("z") || Codepoint.CODES.get("A") <= c && c <= Codepoint.CODES.get("Z");
|
|
@@ -661,7 +665,7 @@ var Utils = class Utils {
|
|
|
661
665
|
runes.push(cp);
|
|
662
666
|
i += cp > Unicode.MAX_BMP ? 2 : 1;
|
|
663
667
|
}
|
|
664
|
-
return runes;
|
|
668
|
+
return new Int32Array(runes);
|
|
665
669
|
}
|
|
666
670
|
static runeToString(r) {
|
|
667
671
|
return String.fromCodePoint(r);
|
|
@@ -708,7 +712,7 @@ var Utils = class Utils {
|
|
|
708
712
|
static stringToUtf8ByteArray(str) {
|
|
709
713
|
if (globalThis.TextEncoder) {
|
|
710
714
|
if (!cachedNativeEncoder) cachedNativeEncoder = new TextEncoder();
|
|
711
|
-
return
|
|
715
|
+
return cachedNativeEncoder.encode(str);
|
|
712
716
|
} else {
|
|
713
717
|
let out = [], p = 0;
|
|
714
718
|
for (let i = 0; i < str.length; i++) {
|
|
@@ -788,7 +792,7 @@ var MatcherInputBase = class MatcherInputBase {
|
|
|
788
792
|
asCharSequence() {
|
|
789
793
|
throw Error("not implemented");
|
|
790
794
|
}
|
|
791
|
-
/** @returns {Uint8Array|number[]} */
|
|
795
|
+
/** @returns {Uint8Array|number[]|null} */
|
|
792
796
|
asBytes() {
|
|
793
797
|
throw Error("not implemented");
|
|
794
798
|
}
|
|
@@ -919,7 +923,8 @@ var MachineInputBase = class {
|
|
|
919
923
|
return 0;
|
|
920
924
|
}
|
|
921
925
|
};
|
|
922
|
-
var MachineUTF8Input = class extends MachineInputBase {
|
|
926
|
+
var MachineUTF8Input = class MachineUTF8Input extends MachineInputBase {
|
|
927
|
+
static RUNE_ERROR_STEP = Unicode.RUNE_ERROR << 3 | 1;
|
|
923
928
|
constructor(bytes, start = 0, end = bytes.length) {
|
|
924
929
|
super();
|
|
925
930
|
this.bytes = bytes;
|
|
@@ -933,33 +938,46 @@ var MachineUTF8Input = class extends MachineInputBase {
|
|
|
933
938
|
return idx !== -1 && idx <= this.end - target.length;
|
|
934
939
|
}
|
|
935
940
|
hasAnyString(prefilter, pos) {
|
|
936
|
-
|
|
937
|
-
return prefilter.ac8.searchUTF8(this.bytes, this.start + pos, this.end);
|
|
941
|
+
return prefilter.automaton8().searchUTF8(this.bytes, this.start + pos, this.end);
|
|
938
942
|
}
|
|
939
943
|
step(pos) {
|
|
940
944
|
pos += this.start;
|
|
941
945
|
if (pos >= this.end) return MachineInputBase.EOF();
|
|
942
946
|
const c = this.bytes[pos] & 255;
|
|
943
947
|
if (c < 128) return c << 3 | 1;
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
948
|
+
let size;
|
|
949
|
+
let rune;
|
|
950
|
+
let lo = 128;
|
|
951
|
+
let hi = 191;
|
|
952
|
+
if (c >= 194 && c <= 223) {
|
|
953
|
+
size = 2;
|
|
954
|
+
rune = c & 31;
|
|
955
|
+
} else if (c >= 224 && c <= 239) {
|
|
956
|
+
size = 3;
|
|
957
|
+
rune = c & 15;
|
|
958
|
+
if (c === 224) lo = 160;
|
|
959
|
+
else if (c === 237) hi = 159;
|
|
960
|
+
} else if (c >= 240 && c <= 244) {
|
|
961
|
+
size = 4;
|
|
962
|
+
rune = c & 7;
|
|
963
|
+
if (c === 240) lo = 144;
|
|
964
|
+
else if (c === 244) hi = 143;
|
|
965
|
+
} else return MachineUTF8Input.RUNE_ERROR_STEP;
|
|
966
|
+
if (pos + size > this.end) return MachineUTF8Input.RUNE_ERROR_STEP;
|
|
967
|
+
const c1 = this.bytes[pos + 1] & 255;
|
|
968
|
+
if (c1 < lo || c1 > hi) return MachineUTF8Input.RUNE_ERROR_STEP;
|
|
969
|
+
rune = rune << 6 | c1 & 63;
|
|
970
|
+
if (size > 2) {
|
|
957
971
|
const c2 = this.bytes[pos + 2] & 255;
|
|
958
|
-
if ((c2 & 192) !== 128) return
|
|
959
|
-
|
|
960
|
-
if (
|
|
961
|
-
|
|
962
|
-
|
|
972
|
+
if ((c2 & 192) !== 128) return MachineUTF8Input.RUNE_ERROR_STEP;
|
|
973
|
+
rune = rune << 6 | c2 & 63;
|
|
974
|
+
if (size > 3) {
|
|
975
|
+
const c3 = this.bytes[pos + 3] & 255;
|
|
976
|
+
if ((c3 & 192) !== 128) return MachineUTF8Input.RUNE_ERROR_STEP;
|
|
977
|
+
rune = rune << 6 | c3 & 63;
|
|
978
|
+
}
|
|
979
|
+
}
|
|
980
|
+
return rune << 3 | size;
|
|
963
981
|
}
|
|
964
982
|
index(re2, pos) {
|
|
965
983
|
pos += this.start;
|
|
@@ -1024,8 +1042,7 @@ var MachineUTF16Input = class extends MachineInputBase {
|
|
|
1024
1042
|
return idx !== -1 && idx <= this.end - prefilter.str.length;
|
|
1025
1043
|
}
|
|
1026
1044
|
hasAnyString(prefilter, pos) {
|
|
1027
|
-
|
|
1028
|
-
return prefilter.ac16.searchUTF16(this.charSequence, this.start + pos, this.end);
|
|
1045
|
+
return prefilter.automaton16().searchUTF16(this.charSequence, this.start + pos, this.end);
|
|
1029
1046
|
}
|
|
1030
1047
|
step(pos) {
|
|
1031
1048
|
pos += this.start;
|
|
@@ -1218,6 +1235,8 @@ var Matcher = class Matcher {
|
|
|
1218
1235
|
this.namedGroups = re2.namedGroups;
|
|
1219
1236
|
/** @type {number} */
|
|
1220
1237
|
this.numberOfInstructions = re2.numberOfInstructions();
|
|
1238
|
+
/** @type {import('./Machine.js').LookbehindState|null} */
|
|
1239
|
+
this.lookbehindState = null;
|
|
1221
1240
|
if (input instanceof MatcherInputBase) this.resetMatcherInput(input);
|
|
1222
1241
|
else if (Utils.isByteArray(input)) this.resetMatcherInput(MatcherInput.utf8(input));
|
|
1223
1242
|
else this.resetMatcherInput(MatcherInput.utf16(input));
|
|
@@ -1251,9 +1270,13 @@ var Matcher = class Matcher {
|
|
|
1251
1270
|
*/
|
|
1252
1271
|
resetMatcherInput(input) {
|
|
1253
1272
|
if (input === null) throw new Error("input is null");
|
|
1254
|
-
if (!(input instanceof MatcherInputBase))
|
|
1255
|
-
|
|
1273
|
+
if (!(input instanceof MatcherInputBase)) {
|
|
1274
|
+
if (Utils.isByteArray(input)) input = MatcherInput.utf8(input);
|
|
1275
|
+
else input = MatcherInput.utf16(input);
|
|
1276
|
+
}
|
|
1256
1277
|
this.matcherInput = input;
|
|
1278
|
+
if (this.lookbehindState !== null) this.lookbehindState.reset();
|
|
1279
|
+
else this.lookbehindState = this.patternInput.re2().createLookbehindState();
|
|
1257
1280
|
this.reset();
|
|
1258
1281
|
return this;
|
|
1259
1282
|
}
|
|
@@ -1341,11 +1364,11 @@ var Matcher = class Matcher {
|
|
|
1341
1364
|
* @private
|
|
1342
1365
|
*/
|
|
1343
1366
|
loadGroup(group) {
|
|
1344
|
-
if (group < 0 || group > this.patternGroupCount) throw new RE2JSGroupException(`Group index out of bounds: ${group}`);
|
|
1367
|
+
if (!Number.isInteger(group) || group < 0 || group > this.patternGroupCount) throw new RE2JSGroupException(`Group index out of bounds: ${group}`);
|
|
1345
1368
|
if (!this.hasMatch) throw new RE2JSGroupException("perhaps no match attempted");
|
|
1346
1369
|
if (group === 0 || this.hasGroups) return;
|
|
1347
1370
|
const end = this.matcherInputLength;
|
|
1348
|
-
const res = this.patternInput.re2().matchMachineInput(this.matcherInput, this.groups[0], end, this.anchorFlag, 1 + this.patternGroupCount);
|
|
1371
|
+
const res = this.patternInput.re2().matchMachineInput(this.matcherInput, this.groups[0], end, this.anchorFlag, 1 + this.patternGroupCount, this.lookbehindState);
|
|
1349
1372
|
if (!res[0]) throw new RE2JSGroupException("inconsistency in matching group data");
|
|
1350
1373
|
this.groups = res[1];
|
|
1351
1374
|
this.hasGroups = true;
|
|
@@ -1378,7 +1401,7 @@ var Matcher = class Matcher {
|
|
|
1378
1401
|
*/
|
|
1379
1402
|
find(start = null) {
|
|
1380
1403
|
if (start !== null) {
|
|
1381
|
-
if (start < 0 || start > this.matcherInputLength) throw new RE2JSGroupException(`start index out of bounds: ${start}`);
|
|
1404
|
+
if (!Number.isInteger(start) || start < 0 || start > this.matcherInputLength) throw new RE2JSGroupException(`start index out of bounds: ${start}`);
|
|
1382
1405
|
this.reset();
|
|
1383
1406
|
return this.genMatch(start, 0);
|
|
1384
1407
|
}
|
|
@@ -1401,8 +1424,11 @@ var Matcher = class Matcher {
|
|
|
1401
1424
|
* @private
|
|
1402
1425
|
*/
|
|
1403
1426
|
genMatch(startByte, anchor) {
|
|
1404
|
-
const res = this.patternInput.re2().matchMachineInput(this.matcherInput, startByte, this.matcherInputLength, anchor, 1);
|
|
1405
|
-
if (!res[0])
|
|
1427
|
+
const res = this.patternInput.re2().matchMachineInput(this.matcherInput, startByte, this.matcherInputLength, anchor, 1, this.lookbehindState);
|
|
1428
|
+
if (!res[0]) {
|
|
1429
|
+
this.hasMatch = false;
|
|
1430
|
+
return false;
|
|
1431
|
+
}
|
|
1406
1432
|
this.groups = res[1];
|
|
1407
1433
|
this.hasMatch = true;
|
|
1408
1434
|
this.hasGroups = this.patternGroupCount === 0;
|
|
@@ -1465,43 +1491,47 @@ var Matcher = class Matcher {
|
|
|
1465
1491
|
let res = "";
|
|
1466
1492
|
let last = 0;
|
|
1467
1493
|
const m = replacement.length;
|
|
1468
|
-
|
|
1469
|
-
|
|
1494
|
+
let i = 0;
|
|
1495
|
+
while (i < m) {
|
|
1496
|
+
const cCode = replacement.codePointAt(i);
|
|
1497
|
+
if (cCode === Codepoint.CODES.get("\\")) {
|
|
1470
1498
|
if (last < i) res += replacement.substring(last, i);
|
|
1471
1499
|
i++;
|
|
1500
|
+
if (i >= m) throw new RE2JSGroupException("character to be escaped is missing");
|
|
1472
1501
|
last = i;
|
|
1502
|
+
i++;
|
|
1473
1503
|
continue;
|
|
1474
1504
|
}
|
|
1475
|
-
if (
|
|
1476
|
-
|
|
1477
|
-
if (
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1505
|
+
if (cCode === Codepoint.CODES.get("$")) {
|
|
1506
|
+
if (last < i) res += replacement.substring(last, i);
|
|
1507
|
+
if (i + 1 >= m) throw new RE2JSGroupException("Illegal group reference: group index is missing");
|
|
1508
|
+
const nextCode = replacement.codePointAt(i + 1);
|
|
1509
|
+
if (Codepoint.CODES.get("0") <= nextCode && nextCode <= Codepoint.CODES.get("9")) {
|
|
1510
|
+
let n = nextCode - Codepoint.CODES.get("0");
|
|
1511
|
+
let j = i + 2;
|
|
1512
|
+
for (; j < m; j++) {
|
|
1513
|
+
const digit = replacement.codePointAt(j);
|
|
1514
|
+
if (digit < Codepoint.CODES.get("0") || digit > Codepoint.CODES.get("9") || n * 10 + digit - Codepoint.CODES.get("0") > this.patternGroupCount) break;
|
|
1515
|
+
n = n * 10 + digit - Codepoint.CODES.get("0");
|
|
1484
1516
|
}
|
|
1485
1517
|
if (n > this.patternGroupCount) throw new RE2JSGroupException(`n > number of groups: ${n}`);
|
|
1486
1518
|
const group = this.group(n);
|
|
1487
1519
|
if (group !== null) res += group;
|
|
1520
|
+
i = j;
|
|
1488
1521
|
last = i;
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
if (
|
|
1493
|
-
i
|
|
1494
|
-
let j = i + 1;
|
|
1495
|
-
while (j < replacement.length && replacement.codePointAt(j) !== Codepoint.CODES.get("}") && replacement.codePointAt(j) !== Codepoint.CODES.get(" ")) j++;
|
|
1496
|
-
if (j === replacement.length || replacement.codePointAt(j) !== Codepoint.CODES.get("}")) throw new RE2JSGroupException("named capture group is missing trailing '}'");
|
|
1497
|
-
const groupName = replacement.substring(i + 1, j);
|
|
1522
|
+
} else if (nextCode === Codepoint.CODES.get("{")) {
|
|
1523
|
+
let j = i + 2;
|
|
1524
|
+
while (j < m && replacement.codePointAt(j) !== Codepoint.CODES.get("}")) j++;
|
|
1525
|
+
if (j >= m) throw new RE2JSGroupException("named capture group is missing trailing '}'");
|
|
1526
|
+
const groupName = replacement.substring(i + 2, j);
|
|
1498
1527
|
const groupVal = this.group(groupName);
|
|
1499
1528
|
if (groupVal !== null) res += groupVal;
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1529
|
+
i = j + 1;
|
|
1530
|
+
last = i;
|
|
1531
|
+
} else throw new RE2JSGroupException("Illegal group reference");
|
|
1532
|
+
continue;
|
|
1504
1533
|
}
|
|
1534
|
+
i++;
|
|
1505
1535
|
}
|
|
1506
1536
|
if (last < m) res += replacement.substring(last, m);
|
|
1507
1537
|
return res;
|
|
@@ -1723,7 +1753,8 @@ var Inst = class Inst {
|
|
|
1723
1753
|
this.op = op;
|
|
1724
1754
|
this.out = 0;
|
|
1725
1755
|
this.arg = 0;
|
|
1726
|
-
|
|
1756
|
+
/** @type {Int32Array} */
|
|
1757
|
+
this.runes = /* @__PURE__ */ new Int32Array(0);
|
|
1727
1758
|
/** @type {Uint32Array | number[] | null} */
|
|
1728
1759
|
this.next = null;
|
|
1729
1760
|
}
|
|
@@ -1812,18 +1843,26 @@ var Inst = class Inst {
|
|
|
1812
1843
|
};
|
|
1813
1844
|
//#endregion
|
|
1814
1845
|
//#region src/Machine.js
|
|
1815
|
-
var
|
|
1816
|
-
constructor() {
|
|
1817
|
-
this.inst = null;
|
|
1818
|
-
this.cap = null;
|
|
1819
|
-
}
|
|
1820
|
-
};
|
|
1821
|
-
var Queue = class {
|
|
1846
|
+
var Queue = class Queue {
|
|
1822
1847
|
constructor(numInst) {
|
|
1823
1848
|
this.sparse = new Int32Array(numInst);
|
|
1824
1849
|
this.densePcs = new Int32Array(numInst);
|
|
1825
|
-
this.
|
|
1850
|
+
this.denseCaps = null;
|
|
1826
1851
|
this.size = 0;
|
|
1852
|
+
this.ncap = 0;
|
|
1853
|
+
this.mainThreads = 0;
|
|
1854
|
+
}
|
|
1855
|
+
static INITIAL_THREADS = 32;
|
|
1856
|
+
init(ncap) {
|
|
1857
|
+
this.ncap = ncap;
|
|
1858
|
+
const needed = Math.min(this.densePcs.length, Queue.INITIAL_THREADS) * ncap;
|
|
1859
|
+
if (!this.denseCaps || this.denseCaps.length < needed) this.denseCaps = new Int32Array(needed);
|
|
1860
|
+
}
|
|
1861
|
+
growCaps(needed) {
|
|
1862
|
+
const limit = this.densePcs.length * this.ncap;
|
|
1863
|
+
const grown = new Int32Array(Math.min(limit, Math.max(needed, 2 * this.denseCaps.length)));
|
|
1864
|
+
grown.set(this.denseCaps);
|
|
1865
|
+
this.denseCaps = grown;
|
|
1827
1866
|
}
|
|
1828
1867
|
contains(pc) {
|
|
1829
1868
|
const j = this.sparse[pc];
|
|
@@ -1835,13 +1874,12 @@ var Queue = class {
|
|
|
1835
1874
|
add(pc) {
|
|
1836
1875
|
const j = this.size++;
|
|
1837
1876
|
this.sparse[pc] = j;
|
|
1838
|
-
this.denseThreads[j] = null;
|
|
1839
1877
|
this.densePcs[j] = pc;
|
|
1840
1878
|
return j;
|
|
1841
1879
|
}
|
|
1842
1880
|
clear() {
|
|
1843
|
-
for (let i = 0; i < this.size; i++) this.denseThreads[i] = null;
|
|
1844
1881
|
this.size = 0;
|
|
1882
|
+
this.mainThreads = 0;
|
|
1845
1883
|
}
|
|
1846
1884
|
toString() {
|
|
1847
1885
|
let out = "{";
|
|
@@ -1853,31 +1891,37 @@ var Queue = class {
|
|
|
1853
1891
|
return out;
|
|
1854
1892
|
}
|
|
1855
1893
|
};
|
|
1894
|
+
var LookbehindState = class {
|
|
1895
|
+
constructor(prog) {
|
|
1896
|
+
this.pos = -1;
|
|
1897
|
+
this.pcs = new Int32Array(prog.numInst());
|
|
1898
|
+
this.size = 0;
|
|
1899
|
+
this.lbTable = new Int32Array(prog.numLb + 1);
|
|
1900
|
+
}
|
|
1901
|
+
reset() {
|
|
1902
|
+
this.pos = -1;
|
|
1903
|
+
this.size = 0;
|
|
1904
|
+
}
|
|
1905
|
+
};
|
|
1856
1906
|
var Machine = class Machine {
|
|
1857
|
-
static THREADS_CHUNK_SIZE = 128;
|
|
1858
1907
|
static fromRE2(re2) {
|
|
1859
1908
|
const m = new Machine();
|
|
1860
1909
|
m.prog = re2.prog;
|
|
1861
1910
|
m.re2 = re2;
|
|
1862
1911
|
m.q0 = new Queue(m.prog.numInst());
|
|
1863
1912
|
m.q1 = new Queue(m.prog.numInst());
|
|
1864
|
-
m.
|
|
1865
|
-
m.poolSize = 0;
|
|
1913
|
+
m.addStack = new Int32Array(2 * (m.prog.numInst() + 1));
|
|
1866
1914
|
m.matched = false;
|
|
1867
1915
|
m.matchcap = new Int32Array(m.prog.numCap < 2 ? 2 : m.prog.numCap);
|
|
1868
1916
|
m.ncap = 0;
|
|
1869
1917
|
return m;
|
|
1870
1918
|
}
|
|
1871
|
-
static fromMachine(machine) {
|
|
1872
|
-
return Machine.fromRE2(machine.re2);
|
|
1873
|
-
}
|
|
1874
1919
|
constructor() {
|
|
1875
1920
|
this.prog = null;
|
|
1876
1921
|
this.re2 = null;
|
|
1877
1922
|
this.q0 = null;
|
|
1878
1923
|
this.q1 = null;
|
|
1879
|
-
this.
|
|
1880
|
-
this.poolSize = 0;
|
|
1924
|
+
this.addStack = null;
|
|
1881
1925
|
this.matched = false;
|
|
1882
1926
|
this.matchcap = null;
|
|
1883
1927
|
this.ncap = 0;
|
|
@@ -1885,59 +1929,36 @@ var Machine = class Machine {
|
|
|
1885
1929
|
}
|
|
1886
1930
|
init(ncap) {
|
|
1887
1931
|
this.ncap = ncap;
|
|
1888
|
-
if (ncap > this.matchcap.length) this.
|
|
1889
|
-
else this.
|
|
1932
|
+
if (ncap > this.matchcap.length) this.matchcap = new Int32Array(ncap).fill(-1);
|
|
1933
|
+
else this.matchcap.fill(-1);
|
|
1934
|
+
this.q0.init(ncap);
|
|
1935
|
+
this.q1.init(ncap);
|
|
1890
1936
|
if (this.prog.numLb > 0) {
|
|
1891
1937
|
if (!this.lbTable || this.lbTable.length < this.prog.numLb + 1) this.lbTable = new Int32Array(this.prog.numLb + 1);
|
|
1892
1938
|
this.lbTable.fill(-1);
|
|
1893
1939
|
}
|
|
1894
1940
|
}
|
|
1895
|
-
resetCap() {
|
|
1896
|
-
for (let i = 0; i < this.poolSize; i++) this.pool[i].cap.fill(-1);
|
|
1897
|
-
}
|
|
1898
|
-
initNewCap(ncap) {
|
|
1899
|
-
for (let i = 0; i < this.poolSize; i++) {
|
|
1900
|
-
const t = this.pool[i];
|
|
1901
|
-
t.cap = new Int32Array(ncap).fill(-1);
|
|
1902
|
-
}
|
|
1903
|
-
this.matchcap = new Int32Array(ncap).fill(-1);
|
|
1904
|
-
}
|
|
1905
1941
|
submatches() {
|
|
1906
1942
|
if (this.ncap === 0) return Utils.emptyInts();
|
|
1907
1943
|
return Utils.toArray(this.matchcap.subarray(0, this.ncap));
|
|
1908
1944
|
}
|
|
1909
|
-
|
|
1910
|
-
if (this.poolSize === 0) {
|
|
1911
|
-
const capLen = this.matchcap.length;
|
|
1912
|
-
for (let i = 0; i < Machine.THREADS_CHUNK_SIZE; i++) {
|
|
1913
|
-
const t = new Thread();
|
|
1914
|
-
t.cap = new Int32Array(capLen);
|
|
1915
|
-
this.pool[this.poolSize++] = t;
|
|
1916
|
-
}
|
|
1917
|
-
}
|
|
1918
|
-
this.poolSize--;
|
|
1919
|
-
const t = this.pool[this.poolSize];
|
|
1920
|
-
t.inst = inst;
|
|
1921
|
-
return t;
|
|
1922
|
-
}
|
|
1923
|
-
freeQueue(queue, from = 0) {
|
|
1924
|
-
for (let i = from; i < queue.size; i++) {
|
|
1925
|
-
const t = queue.denseThreads[i];
|
|
1926
|
-
if (t !== null) this.pool[this.poolSize++] = t;
|
|
1927
|
-
}
|
|
1928
|
-
queue.clear();
|
|
1929
|
-
}
|
|
1930
|
-
freeThread(t) {
|
|
1931
|
-
this.pool[this.poolSize++] = t;
|
|
1932
|
-
}
|
|
1933
|
-
match(input, pos, anchor) {
|
|
1945
|
+
match(input, pos, anchor, lbState = null) {
|
|
1934
1946
|
const startCond = this.re2.cond;
|
|
1935
1947
|
if (startCond === Utils.EMPTY_ALL) return false;
|
|
1936
1948
|
if ((anchor === RE2Flags.ANCHOR_START || anchor === RE2Flags.ANCHOR_BOTH) && pos !== 0) return false;
|
|
1937
1949
|
this.matched = false;
|
|
1938
1950
|
this.matchcap.fill(-1);
|
|
1939
|
-
|
|
1940
|
-
|
|
1951
|
+
const hasLookbehinds = this.prog.numLb > 0;
|
|
1952
|
+
const matchStartPos = pos;
|
|
1953
|
+
let currentPos = pos;
|
|
1954
|
+
let resumeLookbehinds = false;
|
|
1955
|
+
if (hasLookbehinds) {
|
|
1956
|
+
if (lbState !== null && lbState.pos >= 0 && lbState.pos <= pos) {
|
|
1957
|
+
currentPos = lbState.pos;
|
|
1958
|
+
resumeLookbehinds = true;
|
|
1959
|
+
} else currentPos = 0;
|
|
1960
|
+
}
|
|
1961
|
+
let saveLookbehinds = hasLookbehinds && lbState !== null;
|
|
1941
1962
|
let runq = this.q0;
|
|
1942
1963
|
let nextq = this.q1;
|
|
1943
1964
|
let r = input.step(currentPos);
|
|
@@ -1953,12 +1974,16 @@ var Machine = class Machine {
|
|
|
1953
1974
|
let flag;
|
|
1954
1975
|
if (currentPos === 0) flag = Utils.emptyOpContext(-1, rune);
|
|
1955
1976
|
else flag = input.context(currentPos);
|
|
1977
|
+
if (hasLookbehinds) {
|
|
1978
|
+
if (resumeLookbehinds) this.restoreLookbehinds(lbState, runq, flag);
|
|
1979
|
+
else this.spawnLookbehinds(runq, currentPos, flag);
|
|
1980
|
+
}
|
|
1956
1981
|
while (true) {
|
|
1957
|
-
if (runq.
|
|
1982
|
+
if (runq.mainThreads === 0) {
|
|
1958
1983
|
if ((startCond & Utils.EMPTY_BEGIN_TEXT) !== 0 && currentPos !== 0) break;
|
|
1959
1984
|
if ((anchor === RE2Flags.ANCHOR_START || anchor === RE2Flags.ANCHOR_BOTH) && currentPos !== 0) break;
|
|
1960
1985
|
if (this.matched) break;
|
|
1961
|
-
if (this.prog.numLb === 0 && !(this.re2.prefix.length === 0) && rune1 !== this.re2.prefixRune && input.canCheckPrefix()) {
|
|
1986
|
+
if (this.prog.numLb === 0 && runq.isEmpty() && !(this.re2.prefix.length === 0) && rune1 !== this.re2.prefixRune && input.canCheckPrefix()) {
|
|
1962
1987
|
const advance = input.index(this.re2, currentPos);
|
|
1963
1988
|
if (advance < 0) break;
|
|
1964
1989
|
currentPos += advance;
|
|
@@ -1968,13 +1993,17 @@ var Machine = class Machine {
|
|
|
1968
1993
|
r = input.step(currentPos + width);
|
|
1969
1994
|
rune1 = r >> 3;
|
|
1970
1995
|
width1 = r & 7;
|
|
1996
|
+
flag = input.context(currentPos);
|
|
1971
1997
|
}
|
|
1972
1998
|
}
|
|
1973
|
-
if (currentPos
|
|
1974
|
-
|
|
1975
|
-
|
|
1999
|
+
if (currentPos >= matchStartPos) {
|
|
2000
|
+
if (saveLookbehinds) {
|
|
2001
|
+
this.saveLookbehinds(lbState, runq, currentPos);
|
|
2002
|
+
saveLookbehinds = false;
|
|
2003
|
+
}
|
|
2004
|
+
if (!this.matched && (currentPos === 0 || anchor === RE2Flags.UNANCHORED)) {
|
|
1976
2005
|
if (this.ncap > 0) this.matchcap[0] = currentPos;
|
|
1977
|
-
this.add(runq, this.prog.start, currentPos, this.matchcap,
|
|
2006
|
+
this.add(runq, this.prog.start, currentPos, this.matchcap, 0, flag);
|
|
1978
2007
|
}
|
|
1979
2008
|
}
|
|
1980
2009
|
const nextPos = currentPos + width;
|
|
@@ -1994,7 +2023,8 @@ var Machine = class Machine {
|
|
|
1994
2023
|
runq = nextq;
|
|
1995
2024
|
nextq = tmpq;
|
|
1996
2025
|
}
|
|
1997
|
-
|
|
2026
|
+
runq.clear();
|
|
2027
|
+
nextq.clear();
|
|
1998
2028
|
return this.matched;
|
|
1999
2029
|
}
|
|
2000
2030
|
matchSet(input, pos, anchor) {
|
|
@@ -2017,21 +2047,21 @@ var Machine = class Machine {
|
|
|
2017
2047
|
}
|
|
2018
2048
|
let flag = currentPos === 0 ? Utils.emptyOpContext(-1, rune) : input.context(currentPos);
|
|
2019
2049
|
const matches = /* @__PURE__ */ new Set();
|
|
2050
|
+
if (this.prog.numLb > 0) this.spawnLookbehinds(runq, currentPos, flag);
|
|
2020
2051
|
while (true) {
|
|
2021
|
-
if (runq.
|
|
2052
|
+
if (runq.mainThreads === 0) {
|
|
2022
2053
|
if ((startCond & Utils.EMPTY_BEGIN_TEXT) !== 0 && currentPos !== 0) break;
|
|
2023
2054
|
if ((anchor === RE2Flags.ANCHOR_START || anchor === RE2Flags.ANCHOR_BOTH) && currentPos !== 0) break;
|
|
2024
2055
|
}
|
|
2025
|
-
if (currentPos === 0 && this.prog.numLb > 0) for (let i = 0; i < this.prog.lbStarts.length; i++) this.add(runq, this.prog.lbStarts[i], currentPos, this.matchcap, flag, null);
|
|
2026
2056
|
if (currentPos === 0 || anchor === RE2Flags.UNANCHORED) {
|
|
2027
|
-
if (currentPos >= matchStartPos) this.add(runq, this.prog.start, currentPos, this.matchcap,
|
|
2057
|
+
if (currentPos >= matchStartPos) this.add(runq, this.prog.start, currentPos, this.matchcap, 0, flag);
|
|
2028
2058
|
}
|
|
2029
2059
|
const nextPos = currentPos + width;
|
|
2030
2060
|
flag = input.context(nextPos);
|
|
2031
2061
|
for (let j = 0; j < runq.size; j++) {
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
const
|
|
2062
|
+
const pc = runq.densePcs[j];
|
|
2063
|
+
const i = this.prog.inst[pc];
|
|
2064
|
+
const capOffset = j * this.ncap;
|
|
2035
2065
|
let add = false;
|
|
2036
2066
|
switch (i.op) {
|
|
2037
2067
|
case Inst.MATCH:
|
|
@@ -2048,15 +2078,11 @@ var Machine = class Machine {
|
|
|
2048
2078
|
add = true;
|
|
2049
2079
|
break;
|
|
2050
2080
|
case Inst.RUNE_ANY_NOT_NL:
|
|
2051
|
-
add = rune !==
|
|
2081
|
+
add = rune !== 10;
|
|
2052
2082
|
break;
|
|
2053
|
-
default:
|
|
2054
|
-
}
|
|
2055
|
-
if (add) t = this.add(nextq, i.out, nextPos, t.cap, flag, t);
|
|
2056
|
-
if (t !== null) {
|
|
2057
|
-
this.freeThread(t);
|
|
2058
|
-
runq.denseThreads[j] = null;
|
|
2083
|
+
default: continue;
|
|
2059
2084
|
}
|
|
2085
|
+
if (add) this.add(nextq, i.out, nextPos, runq.denseCaps, capOffset, flag);
|
|
2060
2086
|
}
|
|
2061
2087
|
runq.clear();
|
|
2062
2088
|
if (width === 0) break;
|
|
@@ -2072,28 +2098,25 @@ var Machine = class Machine {
|
|
|
2072
2098
|
runq = nextq;
|
|
2073
2099
|
nextq = tmpq;
|
|
2074
2100
|
}
|
|
2075
|
-
|
|
2101
|
+
nextq.clear();
|
|
2076
2102
|
return Array.from(matches).sort((a, b) => a - b);
|
|
2077
2103
|
}
|
|
2078
2104
|
step(runq, nextq, pos, nextPos, c, nextCond, anchor, atEnd) {
|
|
2079
2105
|
const longest = this.re2.longest;
|
|
2080
2106
|
for (let j = 0; j < runq.size; j++) {
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
if (longest && this.matched && this.ncap > 0 && this.matchcap[0] <
|
|
2084
|
-
|
|
2085
|
-
continue;
|
|
2086
|
-
}
|
|
2087
|
-
const i = t.inst;
|
|
2107
|
+
const pc = runq.densePcs[j];
|
|
2108
|
+
const capOffset = j * this.ncap;
|
|
2109
|
+
if (longest && this.matched && this.ncap > 0 && this.matchcap[0] < runq.denseCaps[capOffset]) continue;
|
|
2110
|
+
const i = this.prog.inst[pc];
|
|
2088
2111
|
let add = false;
|
|
2089
2112
|
switch (i.op) {
|
|
2090
2113
|
case Inst.MATCH:
|
|
2091
2114
|
if (anchor === RE2Flags.ANCHOR_BOTH && !atEnd) break;
|
|
2092
2115
|
if (this.ncap > 0 && (!longest || !this.matched || this.matchcap[1] < pos)) {
|
|
2093
|
-
|
|
2094
|
-
|
|
2116
|
+
runq.denseCaps[capOffset + 1] = pos;
|
|
2117
|
+
for (let k = 0; k < this.ncap; k++) this.matchcap[k] = runq.denseCaps[capOffset + k];
|
|
2095
2118
|
}
|
|
2096
|
-
if (!longest)
|
|
2119
|
+
if (!longest) runq.size = 0;
|
|
2097
2120
|
this.matched = true;
|
|
2098
2121
|
break;
|
|
2099
2122
|
case Inst.RUNE:
|
|
@@ -2106,78 +2129,93 @@ var Machine = class Machine {
|
|
|
2106
2129
|
add = true;
|
|
2107
2130
|
break;
|
|
2108
2131
|
case Inst.RUNE_ANY_NOT_NL:
|
|
2109
|
-
add = c !==
|
|
2132
|
+
add = c !== 10;
|
|
2110
2133
|
break;
|
|
2111
|
-
default:
|
|
2112
|
-
}
|
|
2113
|
-
if (add) t = this.add(nextq, i.out, nextPos, t.cap, nextCond, t);
|
|
2114
|
-
if (t !== null) {
|
|
2115
|
-
this.freeThread(t);
|
|
2116
|
-
runq.denseThreads[j] = null;
|
|
2134
|
+
default: continue;
|
|
2117
2135
|
}
|
|
2136
|
+
if (add) this.add(nextq, i.out, nextPos, runq.denseCaps, capOffset, nextCond);
|
|
2118
2137
|
}
|
|
2119
2138
|
runq.clear();
|
|
2120
2139
|
}
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2140
|
+
spawnLookbehinds(q, pos, flag) {
|
|
2141
|
+
for (let i = 0; i < this.prog.lbStarts.length; i++) this.add(q, this.prog.lbStarts[i], pos, this.matchcap, 0, flag);
|
|
2142
|
+
}
|
|
2143
|
+
restoreLookbehinds(lbState, q, flag) {
|
|
2144
|
+
this.lbTable.set(lbState.lbTable);
|
|
2145
|
+
for (let j = 0; j < lbState.size; j++) this.add(q, lbState.pcs[j], lbState.pos, this.matchcap, 0, flag);
|
|
2146
|
+
}
|
|
2147
|
+
saveLookbehinds(lbState, q, pos) {
|
|
2148
|
+
let size = 0;
|
|
2149
|
+
for (let j = 0; j < q.size; j++) {
|
|
2150
|
+
const pc = q.densePcs[j];
|
|
2151
|
+
if (this.prog.lbInst[pc] === 1 && Inst.isRuneOp(this.prog.inst[pc].op)) lbState.pcs[size++] = pc;
|
|
2152
|
+
}
|
|
2153
|
+
lbState.size = size;
|
|
2154
|
+
lbState.pos = pos;
|
|
2155
|
+
lbState.lbTable.set(this.lbTable);
|
|
2156
|
+
}
|
|
2157
|
+
add(q, pc, pos, capArray, capOffset, cond) {
|
|
2158
|
+
const stk = this.addStack;
|
|
2159
|
+
let nstk = 0;
|
|
2160
|
+
for (;;) {
|
|
2161
|
+
while (pc !== 0 && !q.contains(pc)) {
|
|
2162
|
+
const d = q.add(pc);
|
|
2163
|
+
const inst = this.prog.inst[pc];
|
|
2164
|
+
switch (inst.op) {
|
|
2165
|
+
case Inst.FAIL:
|
|
2166
|
+
pc = 0;
|
|
2167
|
+
break;
|
|
2168
|
+
case Inst.ALT:
|
|
2169
|
+
case Inst.ALT_MATCH:
|
|
2170
|
+
stk[nstk++] = inst.arg;
|
|
2171
|
+
stk[nstk++] = 0;
|
|
2136
2172
|
pc = inst.out;
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
} else {
|
|
2150
|
-
pc = inst.out;
|
|
2151
|
-
continue;
|
|
2152
|
-
}
|
|
2153
|
-
case Inst.LB_WRITE:
|
|
2154
|
-
this.lbTable[Math.abs(inst.arg)] = pos;
|
|
2155
|
-
pc = inst.out;
|
|
2156
|
-
continue;
|
|
2157
|
-
case Inst.LB_CHECK:
|
|
2158
|
-
if (inst.arg > 0) {
|
|
2159
|
-
if (this.lbTable[inst.arg] === pos) {
|
|
2160
|
-
pc = inst.out;
|
|
2161
|
-
continue;
|
|
2173
|
+
break;
|
|
2174
|
+
case Inst.EMPTY_WIDTH:
|
|
2175
|
+
pc = (inst.arg & ~cond) === 0 ? inst.out : 0;
|
|
2176
|
+
break;
|
|
2177
|
+
case Inst.NOP:
|
|
2178
|
+
pc = inst.out;
|
|
2179
|
+
break;
|
|
2180
|
+
case Inst.CAPTURE:
|
|
2181
|
+
if (inst.arg < this.ncap) {
|
|
2182
|
+
stk[nstk++] = -inst.arg - 1;
|
|
2183
|
+
stk[nstk++] = capArray[capOffset + inst.arg];
|
|
2184
|
+
capArray[capOffset + inst.arg] = pos;
|
|
2162
2185
|
}
|
|
2163
|
-
} else if (this.lbTable[-inst.arg] !== pos) {
|
|
2164
2186
|
pc = inst.out;
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2187
|
+
break;
|
|
2188
|
+
case Inst.LB_WRITE:
|
|
2189
|
+
this.lbTable[Math.abs(inst.arg)] = pos;
|
|
2190
|
+
pc = inst.out;
|
|
2191
|
+
break;
|
|
2192
|
+
case Inst.LB_CHECK:
|
|
2193
|
+
if (inst.arg > 0) pc = this.lbTable[inst.arg] === pos ? inst.out : 0;
|
|
2194
|
+
else pc = this.lbTable[-inst.arg] !== pos ? inst.out : 0;
|
|
2195
|
+
break;
|
|
2196
|
+
case Inst.MATCH:
|
|
2197
|
+
case Inst.RUNE:
|
|
2198
|
+
case Inst.RUNE1:
|
|
2199
|
+
case Inst.RUNE_ANY:
|
|
2200
|
+
case Inst.RUNE_ANY_NOT_NL:
|
|
2201
|
+
if (this.prog.lbInst[pc] === 0) q.mainThreads++;
|
|
2202
|
+
if (this.ncap > 0) {
|
|
2203
|
+
const destOffset = d * this.ncap;
|
|
2204
|
+
if (destOffset + this.ncap > q.denseCaps.length) q.growCaps(destOffset + this.ncap);
|
|
2205
|
+
for (let c = 0; c < this.ncap; c++) q.denseCaps[destOffset + c] = capArray[capOffset + c];
|
|
2206
|
+
}
|
|
2207
|
+
pc = 0;
|
|
2208
|
+
break;
|
|
2209
|
+
default: throw new RE2JSInternalException("unhandled");
|
|
2210
|
+
}
|
|
2180
2211
|
}
|
|
2212
|
+
if (nstk === 0) return;
|
|
2213
|
+
nstk -= 2;
|
|
2214
|
+
const entry = stk[nstk];
|
|
2215
|
+
if (entry < 0) {
|
|
2216
|
+
capArray[capOffset - entry - 1] = stk[nstk + 1];
|
|
2217
|
+
pc = 0;
|
|
2218
|
+
} else pc = entry;
|
|
2181
2219
|
}
|
|
2182
2220
|
}
|
|
2183
2221
|
};
|
|
@@ -2197,35 +2235,85 @@ const arraysEqual = (a, b) => {
|
|
|
2197
2235
|
return true;
|
|
2198
2236
|
};
|
|
2199
2237
|
var DFAState = class {
|
|
2200
|
-
constructor(nfaStates, isMatch, matchIDs
|
|
2238
|
+
constructor(nfaStates, isMatch, matchIDs) {
|
|
2201
2239
|
this.nfaStates = nfaStates;
|
|
2202
2240
|
this.isMatch = isMatch;
|
|
2203
2241
|
this.matchIDs = matchIDs;
|
|
2204
|
-
this.
|
|
2205
|
-
this.
|
|
2206
|
-
this.transKeys = [];
|
|
2207
|
-
this.transVals = [];
|
|
2208
|
-
this.lastSeen = 0;
|
|
2242
|
+
this.next = null;
|
|
2243
|
+
this.nextAnchored = null;
|
|
2209
2244
|
}
|
|
2210
2245
|
};
|
|
2211
2246
|
var DFA = class DFA {
|
|
2212
|
-
static
|
|
2213
|
-
static
|
|
2247
|
+
static STATE_OVERHEAD = 160;
|
|
2248
|
+
static TABLE_OVERHEAD = 16;
|
|
2249
|
+
static PROGRESS_PER_STATE = 10;
|
|
2214
2250
|
constructor(prog, maxMem = 8388608) {
|
|
2215
2251
|
this.prog = prog;
|
|
2252
|
+
this.maxMem = maxMem;
|
|
2216
2253
|
this.stateCache = /* @__PURE__ */ new Map();
|
|
2217
2254
|
this.stateCount = 0;
|
|
2218
2255
|
this.startState = null;
|
|
2219
|
-
this.stateLimit = Math.max(1, Math.floor(maxMem / DFA.STATE_MEMORY_ESTIMATE));
|
|
2220
|
-
this.cacheClears = 0;
|
|
2221
2256
|
this.failed = false;
|
|
2222
|
-
|
|
2257
|
+
for (let pc = 0; pc < prog.numInst(); pc++) {
|
|
2258
|
+
const op = prog.getInst(pc).op;
|
|
2259
|
+
if (op === Inst.EMPTY_WIDTH || op === Inst.LB_WRITE || op === Inst.LB_CHECK) {
|
|
2260
|
+
this.failed = true;
|
|
2261
|
+
break;
|
|
2262
|
+
}
|
|
2263
|
+
}
|
|
2264
|
+
this.computeRuneClasses();
|
|
2265
|
+
this.stateBudget = maxMem;
|
|
2266
|
+
this.memBudget = maxMem;
|
|
2267
|
+
}
|
|
2268
|
+
computeRuneClasses() {
|
|
2269
|
+
const bounds = /* @__PURE__ */ new Set();
|
|
2270
|
+
const addRune = (r) => {
|
|
2271
|
+
bounds.add(r);
|
|
2272
|
+
bounds.add(r + 1);
|
|
2273
|
+
};
|
|
2274
|
+
for (let pc = 0; pc < this.prog.numInst(); pc++) {
|
|
2275
|
+
const inst = this.prog.getInst(pc);
|
|
2276
|
+
switch (inst.op) {
|
|
2277
|
+
case Inst.RUNE:
|
|
2278
|
+
case Inst.RUNE1:
|
|
2279
|
+
if (inst.runes.length === 1) {
|
|
2280
|
+
addRune(inst.runes[0]);
|
|
2281
|
+
if ((inst.arg & RE2Flags.FOLD_CASE) !== 0) for (let f = Unicode.simpleFold(inst.runes[0]); f !== inst.runes[0]; f = Unicode.simpleFold(f)) addRune(f);
|
|
2282
|
+
} else for (let j = 0; j < inst.runes.length; j += 2) {
|
|
2283
|
+
bounds.add(inst.runes[j]);
|
|
2284
|
+
bounds.add(inst.runes[j + 1] + 1);
|
|
2285
|
+
}
|
|
2286
|
+
break;
|
|
2287
|
+
case Inst.RUNE_ANY_NOT_NL: addRune(10);
|
|
2288
|
+
}
|
|
2289
|
+
}
|
|
2290
|
+
bounds.delete(0);
|
|
2291
|
+
this.classBounds = Int32Array.from(bounds).sort();
|
|
2292
|
+
this.numClasses = this.classBounds.length + 1;
|
|
2293
|
+
const latin1Class = new Int32Array(Unicode.MAX_LATIN1 + 1);
|
|
2294
|
+
for (let r = 0; r <= Unicode.MAX_LATIN1; r++) latin1Class[r] = this.searchClass(r);
|
|
2295
|
+
this.latin1Class = latin1Class;
|
|
2296
|
+
}
|
|
2297
|
+
runeClass(r) {
|
|
2298
|
+
if (r <= Unicode.MAX_LATIN1) return this.latin1Class[r];
|
|
2299
|
+
return this.searchClass(r);
|
|
2300
|
+
}
|
|
2301
|
+
searchClass(r) {
|
|
2302
|
+
const bounds = this.classBounds;
|
|
2303
|
+
let lo = 0;
|
|
2304
|
+
let hi = bounds.length;
|
|
2305
|
+
while (lo < hi) {
|
|
2306
|
+
const mid = lo + hi >> 1;
|
|
2307
|
+
if (bounds[mid] <= r) lo = mid + 1;
|
|
2308
|
+
else hi = mid;
|
|
2309
|
+
}
|
|
2310
|
+
return lo;
|
|
2223
2311
|
}
|
|
2224
2312
|
computeClosure(pcs) {
|
|
2225
2313
|
const closure = /* @__PURE__ */ new Set();
|
|
2226
2314
|
const stack = [...pcs];
|
|
2227
2315
|
let isMatch = false;
|
|
2228
|
-
const matchIDs =
|
|
2316
|
+
const matchIDs = /* @__PURE__ */ new Set();
|
|
2229
2317
|
while (stack.length > 0) {
|
|
2230
2318
|
const pc = stack.pop();
|
|
2231
2319
|
if (closure.has(pc)) continue;
|
|
@@ -2234,7 +2322,7 @@ var DFA = class DFA {
|
|
|
2234
2322
|
switch (inst.op) {
|
|
2235
2323
|
case Inst.MATCH:
|
|
2236
2324
|
isMatch = true;
|
|
2237
|
-
|
|
2325
|
+
matchIDs.add(inst.arg);
|
|
2238
2326
|
break;
|
|
2239
2327
|
case Inst.ALT:
|
|
2240
2328
|
case Inst.ALT_MATCH:
|
|
@@ -2251,11 +2339,11 @@ var DFA = class DFA {
|
|
|
2251
2339
|
}
|
|
2252
2340
|
}
|
|
2253
2341
|
const sortedPCs = Int32Array.from(closure).sort();
|
|
2254
|
-
matchIDs.sort((a, b) => a - b);
|
|
2342
|
+
const ids = Array.from(matchIDs).sort((a, b) => a - b);
|
|
2255
2343
|
return {
|
|
2256
2344
|
pcs: sortedPCs,
|
|
2257
2345
|
isMatch,
|
|
2258
|
-
matchIDs
|
|
2346
|
+
matchIDs: ids
|
|
2259
2347
|
};
|
|
2260
2348
|
}
|
|
2261
2349
|
getState(pcs) {
|
|
@@ -2266,156 +2354,126 @@ var DFA = class DFA {
|
|
|
2266
2354
|
let bucket = this.stateCache.get(hash);
|
|
2267
2355
|
if (bucket) for (let i = 0; i < bucket.length; i++) {
|
|
2268
2356
|
const state = bucket[i];
|
|
2269
|
-
if (arraysEqual(state.nfaStates, sortedPCs))
|
|
2270
|
-
state.lastSeen = ++this.clock;
|
|
2271
|
-
return state;
|
|
2272
|
-
}
|
|
2357
|
+
if (arraysEqual(state.nfaStates, sortedPCs)) return state;
|
|
2273
2358
|
}
|
|
2274
|
-
|
|
2359
|
+
const cost = DFA.STATE_OVERHEAD + 4 * sortedPCs.length + 8 * closureResult.matchIDs.length;
|
|
2360
|
+
if (this.memBudget < cost) return null;
|
|
2361
|
+
this.memBudget -= cost;
|
|
2362
|
+
if (!bucket) {
|
|
2275
2363
|
bucket = [];
|
|
2276
2364
|
this.stateCache.set(hash, bucket);
|
|
2277
2365
|
}
|
|
2278
|
-
if (this.failed) return null;
|
|
2279
|
-
if (this.stateCount >= this.stateLimit) {
|
|
2280
|
-
this.cacheClears++;
|
|
2281
|
-
if (this.cacheClears >= DFA.MAX_CACHE_CLEARS) {
|
|
2282
|
-
this.failed = true;
|
|
2283
|
-
this.stateCache.clear();
|
|
2284
|
-
this.stateCount = 0;
|
|
2285
|
-
this.startState = null;
|
|
2286
|
-
return null;
|
|
2287
|
-
}
|
|
2288
|
-
this.evictCache();
|
|
2289
|
-
bucket = this.stateCache.get(hash);
|
|
2290
|
-
if (!bucket) {
|
|
2291
|
-
bucket = [];
|
|
2292
|
-
this.stateCache.set(hash, bucket);
|
|
2293
|
-
}
|
|
2294
|
-
}
|
|
2295
2366
|
const state = new DFAState(sortedPCs, closureResult.isMatch, closureResult.matchIDs);
|
|
2296
|
-
state.lastSeen = ++this.clock;
|
|
2297
2367
|
bucket.push(state);
|
|
2298
2368
|
this.stateCount++;
|
|
2299
2369
|
return state;
|
|
2300
2370
|
}
|
|
2301
|
-
|
|
2302
|
-
const
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
const
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2371
|
+
allocTable(state, anchor) {
|
|
2372
|
+
const cost = DFA.TABLE_OVERHEAD + 8 * this.numClasses;
|
|
2373
|
+
if (this.memBudget < cost) return null;
|
|
2374
|
+
this.memBudget -= cost;
|
|
2375
|
+
const table = new Array(this.numClasses).fill(null);
|
|
2376
|
+
if (anchor === RE2Flags.UNANCHORED) state.next = table;
|
|
2377
|
+
else state.nextAnchored = table;
|
|
2378
|
+
return table;
|
|
2379
|
+
}
|
|
2380
|
+
clearCache() {
|
|
2309
2381
|
this.stateCache.clear();
|
|
2310
2382
|
this.stateCount = 0;
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
const hash = hashPCs(state.nfaStates);
|
|
2318
|
-
let bucket = this.stateCache.get(hash);
|
|
2319
|
-
if (!bucket) {
|
|
2320
|
-
bucket = [];
|
|
2321
|
-
this.stateCache.set(hash, bucket);
|
|
2322
|
-
}
|
|
2323
|
-
bucket.push(state);
|
|
2324
|
-
this.stateCount++;
|
|
2325
|
-
}
|
|
2326
|
-
if (this.startState && !survivors.has(this.startState)) this.startState = null;
|
|
2383
|
+
this.startState = null;
|
|
2384
|
+
this.memBudget = this.stateBudget;
|
|
2385
|
+
}
|
|
2386
|
+
resetCache(current) {
|
|
2387
|
+
this.clearCache();
|
|
2388
|
+
return this.getState(current.nfaStates);
|
|
2327
2389
|
}
|
|
2328
|
-
step(state,
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2390
|
+
step(state, cls, rune, anchor) {
|
|
2391
|
+
let table = anchor === RE2Flags.UNANCHORED ? state.next : state.nextAnchored;
|
|
2392
|
+
if (table !== null) {
|
|
2393
|
+
const cached = table[cls];
|
|
2394
|
+
if (cached !== null) return cached;
|
|
2332
2395
|
} else {
|
|
2333
|
-
|
|
2334
|
-
if (
|
|
2335
|
-
}
|
|
2336
|
-
else {
|
|
2337
|
-
const key = charCode + (anchor === RE2Flags.UNANCHORED ? 0 : Unicode.MAX_RUNE + 1);
|
|
2338
|
-
const keys = state.transKeys;
|
|
2339
|
-
const len = keys.length;
|
|
2340
|
-
for (let i = 0; i < len; i++) if (keys[i] === key) return state.transVals[i];
|
|
2396
|
+
table = this.allocTable(state, anchor);
|
|
2397
|
+
if (table === null) return null;
|
|
2341
2398
|
}
|
|
2342
2399
|
const nextPCs = [];
|
|
2343
2400
|
for (let i = 0; i < state.nfaStates.length; i++) {
|
|
2344
2401
|
const pc = state.nfaStates[i];
|
|
2345
2402
|
const inst = this.prog.getInst(pc);
|
|
2346
|
-
if (Inst.isRuneOp(inst.op) && inst.matchRune(
|
|
2403
|
+
if (Inst.isRuneOp(inst.op) && inst.matchRune(rune)) nextPCs.push(inst.out);
|
|
2347
2404
|
}
|
|
2348
2405
|
if (anchor === RE2Flags.UNANCHORED) nextPCs.push(this.prog.start);
|
|
2349
2406
|
const nextState = this.getState(nextPCs);
|
|
2350
|
-
if (
|
|
2351
|
-
|
|
2352
|
-
else {
|
|
2353
|
-
const key = charCode + (anchor === RE2Flags.UNANCHORED ? 0 : Unicode.MAX_RUNE + 1);
|
|
2354
|
-
state.transKeys.push(key);
|
|
2355
|
-
state.transVals.push(nextState);
|
|
2356
|
-
}
|
|
2407
|
+
if (nextState === null) return null;
|
|
2408
|
+
table[cls] = nextState;
|
|
2357
2409
|
return nextState;
|
|
2358
2410
|
}
|
|
2359
|
-
|
|
2360
|
-
if (
|
|
2361
|
-
if (!this.startState) {
|
|
2411
|
+
start() {
|
|
2412
|
+
if (this.startState === null) {
|
|
2362
2413
|
this.startState = this.getState([this.prog.start]);
|
|
2363
|
-
if (
|
|
2414
|
+
if (this.startState === null && !this.failed) {
|
|
2415
|
+
this.clearCache();
|
|
2416
|
+
this.startState = this.getState([this.prog.start]);
|
|
2417
|
+
}
|
|
2364
2418
|
}
|
|
2365
|
-
|
|
2366
|
-
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
|
|
2419
|
+
return this.startState;
|
|
2420
|
+
}
|
|
2421
|
+
run(input, pos, anchor, state, onState, noMatch) {
|
|
2422
|
+
const endPos = input.endPos();
|
|
2423
|
+
const latin1Class = this.latin1Class;
|
|
2424
|
+
let resetPos = -1;
|
|
2370
2425
|
let i = pos;
|
|
2371
2426
|
while (i < endPos) {
|
|
2372
2427
|
const r = input.step(i);
|
|
2373
2428
|
const rune = r >> 3;
|
|
2374
2429
|
const width = r & 7;
|
|
2375
2430
|
if (width === 0) break;
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
|
|
2379
|
-
|
|
2380
|
-
if (
|
|
2381
|
-
|
|
2382
|
-
|
|
2383
|
-
|
|
2431
|
+
const cls = rune <= Unicode.MAX_LATIN1 ? latin1Class[rune] : this.runeClass(rune);
|
|
2432
|
+
let next = anchor === RE2Flags.UNANCHORED && state.next !== null ? state.next[cls] : null;
|
|
2433
|
+
if (next === null) {
|
|
2434
|
+
next = this.step(state, cls, rune, anchor);
|
|
2435
|
+
if (next === null) {
|
|
2436
|
+
if (resetPos >= 0 && i - resetPos < DFA.PROGRESS_PER_STATE * this.stateCount) return null;
|
|
2437
|
+
resetPos = i;
|
|
2438
|
+
state = this.resetCache(state);
|
|
2439
|
+
if (state === null) return null;
|
|
2440
|
+
next = this.step(state, cls, rune, anchor);
|
|
2441
|
+
if (next === null) return null;
|
|
2442
|
+
}
|
|
2384
2443
|
}
|
|
2444
|
+
state = next;
|
|
2385
2445
|
i += width;
|
|
2446
|
+
const result = onState(state, i);
|
|
2447
|
+
if (result !== null) return result;
|
|
2448
|
+
if (state.nfaStates.length === 0 && anchor !== RE2Flags.UNANCHORED) return noMatch;
|
|
2386
2449
|
}
|
|
2387
|
-
return
|
|
2450
|
+
return noMatch;
|
|
2451
|
+
}
|
|
2452
|
+
match(input, pos, anchor) {
|
|
2453
|
+
if (this.failed) return null;
|
|
2454
|
+
if ((anchor === RE2Flags.ANCHOR_START || anchor === RE2Flags.ANCHOR_BOTH) && pos !== 0) return false;
|
|
2455
|
+
const startState = this.start();
|
|
2456
|
+
if (startState === null) return null;
|
|
2457
|
+
const endPos = input.endPos();
|
|
2458
|
+
if (startState.isMatch && (anchor !== RE2Flags.ANCHOR_BOTH || pos === endPos)) return true;
|
|
2459
|
+
return this.run(input, pos, anchor, startState, (state, nextPos) => {
|
|
2460
|
+
if (state.isMatch && (anchor !== RE2Flags.ANCHOR_BOTH || nextPos === endPos)) return true;
|
|
2461
|
+
return null;
|
|
2462
|
+
}, false);
|
|
2388
2463
|
}
|
|
2389
2464
|
matchSet(input, pos, anchor) {
|
|
2465
|
+
if (this.failed) return null;
|
|
2390
2466
|
if ((anchor === RE2Flags.ANCHOR_START || anchor === RE2Flags.ANCHOR_BOTH) && pos !== 0) return [];
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
|
|
2394
|
-
}
|
|
2395
|
-
let endPos = input.endPos();
|
|
2396
|
-
let currentState = this.startState;
|
|
2467
|
+
const startState = this.start();
|
|
2468
|
+
if (startState === null) return null;
|
|
2469
|
+
const endPos = input.endPos();
|
|
2397
2470
|
const matches = /* @__PURE__ */ new Set();
|
|
2398
|
-
const
|
|
2399
|
-
if (state.isMatch
|
|
2400
|
-
|
|
2401
|
-
} else state.matchIDs.forEach((id) => matches.add(id));
|
|
2471
|
+
const collect = (state, currentPos) => {
|
|
2472
|
+
if (state.isMatch && (anchor !== RE2Flags.ANCHOR_BOTH || currentPos === endPos)) for (let k = 0; k < state.matchIDs.length; k++) matches.add(state.matchIDs[k]);
|
|
2473
|
+
return null;
|
|
2402
2474
|
};
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
while (i < endPos) {
|
|
2406
|
-
const r = input.step(i);
|
|
2407
|
-
const rune = r >> 3;
|
|
2408
|
-
const width = r & 7;
|
|
2409
|
-
if (width === 0) break;
|
|
2410
|
-
currentState = anchor === RE2Flags.UNANCHORED && rune <= Unicode.MAX_LATIN1 && currentState.nextLatin1[rune] || this.step(currentState, rune, anchor);
|
|
2411
|
-
if (currentState === null) return null;
|
|
2412
|
-
currentState.lastSeen = ++this.clock;
|
|
2413
|
-
i += width;
|
|
2414
|
-
checkMatch(currentState, i);
|
|
2415
|
-
if (currentState.nfaStates.length === 0) {
|
|
2416
|
-
if (anchor !== RE2Flags.UNANCHORED) break;
|
|
2417
|
-
}
|
|
2418
|
-
}
|
|
2475
|
+
collect(startState, pos);
|
|
2476
|
+
if (this.run(input, pos, anchor, startState, collect, false) === null) return null;
|
|
2419
2477
|
return Array.from(matches).sort((a, b) => a - b);
|
|
2420
2478
|
}
|
|
2421
2479
|
};
|
|
@@ -2424,7 +2482,7 @@ var DFA = class DFA {
|
|
|
2424
2482
|
const VISITED_BITS = 32;
|
|
2425
2483
|
const MAX_BACKTRACK_PROG = 500;
|
|
2426
2484
|
const INITIAL_JOB_CAPACITY = 256;
|
|
2427
|
-
const MAX_BACKTRACK_VECTOR =
|
|
2485
|
+
const MAX_BACKTRACK_VECTOR = 262144;
|
|
2428
2486
|
var BitState = class {
|
|
2429
2487
|
constructor() {
|
|
2430
2488
|
this.end = 0;
|
|
@@ -2707,7 +2765,7 @@ var OnePassProg = class {
|
|
|
2707
2765
|
const inst = new Inst(orig.op);
|
|
2708
2766
|
inst.out = orig.out;
|
|
2709
2767
|
inst.arg = orig.arg;
|
|
2710
|
-
inst.runes = orig.runes ? orig.runes
|
|
2768
|
+
inst.runes = orig.runes ? new Int32Array(orig.runes) : /* @__PURE__ */ new Int32Array(0);
|
|
2711
2769
|
inst.next = null;
|
|
2712
2770
|
this.inst[i] = inst;
|
|
2713
2771
|
}
|
|
@@ -2773,9 +2831,11 @@ const makeOnePass = (p) => {
|
|
|
2773
2831
|
m[pc] = true;
|
|
2774
2832
|
inst.op = Inst.ALT_MATCH;
|
|
2775
2833
|
}
|
|
2776
|
-
const
|
|
2834
|
+
const leftRunes = onePassRunes[inst.out] || [];
|
|
2835
|
+
const rightRunes = onePassRunes[inst.arg] || [];
|
|
2836
|
+
const mergeRes = mergeRuneSets(leftRunes, rightRunes, inst.out, inst.arg);
|
|
2777
2837
|
if (!mergeRes) return false;
|
|
2778
|
-
onePassRunes[pc] = mergeRes.merged;
|
|
2838
|
+
onePassRunes[pc] = new Int32Array(mergeRes.merged);
|
|
2779
2839
|
inst.next = new Uint32Array(mergeRes.next);
|
|
2780
2840
|
break;
|
|
2781
2841
|
}
|
|
@@ -2784,7 +2844,7 @@ const makeOnePass = (p) => {
|
|
|
2784
2844
|
case Inst.NOP:
|
|
2785
2845
|
ok = check(inst.out);
|
|
2786
2846
|
m[pc] = m[inst.out];
|
|
2787
|
-
onePassRunes[pc] = onePassRunes[inst.out] ? onePassRunes[inst.out]
|
|
2847
|
+
onePassRunes[pc] = onePassRunes[inst.out] ? new Int32Array(onePassRunes[inst.out]) : /* @__PURE__ */ new Int32Array(0);
|
|
2788
2848
|
inst.next = new Uint32Array(Math.floor(onePassRunes[pc].length / 2) + 1).fill(inst.out);
|
|
2789
2849
|
break;
|
|
2790
2850
|
case Inst.MATCH:
|
|
@@ -2796,7 +2856,7 @@ const makeOnePass = (p) => {
|
|
|
2796
2856
|
if (inst.next && inst.next.length > 0) break;
|
|
2797
2857
|
instQueue.insert(inst.out);
|
|
2798
2858
|
if (!inst.runes || inst.runes.length === 0) {
|
|
2799
|
-
onePassRunes[pc] =
|
|
2859
|
+
onePassRunes[pc] = /* @__PURE__ */ new Int32Array(0);
|
|
2800
2860
|
inst.next = new Uint32Array([inst.out]);
|
|
2801
2861
|
break;
|
|
2802
2862
|
}
|
|
@@ -2807,7 +2867,7 @@ const makeOnePass = (p) => {
|
|
|
2807
2867
|
for (let r1 = Unicode.simpleFold(r0); r1 !== r0; r1 = Unicode.simpleFold(r1)) runes.push(r1, r1);
|
|
2808
2868
|
runes.sort((a, b) => a - b);
|
|
2809
2869
|
} else for (let j = 0; j < inst.runes.length; j++) runes.push(inst.runes[j]);
|
|
2810
|
-
onePassRunes[pc] = runes;
|
|
2870
|
+
onePassRunes[pc] = new Int32Array(runes);
|
|
2811
2871
|
inst.next = new Uint32Array(Math.floor(runes.length / 2) + 1).fill(inst.out);
|
|
2812
2872
|
inst.op = Inst.RUNE;
|
|
2813
2873
|
break;
|
|
@@ -2823,7 +2883,7 @@ const makeOnePass = (p) => {
|
|
|
2823
2883
|
for (let r1 = Unicode.simpleFold(r0); r1 !== r0; r1 = Unicode.simpleFold(r1)) runes.push(r1, r1);
|
|
2824
2884
|
runes.sort((a, b) => a - b);
|
|
2825
2885
|
} else runes.push(inst.runes[0], inst.runes[0]);
|
|
2826
|
-
onePassRunes[pc] = runes;
|
|
2886
|
+
onePassRunes[pc] = new Int32Array(runes);
|
|
2827
2887
|
inst.next = new Uint32Array(Math.floor(runes.length / 2) + 1).fill(inst.out);
|
|
2828
2888
|
inst.op = Inst.RUNE;
|
|
2829
2889
|
break;
|
|
@@ -2832,21 +2892,20 @@ const makeOnePass = (p) => {
|
|
|
2832
2892
|
m[pc] = false;
|
|
2833
2893
|
if (inst.next && inst.next.length > 0) break;
|
|
2834
2894
|
instQueue.insert(inst.out);
|
|
2835
|
-
onePassRunes[pc] = [0, Unicode.MAX_RUNE];
|
|
2895
|
+
onePassRunes[pc] = new Int32Array([0, Unicode.MAX_RUNE]);
|
|
2836
2896
|
inst.next = new Uint32Array([inst.out]);
|
|
2837
2897
|
break;
|
|
2838
2898
|
case Inst.RUNE_ANY_NOT_NL:
|
|
2839
2899
|
m[pc] = false;
|
|
2840
2900
|
if (inst.next && inst.next.length > 0) break;
|
|
2841
2901
|
instQueue.insert(inst.out);
|
|
2842
|
-
onePassRunes[pc] = [
|
|
2902
|
+
onePassRunes[pc] = new Int32Array([
|
|
2843
2903
|
0,
|
|
2844
2904
|
9,
|
|
2845
2905
|
11,
|
|
2846
2906
|
Unicode.MAX_RUNE
|
|
2847
|
-
];
|
|
2907
|
+
]);
|
|
2848
2908
|
inst.next = new Uint32Array(Math.floor(onePassRunes[pc].length / 2) + 1).fill(inst.out);
|
|
2849
|
-
break;
|
|
2850
2909
|
}
|
|
2851
2910
|
return ok;
|
|
2852
2911
|
};
|
|
@@ -2878,8 +2937,7 @@ const cleanupOnePass = (p, original) => {
|
|
|
2878
2937
|
case Inst.RUNE_ANY_NOT_NL:
|
|
2879
2938
|
p.inst[ix].next = null;
|
|
2880
2939
|
p.inst[ix].op = instOriginal.op;
|
|
2881
|
-
p.inst[ix].runes = instOriginal.runes ? instOriginal.runes
|
|
2882
|
-
break;
|
|
2940
|
+
p.inst[ix].runes = instOriginal.runes ? new Int32Array(instOriginal.runes) : /* @__PURE__ */ new Int32Array(0);
|
|
2883
2941
|
}
|
|
2884
2942
|
}
|
|
2885
2943
|
};
|
|
@@ -2908,9 +2966,7 @@ var OnePass = class OnePass {
|
|
|
2908
2966
|
return null;
|
|
2909
2967
|
}
|
|
2910
2968
|
break;
|
|
2911
|
-
default:
|
|
2912
|
-
if (opOut === Inst.MATCH && hasAlt) return null;
|
|
2913
|
-
break;
|
|
2969
|
+
default: if (opOut === Inst.MATCH && hasAlt) return null;
|
|
2914
2970
|
}
|
|
2915
2971
|
}
|
|
2916
2972
|
let p = onePassCopy(prog);
|
|
@@ -3061,7 +3117,7 @@ var Regexp = class Regexp {
|
|
|
3061
3117
|
this.op = op;
|
|
3062
3118
|
this.flags = 0;
|
|
3063
3119
|
this.subs = Regexp.emptySubs();
|
|
3064
|
-
this.runes =
|
|
3120
|
+
this.runes = /* @__PURE__ */ new Int32Array(0);
|
|
3065
3121
|
this.min = 0;
|
|
3066
3122
|
this.max = 0;
|
|
3067
3123
|
this.cap = 0;
|
|
@@ -3072,7 +3128,7 @@ var Regexp = class Regexp {
|
|
|
3072
3128
|
reinit() {
|
|
3073
3129
|
this.flags = 0;
|
|
3074
3130
|
this.subs = Regexp.emptySubs();
|
|
3075
|
-
this.runes =
|
|
3131
|
+
this.runes = /* @__PURE__ */ new Int32Array(0);
|
|
3076
3132
|
this.cap = 0;
|
|
3077
3133
|
this.min = 0;
|
|
3078
3134
|
this.max = 0;
|
|
@@ -3116,7 +3172,6 @@ var Regexp = class Regexp {
|
|
|
3116
3172
|
if (this.max >= 0) out += this.max;
|
|
3117
3173
|
}
|
|
3118
3174
|
out += "}";
|
|
3119
|
-
break;
|
|
3120
3175
|
}
|
|
3121
3176
|
if ((this.flags & RE2Flags.NON_GREEDY) !== 0) out += "?";
|
|
3122
3177
|
break;
|
|
@@ -3209,9 +3264,7 @@ var Regexp = class Regexp {
|
|
|
3209
3264
|
}
|
|
3210
3265
|
out += "]";
|
|
3211
3266
|
break;
|
|
3212
|
-
default:
|
|
3213
|
-
out += this.op;
|
|
3214
|
-
break;
|
|
3267
|
+
default: out += this.op;
|
|
3215
3268
|
}
|
|
3216
3269
|
return out;
|
|
3217
3270
|
}
|
|
@@ -3255,70 +3308,158 @@ var Regexp = class Regexp {
|
|
|
3255
3308
|
if (this.cap !== that.cap || (this.name === null ? that.name !== null : this.name !== that.name) || !this.subs[0].equals(that.subs[0])) return false;
|
|
3256
3309
|
break;
|
|
3257
3310
|
case Regexp.Op.PLB:
|
|
3258
|
-
case Regexp.Op.NLB:
|
|
3259
|
-
if (this.lb !== that.lb || !this.subs[0].equals(that.subs[0])) return false;
|
|
3260
|
-
break;
|
|
3311
|
+
case Regexp.Op.NLB: if (this.lb !== that.lb || !this.subs[0].equals(that.subs[0])) return false;
|
|
3261
3312
|
}
|
|
3262
3313
|
return true;
|
|
3263
3314
|
}
|
|
3264
3315
|
};
|
|
3265
3316
|
//#endregion
|
|
3317
|
+
//#region src/RegexpWalker.js
|
|
3318
|
+
/**
|
|
3319
|
+
* Walks a Regexp tree without recursion, visiting nodes in the same order a recursive walk
|
|
3320
|
+
* would (RE2: re2/walker-inl.h, "Helper class for traversing Regexps without recursion").
|
|
3321
|
+
*
|
|
3322
|
+
* The handler sees a node without subexpressions once, through `leaf(re)`, which returns its
|
|
3323
|
+
* result. Any other node is seen up to three times:
|
|
3324
|
+
* - `enter(re)` before its children. It returns the state kept for `re` while its children are
|
|
3325
|
+
* visited; a state whose `result` is already set skips the children.
|
|
3326
|
+
* - `child(re, state, result, i)` after child `i` produced `result`. Setting `state.result`
|
|
3327
|
+
* stops visiting the remaining children.
|
|
3328
|
+
* - `leave(re, state)` after the last child; it returns the result for `re`.
|
|
3329
|
+
*
|
|
3330
|
+
* Counted repetitions expand into one nesting level per copy, so the simplified tree can be
|
|
3331
|
+
* thousands of levels deep; recursion over it would overflow the JS stack, which has no fixed
|
|
3332
|
+
* relation to the parser's nesting limit. This walk keeps its frames on the heap instead.
|
|
3333
|
+
*/
|
|
3334
|
+
var RegexpWalker = class {
|
|
3335
|
+
static walk(root, handler) {
|
|
3336
|
+
const stack = [];
|
|
3337
|
+
let re = root;
|
|
3338
|
+
let result;
|
|
3339
|
+
for (;;) {
|
|
3340
|
+
if (re.subs.length === 0) result = handler.leaf(re);
|
|
3341
|
+
else {
|
|
3342
|
+
const state = handler.enter(re);
|
|
3343
|
+
if (state.result === void 0) {
|
|
3344
|
+
stack.push({
|
|
3345
|
+
re,
|
|
3346
|
+
state,
|
|
3347
|
+
i: 0
|
|
3348
|
+
});
|
|
3349
|
+
re = re.subs[0];
|
|
3350
|
+
continue;
|
|
3351
|
+
}
|
|
3352
|
+
result = state.result;
|
|
3353
|
+
}
|
|
3354
|
+
for (;;) {
|
|
3355
|
+
if (stack.length === 0) return result;
|
|
3356
|
+
const frame = stack[stack.length - 1];
|
|
3357
|
+
handler.child(frame.re, frame.state, result, frame.i);
|
|
3358
|
+
frame.i++;
|
|
3359
|
+
if (frame.state.result === void 0 && frame.i < frame.re.subs.length) {
|
|
3360
|
+
re = frame.re.subs[frame.i];
|
|
3361
|
+
break;
|
|
3362
|
+
}
|
|
3363
|
+
stack.pop();
|
|
3364
|
+
result = frame.state.result !== void 0 ? frame.state.result : handler.leave(frame.re, frame.state);
|
|
3365
|
+
}
|
|
3366
|
+
}
|
|
3367
|
+
}
|
|
3368
|
+
};
|
|
3369
|
+
//#endregion
|
|
3266
3370
|
//#region src/Prefilter.js
|
|
3267
3371
|
var AhoCorasick = class {
|
|
3268
|
-
constructor(
|
|
3269
|
-
|
|
3270
|
-
|
|
3271
|
-
|
|
3272
|
-
|
|
3372
|
+
constructor(words, alphabetSize) {
|
|
3373
|
+
const edges = /* @__PURE__ */ new Map();
|
|
3374
|
+
const parent = [0];
|
|
3375
|
+
const unit = [0];
|
|
3376
|
+
const depth = [0];
|
|
3377
|
+
const terminal = [0];
|
|
3378
|
+
for (const word of words) {
|
|
3273
3379
|
let node = 0;
|
|
3274
3380
|
for (let i = 0; i < word.length; i++) {
|
|
3275
|
-
const
|
|
3276
|
-
|
|
3277
|
-
|
|
3278
|
-
|
|
3279
|
-
|
|
3280
|
-
|
|
3381
|
+
const key = node * alphabetSize + word[i];
|
|
3382
|
+
let child = edges.get(key);
|
|
3383
|
+
if (child === void 0) {
|
|
3384
|
+
child = parent.length;
|
|
3385
|
+
edges.set(key, child);
|
|
3386
|
+
parent.push(node);
|
|
3387
|
+
unit.push(word[i]);
|
|
3388
|
+
depth.push(depth[node] + 1);
|
|
3389
|
+
terminal.push(0);
|
|
3281
3390
|
}
|
|
3282
|
-
node =
|
|
3391
|
+
node = child;
|
|
3283
3392
|
}
|
|
3284
|
-
|
|
3285
|
-
}
|
|
3286
|
-
const
|
|
3287
|
-
|
|
3288
|
-
|
|
3289
|
-
|
|
3290
|
-
|
|
3291
|
-
|
|
3292
|
-
|
|
3293
|
-
|
|
3294
|
-
|
|
3295
|
-
|
|
3296
|
-
|
|
3297
|
-
|
|
3298
|
-
|
|
3299
|
-
|
|
3300
|
-
|
|
3301
|
-
|
|
3393
|
+
terminal[node] = 1;
|
|
3394
|
+
}
|
|
3395
|
+
const numNodes = parent.length;
|
|
3396
|
+
const children = new Int32Array(numNodes - 1);
|
|
3397
|
+
for (let c = 1; c < numNodes; c++) children[c - 1] = c;
|
|
3398
|
+
children.sort((a, b) => parent[a] - parent[b] || unit[a] - unit[b]);
|
|
3399
|
+
const childStart = new Int32Array(numNodes + 1);
|
|
3400
|
+
for (let c = 1; c < numNodes; c++) childStart[parent[c] + 1]++;
|
|
3401
|
+
for (let n = 0; n < numNodes; n++) childStart[n + 1] += childStart[n];
|
|
3402
|
+
const childUnit = new Int32Array(numNodes - 1);
|
|
3403
|
+
for (let k = 0; k < children.length; k++) childUnit[k] = unit[children[k]];
|
|
3404
|
+
this.childStart = childStart;
|
|
3405
|
+
this.childUnit = childUnit;
|
|
3406
|
+
this.childNode = children;
|
|
3407
|
+
const byDepth = new Int32Array(numNodes);
|
|
3408
|
+
for (let n = 0; n < numNodes; n++) byDepth[n] = n;
|
|
3409
|
+
byDepth.sort((a, b) => depth[a] - depth[b]);
|
|
3410
|
+
const fail = new Int32Array(numNodes);
|
|
3411
|
+
const match = Uint8Array.from(terminal);
|
|
3412
|
+
for (let k = 1; k < numNodes; k++) {
|
|
3413
|
+
const c = byDepth[k];
|
|
3414
|
+
const p = parent[c];
|
|
3415
|
+
if (p !== 0) {
|
|
3416
|
+
let f = fail[p];
|
|
3417
|
+
let next = this.next(f, unit[c]);
|
|
3418
|
+
while (next < 0 && f !== 0) {
|
|
3419
|
+
f = fail[f];
|
|
3420
|
+
next = this.next(f, unit[c]);
|
|
3421
|
+
}
|
|
3422
|
+
fail[c] = next >= 0 ? next : 0;
|
|
3302
3423
|
}
|
|
3424
|
+
match[c] |= match[fail[c]];
|
|
3425
|
+
}
|
|
3426
|
+
this.fail = fail;
|
|
3427
|
+
this.match = match;
|
|
3428
|
+
}
|
|
3429
|
+
next(node, u) {
|
|
3430
|
+
let lo = this.childStart[node];
|
|
3431
|
+
let hi = this.childStart[node + 1];
|
|
3432
|
+
const units = this.childUnit;
|
|
3433
|
+
while (lo < hi) {
|
|
3434
|
+
const mid = lo + hi >> 1;
|
|
3435
|
+
const m = units[mid];
|
|
3436
|
+
if (m === u) return this.childNode[mid];
|
|
3437
|
+
if (m < u) lo = mid + 1;
|
|
3438
|
+
else hi = mid;
|
|
3439
|
+
}
|
|
3440
|
+
return -1;
|
|
3441
|
+
}
|
|
3442
|
+
advance(node, u) {
|
|
3443
|
+
for (;;) {
|
|
3444
|
+
const next = this.next(node, u);
|
|
3445
|
+
if (next >= 0) return next;
|
|
3446
|
+
if (node === 0) return 0;
|
|
3447
|
+
node = this.fail[node];
|
|
3303
3448
|
}
|
|
3304
3449
|
}
|
|
3305
3450
|
searchUTF16(charSeq, start, end) {
|
|
3306
3451
|
let node = 0;
|
|
3307
3452
|
for (let i = start; i < end; i++) {
|
|
3308
|
-
|
|
3309
|
-
|
|
3310
|
-
if (val in this.next[node]) node = this.next[node][val];
|
|
3311
|
-
if (this.match[node]) return true;
|
|
3453
|
+
node = this.advance(node, charSeq.charCodeAt(i));
|
|
3454
|
+
if (this.match[node] === 1) return true;
|
|
3312
3455
|
}
|
|
3313
3456
|
return false;
|
|
3314
3457
|
}
|
|
3315
3458
|
searchUTF8(bytes, start, end) {
|
|
3316
3459
|
let node = 0;
|
|
3317
3460
|
for (let i = start; i < end; i++) {
|
|
3318
|
-
|
|
3319
|
-
|
|
3320
|
-
if (val in this.next[node]) node = this.next[node][val];
|
|
3321
|
-
if (this.match[node]) return true;
|
|
3461
|
+
node = this.advance(node, bytes[i]);
|
|
3462
|
+
if (this.match[node] === 1) return true;
|
|
3322
3463
|
}
|
|
3323
3464
|
return false;
|
|
3324
3465
|
}
|
|
@@ -3330,14 +3471,33 @@ var Prefilter = class Prefilter {
|
|
|
3330
3471
|
AND: 2,
|
|
3331
3472
|
OR: 3
|
|
3332
3473
|
};
|
|
3474
|
+
static MAX_SCANS = 32;
|
|
3475
|
+
static MAX_AC_UNITS = 1 << 18;
|
|
3333
3476
|
constructor(type) {
|
|
3334
3477
|
this.type = type;
|
|
3335
3478
|
this.subs = [];
|
|
3336
3479
|
this.str = "";
|
|
3337
3480
|
this.bytes = null;
|
|
3481
|
+
this.cost = type === Prefilter.Type.EXACT ? 1 : 0;
|
|
3482
|
+
this.allExact = false;
|
|
3338
3483
|
this.ac16 = null;
|
|
3339
3484
|
this.ac8 = null;
|
|
3340
3485
|
}
|
|
3486
|
+
automaton16() {
|
|
3487
|
+
if (this.ac16 === null) {
|
|
3488
|
+
const words = this.subs.map((s) => {
|
|
3489
|
+
const arr = new Array(s.str.length);
|
|
3490
|
+
for (let i = 0; i < s.str.length; i++) arr[i] = s.str.charCodeAt(i);
|
|
3491
|
+
return arr;
|
|
3492
|
+
});
|
|
3493
|
+
this.ac16 = new AhoCorasick(words, 65536);
|
|
3494
|
+
}
|
|
3495
|
+
return this.ac16;
|
|
3496
|
+
}
|
|
3497
|
+
automaton8() {
|
|
3498
|
+
if (this.ac8 === null) this.ac8 = new AhoCorasick(this.subs.map((s) => s.bytes), 256);
|
|
3499
|
+
return this.ac8;
|
|
3500
|
+
}
|
|
3341
3501
|
eval(input, pos) {
|
|
3342
3502
|
switch (this.type) {
|
|
3343
3503
|
case Prefilter.Type.NONE: return true;
|
|
@@ -3346,7 +3506,7 @@ var Prefilter = class Prefilter {
|
|
|
3346
3506
|
for (let i = 0; i < this.subs.length; i++) if (!this.subs[i].eval(input, pos)) return false;
|
|
3347
3507
|
return true;
|
|
3348
3508
|
case Prefilter.Type.OR:
|
|
3349
|
-
if (this.
|
|
3509
|
+
if (this.allExact) return input.hasAnyString(this, pos);
|
|
3350
3510
|
for (let i = 0; i < this.subs.length; i++) if (this.subs[i].eval(input, pos)) return true;
|
|
3351
3511
|
return false;
|
|
3352
3512
|
default: return true;
|
|
@@ -3355,100 +3515,115 @@ var Prefilter = class Prefilter {
|
|
|
3355
3515
|
};
|
|
3356
3516
|
var PrefilterTree = class PrefilterTree {
|
|
3357
3517
|
static build(re) {
|
|
3358
|
-
const pf = PrefilterTree.fromRegexp(re);
|
|
3359
|
-
return PrefilterTree.simplify(pf);
|
|
3360
|
-
}
|
|
3361
|
-
static fromRegexp(re) {
|
|
3362
3518
|
if (!re) return new Prefilter(Prefilter.Type.NONE);
|
|
3519
|
+
return RegexpWalker.walk(re, PrefilterTree.WALKER);
|
|
3520
|
+
}
|
|
3521
|
+
static WALKER = {
|
|
3522
|
+
leaf: (re) => PrefilterTree.leaf(re),
|
|
3523
|
+
enter: (re) => PrefilterTree.enter(re),
|
|
3524
|
+
child: (re, state, result) => PrefilterTree.child(re, state, result),
|
|
3525
|
+
leave: (re, state) => PrefilterTree.leave(re, state)
|
|
3526
|
+
};
|
|
3527
|
+
static leaf(re) {
|
|
3528
|
+
if (re.op !== Regexp.Op.LITERAL) return new Prefilter(Prefilter.Type.NONE);
|
|
3529
|
+
if (re.runes.length === 0 || (re.flags & RE2Flags.FOLD_CASE) !== 0) return new Prefilter(Prefilter.Type.NONE);
|
|
3530
|
+
let str = "";
|
|
3531
|
+
for (let i = 0; i < re.runes.length; i++) {
|
|
3532
|
+
if (Unicode.isUnsearchable(re.runes[i])) return new Prefilter(Prefilter.Type.NONE);
|
|
3533
|
+
str += String.fromCodePoint(re.runes[i]);
|
|
3534
|
+
}
|
|
3535
|
+
const pf = new Prefilter(Prefilter.Type.EXACT);
|
|
3536
|
+
pf.str = str;
|
|
3537
|
+
pf.bytes = Utils.stringToUtf8ByteArray(pf.str);
|
|
3538
|
+
return pf;
|
|
3539
|
+
}
|
|
3540
|
+
static enter(re) {
|
|
3363
3541
|
switch (re.op) {
|
|
3364
|
-
case Regexp.Op.PLB:
|
|
3365
|
-
case Regexp.Op.NLB:
|
|
3366
|
-
case Regexp.Op.NO_MATCH:
|
|
3367
|
-
case Regexp.Op.EMPTY_MATCH:
|
|
3368
|
-
case Regexp.Op.BEGIN_LINE:
|
|
3369
|
-
case Regexp.Op.END_LINE:
|
|
3370
|
-
case Regexp.Op.BEGIN_TEXT:
|
|
3371
|
-
case Regexp.Op.END_TEXT:
|
|
3372
|
-
case Regexp.Op.WORD_BOUNDARY:
|
|
3373
|
-
case Regexp.Op.NO_WORD_BOUNDARY:
|
|
3374
|
-
case Regexp.Op.CHAR_CLASS:
|
|
3375
|
-
case Regexp.Op.ANY_CHAR_NOT_NL:
|
|
3376
|
-
case Regexp.Op.ANY_CHAR: return new Prefilter(Prefilter.Type.NONE);
|
|
3377
|
-
case Regexp.Op.LITERAL: {
|
|
3378
|
-
if (re.runes.length === 0 || (re.flags & RE2Flags.FOLD_CASE) !== 0) return new Prefilter(Prefilter.Type.NONE);
|
|
3379
|
-
const pf = new Prefilter(Prefilter.Type.EXACT);
|
|
3380
|
-
let str = "";
|
|
3381
|
-
for (let i = 0; i < re.runes.length; i++) str += String.fromCodePoint(re.runes[i]);
|
|
3382
|
-
pf.str = str;
|
|
3383
|
-
pf.bytes = Utils.stringToUtf8ByteArray(pf.str);
|
|
3384
|
-
return pf;
|
|
3385
|
-
}
|
|
3386
3542
|
case Regexp.Op.CAPTURE:
|
|
3387
|
-
case Regexp.Op.PLUS: return
|
|
3543
|
+
case Regexp.Op.PLUS: return { sub: null };
|
|
3388
3544
|
case Regexp.Op.REPEAT:
|
|
3389
|
-
if (re.min >= 1) return
|
|
3390
|
-
return new Prefilter(Prefilter.Type.NONE);
|
|
3391
|
-
case Regexp.Op.CONCAT: {
|
|
3392
|
-
|
|
3393
|
-
|
|
3394
|
-
|
|
3545
|
+
if (re.min >= 1) return { sub: null };
|
|
3546
|
+
return { result: new Prefilter(Prefilter.Type.NONE) };
|
|
3547
|
+
case Regexp.Op.CONCAT: return {
|
|
3548
|
+
pf: new Prefilter(Prefilter.Type.AND),
|
|
3549
|
+
subs: []
|
|
3550
|
+
};
|
|
3551
|
+
case Regexp.Op.ALTERNATE: return {
|
|
3552
|
+
pf: new Prefilter(Prefilter.Type.OR),
|
|
3553
|
+
subs: []
|
|
3554
|
+
};
|
|
3555
|
+
default: return { result: new Prefilter(Prefilter.Type.NONE) };
|
|
3556
|
+
}
|
|
3557
|
+
}
|
|
3558
|
+
static child(re, state, s) {
|
|
3559
|
+
if (state.subs === void 0) {
|
|
3560
|
+
state.sub = s;
|
|
3561
|
+
return;
|
|
3562
|
+
}
|
|
3563
|
+
if (state.pf.type === Prefilter.Type.AND) {
|
|
3564
|
+
if (s.type === Prefilter.Type.NONE) return;
|
|
3565
|
+
if (s.type === Prefilter.Type.AND) {
|
|
3566
|
+
for (let j = 0; j < s.subs.length; j++) state.subs.push(s.subs[j]);
|
|
3567
|
+
return;
|
|
3395
3568
|
}
|
|
3396
|
-
|
|
3397
|
-
|
|
3398
|
-
|
|
3399
|
-
|
|
3569
|
+
state.subs.push(s);
|
|
3570
|
+
return;
|
|
3571
|
+
}
|
|
3572
|
+
if (s.type === Prefilter.Type.NONE) {
|
|
3573
|
+
state.result = new Prefilter(Prefilter.Type.NONE);
|
|
3574
|
+
return;
|
|
3575
|
+
}
|
|
3576
|
+
if (s.type === Prefilter.Type.OR) {
|
|
3577
|
+
for (let j = 0; j < s.subs.length; j++) state.subs.push(s.subs[j]);
|
|
3578
|
+
return;
|
|
3579
|
+
}
|
|
3580
|
+
state.subs.push(s);
|
|
3581
|
+
}
|
|
3582
|
+
static leave(re, state) {
|
|
3583
|
+
if (state.subs === void 0) return state.sub;
|
|
3584
|
+
const pf = state.pf;
|
|
3585
|
+
const seen = /* @__PURE__ */ new Set();
|
|
3586
|
+
const subs = [];
|
|
3587
|
+
for (const sub of state.subs) {
|
|
3588
|
+
if (sub.type === Prefilter.Type.EXACT) {
|
|
3589
|
+
if (seen.has(sub.str)) continue;
|
|
3590
|
+
seen.add(sub.str);
|
|
3400
3591
|
}
|
|
3401
|
-
|
|
3592
|
+
subs.push(sub);
|
|
3402
3593
|
}
|
|
3403
|
-
}
|
|
3404
|
-
static simplify(pf) {
|
|
3405
|
-
if (pf.type === Prefilter.Type.EXACT || pf.type === Prefilter.Type.NONE) return pf;
|
|
3406
3594
|
if (pf.type === Prefilter.Type.AND) {
|
|
3407
|
-
const
|
|
3408
|
-
|
|
3409
|
-
|
|
3410
|
-
if (
|
|
3411
|
-
|
|
3595
|
+
const kept = [];
|
|
3596
|
+
let cost = 0;
|
|
3597
|
+
for (const sub of subs) {
|
|
3598
|
+
if (cost + sub.cost > Prefilter.MAX_SCANS) continue;
|
|
3599
|
+
kept.push(sub);
|
|
3600
|
+
cost += sub.cost;
|
|
3412
3601
|
}
|
|
3413
|
-
if (
|
|
3414
|
-
if (
|
|
3415
|
-
pf.subs =
|
|
3602
|
+
if (kept.length === 0) return new Prefilter(Prefilter.Type.NONE);
|
|
3603
|
+
if (kept.length === 1) return kept[0];
|
|
3604
|
+
pf.subs = kept;
|
|
3605
|
+
pf.cost = cost;
|
|
3416
3606
|
return pf;
|
|
3417
3607
|
}
|
|
3418
|
-
if (
|
|
3419
|
-
|
|
3420
|
-
|
|
3421
|
-
|
|
3422
|
-
|
|
3423
|
-
|
|
3424
|
-
|
|
3425
|
-
|
|
3426
|
-
|
|
3427
|
-
|
|
3428
|
-
|
|
3429
|
-
|
|
3430
|
-
|
|
3431
|
-
|
|
3432
|
-
|
|
3433
|
-
uniqueSubs.push(sub);
|
|
3434
|
-
}
|
|
3435
|
-
} else uniqueSubs.push(sub);
|
|
3436
|
-
pf.subs = uniqueSubs;
|
|
3437
|
-
let allExact = true;
|
|
3438
|
-
for (const sub of uniqueSubs) if (sub.type !== Prefilter.Type.EXACT) {
|
|
3439
|
-
allExact = false;
|
|
3440
|
-
break;
|
|
3441
|
-
}
|
|
3442
|
-
if (allExact && uniqueSubs.length > 1) {
|
|
3443
|
-
pf.ac16 = new AhoCorasick(uniqueSubs.map((s) => {
|
|
3444
|
-
const arr = [];
|
|
3445
|
-
for (let i = 0; i < s.str.length; i++) arr.push(s.str.charCodeAt(i));
|
|
3446
|
-
return arr;
|
|
3447
|
-
}));
|
|
3448
|
-
pf.ac8 = new AhoCorasick(uniqueSubs.map((s) => s.bytes));
|
|
3449
|
-
}
|
|
3608
|
+
if (subs.length === 0) return new Prefilter(Prefilter.Type.NONE);
|
|
3609
|
+
if (subs.length === 1) return subs[0];
|
|
3610
|
+
pf.subs = subs;
|
|
3611
|
+
let allExact = true;
|
|
3612
|
+
let cost = 0;
|
|
3613
|
+
let units = 0;
|
|
3614
|
+
for (const sub of subs) {
|
|
3615
|
+
if (sub.type !== Prefilter.Type.EXACT) allExact = false;
|
|
3616
|
+
else units += sub.bytes.length;
|
|
3617
|
+
cost += sub.cost;
|
|
3618
|
+
}
|
|
3619
|
+
if (allExact) {
|
|
3620
|
+
if (units > Prefilter.MAX_AC_UNITS) return new Prefilter(Prefilter.Type.NONE);
|
|
3621
|
+
pf.allExact = true;
|
|
3622
|
+
pf.cost = 1;
|
|
3450
3623
|
return pf;
|
|
3451
3624
|
}
|
|
3625
|
+
if (cost > Prefilter.MAX_SCANS) return new Prefilter(Prefilter.Type.NONE);
|
|
3626
|
+
pf.cost = cost;
|
|
3452
3627
|
return pf;
|
|
3453
3628
|
}
|
|
3454
3629
|
};
|
|
@@ -3484,6 +3659,7 @@ var Prog = class {
|
|
|
3484
3659
|
this.numCap = 2;
|
|
3485
3660
|
this.lbStarts = [];
|
|
3486
3661
|
this.numLb = 0;
|
|
3662
|
+
this.lbInst = null;
|
|
3487
3663
|
}
|
|
3488
3664
|
getInst(pc) {
|
|
3489
3665
|
return this.inst[pc];
|
|
@@ -3494,6 +3670,26 @@ var Prog = class {
|
|
|
3494
3670
|
addInst(op) {
|
|
3495
3671
|
this.inst.push(new Inst(op));
|
|
3496
3672
|
}
|
|
3673
|
+
markLookbehindInsts() {
|
|
3674
|
+
const lbInst = new Uint8Array(this.inst.length);
|
|
3675
|
+
const pending = this.lbStarts.slice();
|
|
3676
|
+
while (pending.length > 0) {
|
|
3677
|
+
const pc = pending.pop();
|
|
3678
|
+
if (pc === 0 || lbInst[pc] === 1) continue;
|
|
3679
|
+
lbInst[pc] = 1;
|
|
3680
|
+
const i = this.inst[pc];
|
|
3681
|
+
switch (i.op) {
|
|
3682
|
+
case Inst.ALT:
|
|
3683
|
+
case Inst.ALT_MATCH:
|
|
3684
|
+
pending.push(i.out, i.arg);
|
|
3685
|
+
break;
|
|
3686
|
+
case Inst.MATCH:
|
|
3687
|
+
case Inst.FAIL: break;
|
|
3688
|
+
default: pending.push(i.out);
|
|
3689
|
+
}
|
|
3690
|
+
}
|
|
3691
|
+
this.lbInst = lbInst;
|
|
3692
|
+
}
|
|
3497
3693
|
skipNop(pc) {
|
|
3498
3694
|
let i = this.inst[pc];
|
|
3499
3695
|
while (i.op === Inst.NOP || i.op === Inst.CAPTURE) {
|
|
@@ -3506,7 +3702,7 @@ var Prog = class {
|
|
|
3506
3702
|
let prefix = "";
|
|
3507
3703
|
let i = this.skipNop(this.start);
|
|
3508
3704
|
if (!Inst.isRuneOp(i.op) || i.runes.length !== 1) return [i.op === Inst.MATCH, prefix];
|
|
3509
|
-
while (Inst.isRuneOp(i.op) && i.runes.length === 1 && (i.arg & RE2Flags.FOLD_CASE) === 0) {
|
|
3705
|
+
while (Inst.isRuneOp(i.op) && i.runes.length === 1 && (i.arg & RE2Flags.FOLD_CASE) === 0 && !Unicode.isUnsearchable(i.runes[0])) {
|
|
3510
3706
|
prefix += String.fromCodePoint(i.runes[0]);
|
|
3511
3707
|
i = this.skipNop(i.out);
|
|
3512
3708
|
}
|
|
@@ -3570,6 +3766,13 @@ var Prog = class {
|
|
|
3570
3766
|
};
|
|
3571
3767
|
//#endregion
|
|
3572
3768
|
//#region src/Compiler.js
|
|
3769
|
+
const ANY_RUNE_NOT_NL = new Int32Array([
|
|
3770
|
+
0,
|
|
3771
|
+
Codepoint.CODES.get("\n") - 1,
|
|
3772
|
+
Codepoint.CODES.get("\n") + 1,
|
|
3773
|
+
Unicode.MAX_RUNE
|
|
3774
|
+
]);
|
|
3775
|
+
const ANY_RUNE = new Int32Array([0, Unicode.MAX_RUNE]);
|
|
3573
3776
|
/**
|
|
3574
3777
|
* A fragment of a compiled regular expression program.
|
|
3575
3778
|
*
|
|
@@ -3589,28 +3792,19 @@ var Frag = class {
|
|
|
3589
3792
|
* The only entry point is {@link #compileRegexp}.
|
|
3590
3793
|
*/
|
|
3591
3794
|
var Compiler = class Compiler {
|
|
3592
|
-
static ANY_RUNE_NOT_NL() {
|
|
3593
|
-
return [
|
|
3594
|
-
0,
|
|
3595
|
-
Codepoint.CODES.get("\n") - 1,
|
|
3596
|
-
Codepoint.CODES.get("\n") + 1,
|
|
3597
|
-
Unicode.MAX_RUNE
|
|
3598
|
-
];
|
|
3599
|
-
}
|
|
3600
|
-
static ANY_RUNE() {
|
|
3601
|
-
return [0, Unicode.MAX_RUNE];
|
|
3602
|
-
}
|
|
3603
3795
|
static compileRegexp(re) {
|
|
3604
3796
|
const c = new Compiler();
|
|
3605
3797
|
const f = c.compile(re);
|
|
3606
3798
|
c.prog.patch(f.out, c.newInst(Inst.MATCH).i);
|
|
3607
3799
|
c.prog.start = f.i;
|
|
3800
|
+
c.prog.markLookbehindInsts();
|
|
3608
3801
|
return c.prog;
|
|
3609
3802
|
}
|
|
3610
3803
|
static compileSet(regexps) {
|
|
3611
3804
|
const c = new Compiler();
|
|
3612
3805
|
if (regexps.length === 0) {
|
|
3613
3806
|
c.prog.start = c.newInst(Inst.FAIL).i;
|
|
3807
|
+
c.prog.markLookbehindInsts();
|
|
3614
3808
|
return c.prog;
|
|
3615
3809
|
}
|
|
3616
3810
|
let starts = [];
|
|
@@ -3630,11 +3824,19 @@ var Compiler = class Compiler {
|
|
|
3630
3824
|
start = f.i;
|
|
3631
3825
|
}
|
|
3632
3826
|
c.prog.start = start;
|
|
3827
|
+
c.prog.markLookbehindInsts();
|
|
3633
3828
|
return c.prog;
|
|
3634
3829
|
}
|
|
3635
3830
|
constructor() {
|
|
3636
3831
|
this.prog = new Prog();
|
|
3637
3832
|
this.newInst(Inst.FAIL);
|
|
3833
|
+
this.runeCache = /* @__PURE__ */ new Map();
|
|
3834
|
+
this.walker = {
|
|
3835
|
+
leaf: (re) => this.leaf(re),
|
|
3836
|
+
enter: (re) => this.enter(re),
|
|
3837
|
+
child: (re, state, result) => this.child(re, state, result),
|
|
3838
|
+
leave: (re, state) => this.leave(re, state)
|
|
3839
|
+
};
|
|
3638
3840
|
}
|
|
3639
3841
|
newInst(op) {
|
|
3640
3842
|
this.prog.addInst(op);
|
|
@@ -3727,7 +3929,7 @@ var Compiler = class Compiler {
|
|
|
3727
3929
|
lookBehind(a, lb) {
|
|
3728
3930
|
const id = this.newInst(Inst.LB_WRITE);
|
|
3729
3931
|
this.prog.getInst(id.i).arg = lb;
|
|
3730
|
-
const any = this.rune(
|
|
3932
|
+
const any = this.rune(ANY_RUNE, 0);
|
|
3731
3933
|
const dotStar = this.star(any, true);
|
|
3732
3934
|
const lbAutomaton = this.cat(dotStar, a);
|
|
3733
3935
|
this.prog.patch(lbAutomaton.out, id.i);
|
|
@@ -3739,56 +3941,74 @@ var Compiler = class Compiler {
|
|
|
3739
3941
|
return checkId;
|
|
3740
3942
|
}
|
|
3741
3943
|
compile(re) {
|
|
3944
|
+
return RegexpWalker.walk(re, this.walker);
|
|
3945
|
+
}
|
|
3946
|
+
leaf(re) {
|
|
3742
3947
|
switch (re.op) {
|
|
3743
3948
|
case Regexp.Op.NO_MATCH: return this.fail();
|
|
3744
3949
|
case Regexp.Op.EMPTY_MATCH: return this.nop();
|
|
3745
|
-
case Regexp.Op.LITERAL:
|
|
3746
|
-
|
|
3950
|
+
case Regexp.Op.LITERAL: {
|
|
3951
|
+
if (re.runes.length === 0) return this.nop();
|
|
3747
3952
|
let f = null;
|
|
3748
3953
|
for (let r of re.runes) {
|
|
3749
|
-
|
|
3954
|
+
let singleRune = this.runeCache.get(r);
|
|
3955
|
+
if (singleRune === void 0) {
|
|
3956
|
+
singleRune = new Int32Array([r]);
|
|
3957
|
+
this.runeCache.set(r, singleRune);
|
|
3958
|
+
}
|
|
3959
|
+
const f1 = this.rune(singleRune, re.flags);
|
|
3750
3960
|
f = f === null ? f1 : this.cat(f, f1);
|
|
3751
3961
|
}
|
|
3752
3962
|
return f;
|
|
3753
3963
|
}
|
|
3754
3964
|
case Regexp.Op.CHAR_CLASS: return this.rune(re.runes, re.flags);
|
|
3755
|
-
case Regexp.Op.ANY_CHAR_NOT_NL: return this.rune(
|
|
3756
|
-
case Regexp.Op.ANY_CHAR: return this.rune(
|
|
3965
|
+
case Regexp.Op.ANY_CHAR_NOT_NL: return this.rune(ANY_RUNE_NOT_NL, 0);
|
|
3966
|
+
case Regexp.Op.ANY_CHAR: return this.rune(ANY_RUNE, 0);
|
|
3757
3967
|
case Regexp.Op.BEGIN_LINE: return this.empty(Utils.EMPTY_BEGIN_LINE);
|
|
3758
3968
|
case Regexp.Op.END_LINE: return this.empty(Utils.EMPTY_END_LINE);
|
|
3759
3969
|
case Regexp.Op.BEGIN_TEXT: return this.empty(Utils.EMPTY_BEGIN_TEXT);
|
|
3760
3970
|
case Regexp.Op.END_TEXT: return this.empty(Utils.EMPTY_END_TEXT);
|
|
3761
3971
|
case Regexp.Op.WORD_BOUNDARY: return this.empty(Utils.EMPTY_WORD_BOUNDARY);
|
|
3762
3972
|
case Regexp.Op.NO_WORD_BOUNDARY: return this.empty(Utils.EMPTY_NO_WORD_BOUNDARY);
|
|
3973
|
+
case Regexp.Op.CONCAT:
|
|
3974
|
+
case Regexp.Op.ALTERNATE: return this.nop();
|
|
3975
|
+
default: throw new RE2JSCompileException("regexp: unhandled case in compile");
|
|
3976
|
+
}
|
|
3977
|
+
}
|
|
3978
|
+
enter(re) {
|
|
3979
|
+
switch (re.op) {
|
|
3980
|
+
case Regexp.Op.PLB:
|
|
3981
|
+
case Regexp.Op.NLB:
|
|
3982
|
+
case Regexp.Op.STAR:
|
|
3983
|
+
case Regexp.Op.PLUS:
|
|
3984
|
+
case Regexp.Op.QUEST: return { sub: null };
|
|
3985
|
+
case Regexp.Op.CAPTURE: return {
|
|
3986
|
+
bra: this.cap(re.cap << 1),
|
|
3987
|
+
sub: null
|
|
3988
|
+
};
|
|
3989
|
+
case Regexp.Op.CONCAT:
|
|
3990
|
+
case Regexp.Op.ALTERNATE: return { f: null };
|
|
3991
|
+
default: throw new RE2JSCompileException("regexp: unhandled case in compile");
|
|
3992
|
+
}
|
|
3993
|
+
}
|
|
3994
|
+
child(re, state, f1) {
|
|
3995
|
+
if (re.op === Regexp.Op.CONCAT) state.f = state.f === null ? f1 : this.cat(state.f, f1);
|
|
3996
|
+
else if (re.op === Regexp.Op.ALTERNATE) state.f = state.f === null ? f1 : this.alt(state.f, f1);
|
|
3997
|
+
else state.sub = f1;
|
|
3998
|
+
}
|
|
3999
|
+
leave(re, state) {
|
|
4000
|
+
switch (re.op) {
|
|
3763
4001
|
case Regexp.Op.PLB:
|
|
3764
|
-
case Regexp.Op.NLB: return this.lookBehind(
|
|
4002
|
+
case Regexp.Op.NLB: return this.lookBehind(state.sub, re.lb);
|
|
3765
4003
|
case Regexp.Op.CAPTURE: {
|
|
3766
|
-
const bra = this.cap(re.cap << 1);
|
|
3767
|
-
const sub = this.compile(re.subs[0]);
|
|
3768
4004
|
const ket = this.cap(re.cap << 1 | 1);
|
|
3769
|
-
return this.cat(this.cat(bra, sub), ket);
|
|
3770
|
-
}
|
|
3771
|
-
case Regexp.Op.STAR: return this.star(this.compile(re.subs[0]), (re.flags & RE2Flags.NON_GREEDY) !== 0);
|
|
3772
|
-
case Regexp.Op.PLUS: return this.plus(this.compile(re.subs[0]), (re.flags & RE2Flags.NON_GREEDY) !== 0);
|
|
3773
|
-
case Regexp.Op.QUEST: return this.quest(this.compile(re.subs[0]), (re.flags & RE2Flags.NON_GREEDY) !== 0);
|
|
3774
|
-
case Regexp.Op.CONCAT: if (re.subs.length === 0) return this.nop();
|
|
3775
|
-
else {
|
|
3776
|
-
let f = null;
|
|
3777
|
-
for (let sub of re.subs) {
|
|
3778
|
-
const f1 = this.compile(sub);
|
|
3779
|
-
f = f === null ? f1 : this.cat(f, f1);
|
|
3780
|
-
}
|
|
3781
|
-
return f;
|
|
3782
|
-
}
|
|
3783
|
-
case Regexp.Op.ALTERNATE: if (re.subs.length === 0) return this.nop();
|
|
3784
|
-
else {
|
|
3785
|
-
let f = null;
|
|
3786
|
-
for (let sub of re.subs) {
|
|
3787
|
-
const f1 = this.compile(sub);
|
|
3788
|
-
f = f === null ? f1 : this.alt(f, f1);
|
|
3789
|
-
}
|
|
3790
|
-
return f;
|
|
4005
|
+
return this.cat(this.cat(state.bra, state.sub), ket);
|
|
3791
4006
|
}
|
|
4007
|
+
case Regexp.Op.STAR: return this.star(state.sub, (re.flags & RE2Flags.NON_GREEDY) !== 0);
|
|
4008
|
+
case Regexp.Op.PLUS: return this.plus(state.sub, (re.flags & RE2Flags.NON_GREEDY) !== 0);
|
|
4009
|
+
case Regexp.Op.QUEST: return this.quest(state.sub, (re.flags & RE2Flags.NON_GREEDY) !== 0);
|
|
4010
|
+
case Regexp.Op.CONCAT:
|
|
4011
|
+
case Regexp.Op.ALTERNATE: return state.f;
|
|
3792
4012
|
default: throw new RE2JSCompileException("regexp: unhandled case in compile");
|
|
3793
4013
|
}
|
|
3794
4014
|
}
|
|
@@ -3798,111 +4018,149 @@ var Compiler = class Compiler {
|
|
|
3798
4018
|
var Simplify = class Simplify {
|
|
3799
4019
|
static simplify(re) {
|
|
3800
4020
|
if (re === null) return null;
|
|
4021
|
+
return RegexpWalker.walk(re, Simplify.WALKER);
|
|
4022
|
+
}
|
|
4023
|
+
static WALKER = {
|
|
4024
|
+
leaf: (re) => Simplify.leaf(re),
|
|
4025
|
+
enter: (re) => Simplify.enter(re),
|
|
4026
|
+
child: (re, state, result, i) => Simplify.child(re, state, result, i),
|
|
4027
|
+
leave: (re, state) => Simplify.leave(re, state)
|
|
4028
|
+
};
|
|
4029
|
+
static leaf(re) {
|
|
4030
|
+
if (re.op === Regexp.Op.CHAR_CLASS) {
|
|
4031
|
+
if (re.runes === null) return re;
|
|
4032
|
+
if (re.runes.length === 0) return new Regexp(Regexp.Op.NO_MATCH);
|
|
4033
|
+
if (re.runes.length === 2 && re.runes[0] === 0 && re.runes[1] === Unicode.MAX_RUNE) return new Regexp(Regexp.Op.ANY_CHAR);
|
|
4034
|
+
if (re.runes.length === 4 && re.runes[0] === 0 && re.runes[1] === Codepoint.CODES.get("\n") - 1 && re.runes[2] === Codepoint.CODES.get("\n") + 1 && re.runes[3] === Unicode.MAX_RUNE) return new Regexp(Regexp.Op.ANY_CHAR_NOT_NL);
|
|
4035
|
+
}
|
|
4036
|
+
return re;
|
|
4037
|
+
}
|
|
4038
|
+
static enter(re) {
|
|
4039
|
+
switch (re.op) {
|
|
4040
|
+
case Regexp.Op.PLB:
|
|
4041
|
+
case Regexp.Op.NLB:
|
|
4042
|
+
case Regexp.Op.CAPTURE:
|
|
4043
|
+
case Regexp.Op.STAR:
|
|
4044
|
+
case Regexp.Op.PLUS:
|
|
4045
|
+
case Regexp.Op.QUEST: return { sub: null };
|
|
4046
|
+
case Regexp.Op.CONCAT:
|
|
4047
|
+
case Regexp.Op.ALTERNATE: return {
|
|
4048
|
+
subs: [],
|
|
4049
|
+
changed: false
|
|
4050
|
+
};
|
|
4051
|
+
case Regexp.Op.REPEAT:
|
|
4052
|
+
if (re.min === 0 && re.max === 0) return { result: new Regexp(Regexp.Op.EMPTY_MATCH) };
|
|
4053
|
+
return { sub: null };
|
|
4054
|
+
default: return { result: re };
|
|
4055
|
+
}
|
|
4056
|
+
}
|
|
4057
|
+
static child(re, state, nsub, i) {
|
|
4058
|
+
if (state.subs === void 0) {
|
|
4059
|
+
state.sub = nsub;
|
|
4060
|
+
return;
|
|
4061
|
+
}
|
|
4062
|
+
if (nsub !== re.subs[i]) state.changed = true;
|
|
4063
|
+
if (re.op === Regexp.Op.CONCAT) {
|
|
4064
|
+
if (nsub.op === Regexp.Op.NO_MATCH) {
|
|
4065
|
+
state.result = new Regexp(Regexp.Op.NO_MATCH);
|
|
4066
|
+
return;
|
|
4067
|
+
}
|
|
4068
|
+
if (nsub.op === Regexp.Op.EMPTY_MATCH) {
|
|
4069
|
+
state.changed = true;
|
|
4070
|
+
return;
|
|
4071
|
+
}
|
|
4072
|
+
if (nsub.op === Regexp.Op.CONCAT) {
|
|
4073
|
+
state.changed = true;
|
|
4074
|
+
for (let j = 0; j < nsub.subs.length; j++) state.subs.push(nsub.subs[j]);
|
|
4075
|
+
return;
|
|
4076
|
+
}
|
|
4077
|
+
} else {
|
|
4078
|
+
if (nsub.op === Regexp.Op.NO_MATCH) {
|
|
4079
|
+
state.changed = true;
|
|
4080
|
+
return;
|
|
4081
|
+
}
|
|
4082
|
+
if (nsub.op === Regexp.Op.ALTERNATE) {
|
|
4083
|
+
state.changed = true;
|
|
4084
|
+
for (let j = 0; j < nsub.subs.length; j++) state.subs.push(nsub.subs[j]);
|
|
4085
|
+
return;
|
|
4086
|
+
}
|
|
4087
|
+
}
|
|
4088
|
+
state.subs.push(nsub);
|
|
4089
|
+
}
|
|
4090
|
+
static leave(re, state) {
|
|
3801
4091
|
switch (re.op) {
|
|
3802
4092
|
case Regexp.Op.PLB:
|
|
3803
4093
|
case Regexp.Op.NLB:
|
|
3804
4094
|
case Regexp.Op.CAPTURE: {
|
|
3805
|
-
const sub =
|
|
4095
|
+
const sub = state.sub;
|
|
3806
4096
|
if (sub !== re.subs[0]) {
|
|
3807
4097
|
const nre = Regexp.fromRegexp(re);
|
|
3808
|
-
nre.runes =
|
|
4098
|
+
nre.runes = /* @__PURE__ */ new Int32Array(0);
|
|
3809
4099
|
nre.subs = [sub];
|
|
3810
4100
|
return nre;
|
|
3811
4101
|
}
|
|
3812
4102
|
return re;
|
|
3813
4103
|
}
|
|
3814
4104
|
case Regexp.Op.CONCAT:
|
|
3815
|
-
case Regexp.Op.ALTERNATE:
|
|
3816
|
-
|
|
3817
|
-
|
|
3818
|
-
for (let i = 0; i < re.subs.length; i++) {
|
|
3819
|
-
const sub = re.subs[i];
|
|
3820
|
-
const nsub = Simplify.simplify(sub);
|
|
3821
|
-
if (nsub !== sub) changed = true;
|
|
3822
|
-
if (re.op === Regexp.Op.CONCAT) {
|
|
3823
|
-
if (nsub.op === Regexp.Op.NO_MATCH) return new Regexp(Regexp.Op.NO_MATCH);
|
|
3824
|
-
if (nsub.op === Regexp.Op.EMPTY_MATCH) {
|
|
3825
|
-
changed = true;
|
|
3826
|
-
continue;
|
|
3827
|
-
}
|
|
3828
|
-
if (nsub.op === Regexp.Op.CONCAT) {
|
|
3829
|
-
changed = true;
|
|
3830
|
-
for (let j = 0; j < nsub.subs.length; j++) newSubs.push(nsub.subs[j]);
|
|
3831
|
-
continue;
|
|
3832
|
-
}
|
|
3833
|
-
} else if (re.op === Regexp.Op.ALTERNATE) {
|
|
3834
|
-
if (nsub.op === Regexp.Op.NO_MATCH) {
|
|
3835
|
-
changed = true;
|
|
3836
|
-
continue;
|
|
3837
|
-
}
|
|
3838
|
-
if (nsub.op === Regexp.Op.ALTERNATE) {
|
|
3839
|
-
changed = true;
|
|
3840
|
-
for (let j = 0; j < nsub.subs.length; j++) newSubs.push(nsub.subs[j]);
|
|
3841
|
-
continue;
|
|
3842
|
-
}
|
|
3843
|
-
}
|
|
3844
|
-
newSubs.push(nsub);
|
|
3845
|
-
}
|
|
3846
|
-
if (changed) {
|
|
4105
|
+
case Regexp.Op.ALTERNATE:
|
|
4106
|
+
if (state.changed) {
|
|
4107
|
+
const newSubs = state.subs;
|
|
3847
4108
|
if (newSubs.length === 0) return new Regexp(re.op === Regexp.Op.CONCAT ? Regexp.Op.EMPTY_MATCH : Regexp.Op.NO_MATCH);
|
|
3848
4109
|
if (newSubs.length === 1) return newSubs[0];
|
|
3849
4110
|
const nre = Regexp.fromRegexp(re);
|
|
3850
|
-
nre.runes =
|
|
4111
|
+
nre.runes = /* @__PURE__ */ new Int32Array(0);
|
|
3851
4112
|
nre.subs = newSubs;
|
|
3852
4113
|
return nre;
|
|
3853
4114
|
}
|
|
3854
4115
|
return re;
|
|
3855
|
-
}
|
|
3856
|
-
case Regexp.Op.CHAR_CLASS:
|
|
3857
|
-
if (re.runes === null) return re;
|
|
3858
|
-
if (re.runes.length === 0) return new Regexp(Regexp.Op.NO_MATCH);
|
|
3859
|
-
if (re.runes.length === 2 && re.runes[0] === 0 && re.runes[1] === Unicode.MAX_RUNE) return new Regexp(Regexp.Op.ANY_CHAR);
|
|
3860
|
-
if (re.runes.length === 4 && re.runes[0] === 0 && re.runes[1] === Codepoint.CODES.get("\n") - 1 && re.runes[2] === Codepoint.CODES.get("\n") + 1 && re.runes[3] === Unicode.MAX_RUNE) return new Regexp(Regexp.Op.ANY_CHAR_NOT_NL);
|
|
3861
|
-
return re;
|
|
3862
4116
|
case Regexp.Op.STAR:
|
|
3863
4117
|
case Regexp.Op.PLUS:
|
|
3864
|
-
case Regexp.Op.QUEST:
|
|
3865
|
-
|
|
3866
|
-
|
|
3867
|
-
|
|
3868
|
-
|
|
3869
|
-
|
|
3870
|
-
|
|
3871
|
-
|
|
3872
|
-
|
|
3873
|
-
|
|
3874
|
-
|
|
3875
|
-
|
|
3876
|
-
|
|
3877
|
-
|
|
3878
|
-
|
|
3879
|
-
|
|
3880
|
-
|
|
3881
|
-
|
|
3882
|
-
|
|
3883
|
-
|
|
3884
|
-
|
|
3885
|
-
|
|
3886
|
-
|
|
3887
|
-
|
|
3888
|
-
|
|
3889
|
-
|
|
3890
|
-
|
|
3891
|
-
|
|
3892
|
-
|
|
3893
|
-
|
|
3894
|
-
|
|
3895
|
-
|
|
3896
|
-
|
|
3897
|
-
|
|
3898
|
-
|
|
3899
|
-
|
|
3900
|
-
|
|
3901
|
-
|
|
3902
|
-
return new Regexp(Regexp.Op.NO_MATCH);
|
|
4118
|
+
case Regexp.Op.QUEST: return Simplify.simplify1(re.op, re.flags, state.sub, re);
|
|
4119
|
+
case Regexp.Op.REPEAT: return Simplify.simplifyRepeat(re, state.sub);
|
|
4120
|
+
default: return re;
|
|
4121
|
+
}
|
|
4122
|
+
}
|
|
4123
|
+
static simplifyRepeat(re, sub) {
|
|
4124
|
+
if (re.max === -1) {
|
|
4125
|
+
if (re.min === 0) return Simplify.simplify1(Regexp.Op.STAR, re.flags, sub, null);
|
|
4126
|
+
if (re.min === 1) return Simplify.simplify1(Regexp.Op.PLUS, re.flags, sub, null);
|
|
4127
|
+
const subs = [];
|
|
4128
|
+
for (let i = 0; i < re.min - 1; i++) subs.push(sub);
|
|
4129
|
+
subs.push(Simplify.simplify1(Regexp.Op.PLUS, re.flags, sub, null));
|
|
4130
|
+
return Simplify.concat(subs);
|
|
4131
|
+
}
|
|
4132
|
+
if (re.min === 1 && re.max === 1) return sub;
|
|
4133
|
+
let prefixSubs = null;
|
|
4134
|
+
if (re.min > 0) {
|
|
4135
|
+
prefixSubs = [];
|
|
4136
|
+
for (let i = 0; i < re.min; i++) prefixSubs.push(sub);
|
|
4137
|
+
}
|
|
4138
|
+
if (re.max > re.min) {
|
|
4139
|
+
let suffix = Simplify.simplify1(Regexp.Op.QUEST, re.flags, sub, null);
|
|
4140
|
+
for (let i = re.min + 1; i < re.max; i++) suffix = Simplify.simplify1(Regexp.Op.QUEST, re.flags, Simplify.concat([sub, suffix]), null);
|
|
4141
|
+
if (prefixSubs === null) return suffix;
|
|
4142
|
+
prefixSubs.push(suffix);
|
|
4143
|
+
}
|
|
4144
|
+
if (prefixSubs !== null) return Simplify.concat(prefixSubs);
|
|
4145
|
+
return new Regexp(Regexp.Op.NO_MATCH);
|
|
4146
|
+
}
|
|
4147
|
+
static concat(subs) {
|
|
4148
|
+
const newSubs = [];
|
|
4149
|
+
for (let i = 0; i < subs.length; i++) {
|
|
4150
|
+
const sub = subs[i];
|
|
4151
|
+
if (sub.op === Regexp.Op.NO_MATCH) return new Regexp(Regexp.Op.NO_MATCH);
|
|
4152
|
+
if (sub.op === Regexp.Op.EMPTY_MATCH) continue;
|
|
4153
|
+
if (sub.op === Regexp.Op.CONCAT) {
|
|
4154
|
+
for (let j = 0; j < sub.subs.length; j++) newSubs.push(sub.subs[j]);
|
|
4155
|
+
continue;
|
|
3903
4156
|
}
|
|
4157
|
+
newSubs.push(sub);
|
|
3904
4158
|
}
|
|
3905
|
-
return
|
|
4159
|
+
if (newSubs.length === 0) return new Regexp(Regexp.Op.EMPTY_MATCH);
|
|
4160
|
+
if (newSubs.length === 1) return newSubs[0];
|
|
4161
|
+
const nre = new Regexp(Regexp.Op.CONCAT);
|
|
4162
|
+
nre.subs = newSubs;
|
|
4163
|
+
return nre;
|
|
3906
4164
|
}
|
|
3907
4165
|
static simplify1(op, flags, sub, re) {
|
|
3908
4166
|
if (sub.op === Regexp.Op.EMPTY_MATCH) return sub;
|
|
@@ -4070,46 +4328,35 @@ var CharClass = class CharClass {
|
|
|
4070
4328
|
result += "]";
|
|
4071
4329
|
return result;
|
|
4072
4330
|
}
|
|
4073
|
-
static
|
|
4074
|
-
const
|
|
4075
|
-
|
|
4076
|
-
|
|
4077
|
-
|
|
4078
|
-
const
|
|
4079
|
-
|
|
4080
|
-
|
|
4081
|
-
|
|
4082
|
-
let j = right;
|
|
4083
|
-
while (i <= j) {
|
|
4084
|
-
while (i < right && CharClass.cmp(array, i, pivotFrom, pivotTo) < 0) i += 2;
|
|
4085
|
-
while (j > left && CharClass.cmp(array, j, pivotFrom, pivotTo) > 0) j -= 2;
|
|
4086
|
-
if (i <= j) {
|
|
4087
|
-
if (i !== j) {
|
|
4088
|
-
let temp = array[i];
|
|
4089
|
-
array[i] = array[j];
|
|
4090
|
-
array[j] = temp;
|
|
4091
|
-
temp = array[i + 1];
|
|
4092
|
-
array[i + 1] = array[j + 1];
|
|
4093
|
-
array[j + 1] = temp;
|
|
4094
|
-
}
|
|
4095
|
-
i += 2;
|
|
4096
|
-
j -= 2;
|
|
4097
|
-
}
|
|
4331
|
+
static sortRanges(array, len) {
|
|
4332
|
+
const n = len >> 1;
|
|
4333
|
+
const order = new Array(n);
|
|
4334
|
+
for (let i = 0; i < n; i++) order[i] = i;
|
|
4335
|
+
order.sort((a, b) => array[2 * a] - array[2 * b] || array[2 * b + 1] - array[2 * a + 1]);
|
|
4336
|
+
const sorted = array.slice(0, len);
|
|
4337
|
+
for (let i = 0; i < n; i++) {
|
|
4338
|
+
array[2 * i] = sorted[2 * order[i]];
|
|
4339
|
+
array[2 * i + 1] = sorted[2 * order[i] + 1];
|
|
4098
4340
|
}
|
|
4099
|
-
if (left < j) CharClass.qsortIntPair(array, left, j);
|
|
4100
|
-
if (i < right) CharClass.qsortIntPair(array, i, right);
|
|
4101
4341
|
}
|
|
4102
4342
|
constructor(r = Utils.emptyInts()) {
|
|
4103
4343
|
this.r = r;
|
|
4104
4344
|
this.len = r.length;
|
|
4105
4345
|
}
|
|
4106
4346
|
toArray() {
|
|
4107
|
-
if (this.len === this.r.length
|
|
4108
|
-
|
|
4347
|
+
if (this.r instanceof Int32Array) return this.len === this.r.length ? this.r : this.r.subarray(0, this.len);
|
|
4348
|
+
return new Int32Array(this.len === this.r.length ? this.r : this.r.slice(0, this.len));
|
|
4349
|
+
}
|
|
4350
|
+
toGrowableArray() {
|
|
4351
|
+
if (Array.isArray(this.r)) {
|
|
4352
|
+
this.r.length = this.len;
|
|
4353
|
+
return this.r;
|
|
4354
|
+
}
|
|
4355
|
+
return Array.from(this.r.subarray(0, this.len));
|
|
4109
4356
|
}
|
|
4110
4357
|
cleanClass() {
|
|
4111
4358
|
if (this.len < 4) return this;
|
|
4112
|
-
CharClass.
|
|
4359
|
+
CharClass.sortRanges(this.r, this.len);
|
|
4113
4360
|
let w = 2;
|
|
4114
4361
|
for (let i = 2; i < this.len; i += 2) {
|
|
4115
4362
|
const lo = this.r[i];
|
|
@@ -4313,7 +4560,7 @@ var Parser = class Parser {
|
|
|
4313
4560
|
static ERR_LARGE = "expression too large";
|
|
4314
4561
|
static ERR_INVALID_CAPTURE_IN_LOOKBEHIND = "invalid capture in lookbehind";
|
|
4315
4562
|
static MAX_HEIGHT = 1e3;
|
|
4316
|
-
static MAX_SIZE =
|
|
4563
|
+
static MAX_SIZE = 1398101;
|
|
4317
4564
|
static MAX_RUNES = 33554432;
|
|
4318
4565
|
static ANY_TABLE = new UnicodeRangeTable(new Uint32Array([
|
|
4319
4566
|
0,
|
|
@@ -4455,15 +4702,17 @@ var Parser = class Parser {
|
|
|
4455
4702
|
case Regexp.Op.ANY_CHAR_NOT_NL:
|
|
4456
4703
|
if (Parser.matchRune(src, Codepoint.CODES.get("\n"))) dst.op = Regexp.Op.ANY_CHAR;
|
|
4457
4704
|
break;
|
|
4458
|
-
case Regexp.Op.CHAR_CLASS:
|
|
4459
|
-
|
|
4460
|
-
|
|
4705
|
+
case Regexp.Op.CHAR_CLASS: {
|
|
4706
|
+
const cc = new CharClass(Array.isArray(dst.runes) ? dst.runes : Array.from(dst.runes));
|
|
4707
|
+
if (src.op === Regexp.Op.LITERAL) cc.appendLiteral(src.runes[0], src.flags);
|
|
4708
|
+
else cc.appendClass(src.runes);
|
|
4709
|
+
dst.runes = cc.toGrowableArray();
|
|
4461
4710
|
break;
|
|
4711
|
+
}
|
|
4462
4712
|
case Regexp.Op.LITERAL:
|
|
4463
4713
|
if (src.runes[0] === dst.runes[0] && src.flags === dst.flags) break;
|
|
4464
4714
|
dst.op = Regexp.Op.CHAR_CLASS;
|
|
4465
|
-
dst.runes = new CharClass().appendLiteral(dst.runes[0], dst.flags).appendLiteral(src.runes[0], src.flags).
|
|
4466
|
-
break;
|
|
4715
|
+
dst.runes = new CharClass().appendLiteral(dst.runes[0], dst.flags).appendLiteral(src.runes[0], src.flags).toGrowableArray();
|
|
4467
4716
|
}
|
|
4468
4717
|
}
|
|
4469
4718
|
static parseEscape(t) {
|
|
@@ -4520,9 +4769,7 @@ var Parser = class Parser {
|
|
|
4520
4769
|
case Codepoint.CODES.get("r"): return Codepoint.CODES.get("\r");
|
|
4521
4770
|
case Codepoint.CODES.get("t"): return Codepoint.CODES.get(" ");
|
|
4522
4771
|
case Codepoint.CODES.get("v"): return Codepoint.CODES.get("\v");
|
|
4523
|
-
default:
|
|
4524
|
-
if (c <= Unicode.MAX_ASCII && !Utils.isalnum(c)) return c;
|
|
4525
|
-
break;
|
|
4772
|
+
default: if (c <= Unicode.MAX_ASCII && !Utils.isalnum(c)) return c;
|
|
4526
4773
|
}
|
|
4527
4774
|
throw new RE2JSSyntaxException(Parser.ERR_INVALID_ESCAPE, t.from(startPos));
|
|
4528
4775
|
}
|
|
@@ -4531,10 +4778,6 @@ var Parser = class Parser {
|
|
|
4531
4778
|
if (t.lookingAt("\\")) return Parser.parseEscape(t);
|
|
4532
4779
|
return t.pop();
|
|
4533
4780
|
}
|
|
4534
|
-
static concatRunes(x, y) {
|
|
4535
|
-
for (let i = 0; i < y.length; i++) x.push(y[i]);
|
|
4536
|
-
return x;
|
|
4537
|
-
}
|
|
4538
4781
|
static hasCapture(re) {
|
|
4539
4782
|
if (re === null) return false;
|
|
4540
4783
|
if (re.op === Regexp.Op.CAPTURE) return true;
|
|
@@ -4665,9 +4908,7 @@ var Parser = class Parser {
|
|
|
4665
4908
|
const n = this.stack.length;
|
|
4666
4909
|
let i = n;
|
|
4667
4910
|
while (i > 0 && !Regexp.isPseudoOp(this.stack[i - 1].op)) i--;
|
|
4668
|
-
|
|
4669
|
-
this.stack = this.stack.slice(0, i);
|
|
4670
|
-
return r;
|
|
4911
|
+
return this.stack.splice(i, n - i);
|
|
4671
4912
|
}
|
|
4672
4913
|
push(re) {
|
|
4673
4914
|
this.numRunes += re.runes.length;
|
|
@@ -4692,7 +4933,8 @@ var Parser = class Parser {
|
|
|
4692
4933
|
const re1 = this.stack[n - 1];
|
|
4693
4934
|
const re2 = this.stack[n - 2];
|
|
4694
4935
|
if (re1.op !== Regexp.Op.LITERAL || re2.op !== Regexp.Op.LITERAL || (re1.flags & RE2Flags.FOLD_CASE) !== (re2.flags & RE2Flags.FOLD_CASE)) return false;
|
|
4695
|
-
re2.runes =
|
|
4936
|
+
if (!Array.isArray(re2.runes)) re2.runes = Array.from(re2.runes);
|
|
4937
|
+
for (let i = 0; i < re1.runes.length; i++) re2.runes.push(re1.runes[i]);
|
|
4696
4938
|
if (r >= 0) {
|
|
4697
4939
|
re1.runes = [r];
|
|
4698
4940
|
re1.flags = flags;
|
|
@@ -4764,12 +5006,12 @@ var Parser = class Parser {
|
|
|
4764
5006
|
}
|
|
4765
5007
|
cleanAlt(re) {
|
|
4766
5008
|
if (re.op === Regexp.Op.CHAR_CLASS) {
|
|
4767
|
-
re.runes = new CharClass(re.runes).cleanClass().toArray();
|
|
5009
|
+
re.runes = new CharClass(Array.from(re.runes)).cleanClass().toArray();
|
|
4768
5010
|
if (re.runes.length === 2 && re.runes[0] === 0 && re.runes[1] === Unicode.MAX_RUNE) {
|
|
4769
|
-
re.runes =
|
|
5011
|
+
re.runes = /* @__PURE__ */ new Int32Array(0);
|
|
4770
5012
|
re.op = Regexp.Op.ANY_CHAR;
|
|
4771
5013
|
} else if (re.runes.length === 4 && re.runes[0] === 0 && re.runes[1] === Codepoint.CODES.get("\n") - 1 && re.runes[2] === Codepoint.CODES.get("\n") + 1 && re.runes[3] === Unicode.MAX_RUNE) {
|
|
4772
|
-
re.runes =
|
|
5014
|
+
re.runes = /* @__PURE__ */ new Int32Array(0);
|
|
4773
5015
|
re.op = Regexp.Op.ANY_CHAR_NOT_NL;
|
|
4774
5016
|
}
|
|
4775
5017
|
}
|
|
@@ -4929,9 +5171,7 @@ var Parser = class Parser {
|
|
|
4929
5171
|
this.reuse(old);
|
|
4930
5172
|
break;
|
|
4931
5173
|
}
|
|
4932
|
-
default:
|
|
4933
|
-
re.subs = re.subs.slice(1, re.subs.length);
|
|
4934
|
-
break;
|
|
5174
|
+
default: re.subs = re.subs.slice(1, re.subs.length);
|
|
4935
5175
|
}
|
|
4936
5176
|
}
|
|
4937
5177
|
return re;
|
|
@@ -5030,9 +5270,7 @@ var Parser = class Parser {
|
|
|
5030
5270
|
case Codepoint.CODES.get("+"):
|
|
5031
5271
|
op = Regexp.Op.PLUS;
|
|
5032
5272
|
break;
|
|
5033
|
-
case Codepoint.CODES.get("?"):
|
|
5034
|
-
op = Regexp.Op.QUEST;
|
|
5035
|
-
break;
|
|
5273
|
+
case Codepoint.CODES.get("?"): op = Regexp.Op.QUEST;
|
|
5036
5274
|
}
|
|
5037
5275
|
this.repeat(op, min, max, repeatPos, t, lastRepeatPos);
|
|
5038
5276
|
break;
|
|
@@ -5083,9 +5321,7 @@ var Parser = class Parser {
|
|
|
5083
5321
|
case Codepoint.CODES.get("z"):
|
|
5084
5322
|
this.op(Regexp.Op.END_TEXT);
|
|
5085
5323
|
break bigswitch;
|
|
5086
|
-
default:
|
|
5087
|
-
t.rewindTo(savedPos);
|
|
5088
|
-
break;
|
|
5324
|
+
default: t.rewindTo(savedPos);
|
|
5089
5325
|
}
|
|
5090
5326
|
else t.rewindTo(savedPos);
|
|
5091
5327
|
const re = this.newRegexp(Regexp.Op.CHAR_CLASS);
|
|
@@ -5109,9 +5345,7 @@ var Parser = class Parser {
|
|
|
5109
5345
|
this.literal(Parser.parseEscape(t));
|
|
5110
5346
|
break;
|
|
5111
5347
|
}
|
|
5112
|
-
default:
|
|
5113
|
-
this.literal(t.pop());
|
|
5114
|
-
break;
|
|
5348
|
+
default: this.literal(t.pop());
|
|
5115
5349
|
}
|
|
5116
5350
|
lastRepeatPos = repeatPos;
|
|
5117
5351
|
}
|
|
@@ -5309,7 +5543,7 @@ var Parser = class Parser {
|
|
|
5309
5543
|
if ((this.flags & RE2Flags.FOLD_CASE) === 0 || fold === null) cc.appendTableWithSign(tab, sign);
|
|
5310
5544
|
else {
|
|
5311
5545
|
const tmp = new CharClass().appendTable(tab).appendTable(fold).cleanClass().toArray();
|
|
5312
|
-
cc.appendClassWithSign(tmp, sign);
|
|
5546
|
+
cc.appendClassWithSign(Array.from(tmp), sign);
|
|
5313
5547
|
}
|
|
5314
5548
|
return true;
|
|
5315
5549
|
}
|
|
@@ -5365,24 +5599,6 @@ var Parser = class Parser {
|
|
|
5365
5599
|
};
|
|
5366
5600
|
//#endregion
|
|
5367
5601
|
//#region src/RE2.js
|
|
5368
|
-
var AtomicReference = class {
|
|
5369
|
-
constructor(initialValue) {
|
|
5370
|
-
this.value = initialValue;
|
|
5371
|
-
}
|
|
5372
|
-
get() {
|
|
5373
|
-
return this.value;
|
|
5374
|
-
}
|
|
5375
|
-
set(newValue) {
|
|
5376
|
-
this.value = newValue;
|
|
5377
|
-
}
|
|
5378
|
-
compareAndSet(expect, update) {
|
|
5379
|
-
if (this.value === expect) {
|
|
5380
|
-
this.value = update;
|
|
5381
|
-
return true;
|
|
5382
|
-
}
|
|
5383
|
-
return false;
|
|
5384
|
-
}
|
|
5385
|
-
};
|
|
5386
5602
|
/**
|
|
5387
5603
|
* An RE2 class instance is a compiled representation of an RE2 regular expression, independent of
|
|
5388
5604
|
* the public Java-like Pattern/Matcher API.
|
|
@@ -5471,7 +5687,7 @@ var RE2 = class RE2 {
|
|
|
5471
5687
|
this.prefixUTF8 = null;
|
|
5472
5688
|
this.prefixComplete = false;
|
|
5473
5689
|
this.prefixRune = 0;
|
|
5474
|
-
this.
|
|
5690
|
+
this.machinePool = [];
|
|
5475
5691
|
this.dfa = new DFA(this.prog);
|
|
5476
5692
|
this.onepass = OnePass.compile(this.prog);
|
|
5477
5693
|
this.prefilter = null;
|
|
@@ -5505,7 +5721,10 @@ var RE2 = class RE2 {
|
|
|
5505
5721
|
}
|
|
5506
5722
|
return [];
|
|
5507
5723
|
}
|
|
5508
|
-
|
|
5724
|
+
createLookbehindState() {
|
|
5725
|
+
return this.prog.numLb > 0 ? new LookbehindState(this.prog) : null;
|
|
5726
|
+
}
|
|
5727
|
+
executeEngine(input, pos, anchor, ncap, lbState = null) {
|
|
5509
5728
|
if (this.prefixComplete && (ncap === 0 || this.numSubexp === 0)) return this.matchPrefixComplete(input, pos, anchor, ncap);
|
|
5510
5729
|
if (this.prefilter !== null && anchor === RE2Flags.UNANCHORED) {
|
|
5511
5730
|
if (!this.prefilter.eval(input, pos)) return null;
|
|
@@ -5513,14 +5732,14 @@ var RE2 = class RE2 {
|
|
|
5513
5732
|
if (this.onepass !== null) return OnePass.execute(this, input, pos, anchor, ncap);
|
|
5514
5733
|
if (ncap > 0) {
|
|
5515
5734
|
if (this.prog.numLb === 0 && input.endPos() <= Backtracker.maxBitStateLen(this.prog)) return Backtracker.execute(this, input, pos, anchor, ncap);
|
|
5516
|
-
return this.doExecuteNFA(input, pos, anchor, ncap);
|
|
5735
|
+
return this.doExecuteNFA(input, pos, anchor, ncap, lbState);
|
|
5517
5736
|
}
|
|
5518
5737
|
if (this.prog.numLb === 0) {
|
|
5519
5738
|
const dfaResult = this.dfa.match(input, pos, anchor);
|
|
5520
5739
|
if (dfaResult !== null) return dfaResult ? [] : null;
|
|
5521
5740
|
if (input.endPos() <= Backtracker.maxBitStateLen(this.prog)) return Backtracker.execute(this, input, pos, anchor, ncap);
|
|
5522
5741
|
}
|
|
5523
|
-
return this.doExecuteNFA(input, pos, anchor, ncap);
|
|
5742
|
+
return this.doExecuteNFA(input, pos, anchor, ncap, lbState);
|
|
5524
5743
|
}
|
|
5525
5744
|
/**
|
|
5526
5745
|
* Returns the number of parenthesized subexpressions in this regular expression.
|
|
@@ -5535,42 +5754,23 @@ var RE2 = class RE2 {
|
|
|
5535
5754
|
return this.prog.numInst();
|
|
5536
5755
|
}
|
|
5537
5756
|
get() {
|
|
5538
|
-
|
|
5539
|
-
do
|
|
5540
|
-
head = this.pooled.get();
|
|
5541
|
-
while (head && !this.pooled.compareAndSet(head, head.next));
|
|
5542
|
-
return head;
|
|
5757
|
+
return this.machinePool.length > 0 ? this.machinePool.pop() : null;
|
|
5543
5758
|
}
|
|
5544
5759
|
reset() {
|
|
5545
|
-
this.
|
|
5546
|
-
}
|
|
5547
|
-
put(m
|
|
5548
|
-
|
|
5549
|
-
do {
|
|
5550
|
-
head = this.pooled.get();
|
|
5551
|
-
if (!isNew && head) {
|
|
5552
|
-
m = Machine.fromMachine(m);
|
|
5553
|
-
isNew = true;
|
|
5554
|
-
}
|
|
5555
|
-
if (m.next !== head) m.next = head;
|
|
5556
|
-
} while (!this.pooled.compareAndSet(head, m));
|
|
5760
|
+
this.machinePool.length = 0;
|
|
5761
|
+
}
|
|
5762
|
+
put(m) {
|
|
5763
|
+
this.machinePool.push(m);
|
|
5557
5764
|
}
|
|
5558
5765
|
toString() {
|
|
5559
5766
|
return this.expr;
|
|
5560
5767
|
}
|
|
5561
|
-
doExecuteNFA(input, pos, anchor, ncap) {
|
|
5768
|
+
doExecuteNFA(input, pos, anchor, ncap, lbState = null) {
|
|
5562
5769
|
let m = this.get();
|
|
5563
|
-
|
|
5564
|
-
if (!m) {
|
|
5565
|
-
m = Machine.fromRE2(this);
|
|
5566
|
-
isNew = true;
|
|
5567
|
-
} else if (m.next !== null) {
|
|
5568
|
-
m = Machine.fromMachine(m);
|
|
5569
|
-
isNew = true;
|
|
5570
|
-
}
|
|
5770
|
+
if (!m) m = Machine.fromRE2(this);
|
|
5571
5771
|
m.init(ncap);
|
|
5572
|
-
const cap = m.match(input, pos, anchor) ? m.submatches() : null;
|
|
5573
|
-
this.put(m
|
|
5772
|
+
const cap = m.match(input, pos, anchor, lbState) ? m.submatches() : null;
|
|
5773
|
+
this.put(m);
|
|
5574
5774
|
return cap;
|
|
5575
5775
|
}
|
|
5576
5776
|
match(s) {
|
|
@@ -5588,17 +5788,21 @@ var RE2 = class RE2 {
|
|
|
5588
5788
|
* @param anchor the anchoring flag (UNANCHORED, ANCHOR_START, ANCHOR_BOTH)
|
|
5589
5789
|
* @param group the array to fill with submatch positions
|
|
5590
5790
|
* @param ngroup the number of array pairs to fill in
|
|
5791
|
+
* @param lbState optional state carried between successive matches over the same input (see
|
|
5792
|
+
* createLookbehindState); omit it to evaluate lookbehinds from the beginning of the input
|
|
5591
5793
|
* @returns true if a match was found
|
|
5592
5794
|
*/
|
|
5593
|
-
matchWithGroup(input, start, end, anchor, ngroup) {
|
|
5594
|
-
if (!(input instanceof MatcherInputBase))
|
|
5595
|
-
|
|
5596
|
-
|
|
5795
|
+
matchWithGroup(input, start, end, anchor, ngroup, lbState = null) {
|
|
5796
|
+
if (!(input instanceof MatcherInputBase)) {
|
|
5797
|
+
if (Utils.isByteArray(input)) input = MatcherInput.utf8(input);
|
|
5798
|
+
else input = MatcherInput.utf16(input);
|
|
5799
|
+
}
|
|
5800
|
+
return this.matchMachineInput(input, start, end, anchor, ngroup, lbState);
|
|
5597
5801
|
}
|
|
5598
|
-
matchMachineInput(input, start, end, anchor, ngroup) {
|
|
5802
|
+
matchMachineInput(input, start, end, anchor, ngroup, lbState = null) {
|
|
5599
5803
|
if (start > end) return [false, null];
|
|
5600
5804
|
const machineInput = input.isUTF16Encoding() ? MachineInput.fromUTF16(input.asCharSequence(), 0, end) : MachineInput.fromUTF8(input.asBytes(), 0, end);
|
|
5601
|
-
const groupMatch = this.executeEngine(machineInput, start, anchor, 2 * ngroup);
|
|
5805
|
+
const groupMatch = this.executeEngine(machineInput, start, anchor, 2 * ngroup, lbState);
|
|
5602
5806
|
if (groupMatch === null) return [false, null];
|
|
5603
5807
|
return [true, groupMatch];
|
|
5604
5808
|
}
|
|
@@ -5635,9 +5839,10 @@ var RE2 = class RE2 {
|
|
|
5635
5839
|
let searchPos = 0;
|
|
5636
5840
|
let out = "";
|
|
5637
5841
|
const input = MachineInput.fromUTF16(src);
|
|
5842
|
+
const lbState = this.createLookbehindState();
|
|
5638
5843
|
let numReplaces = 0;
|
|
5639
5844
|
while (searchPos <= src.length) {
|
|
5640
|
-
const a = this.executeEngine(input, searchPos, RE2Flags.UNANCHORED, 2);
|
|
5845
|
+
const a = this.executeEngine(input, searchPos, RE2Flags.UNANCHORED, 2, lbState);
|
|
5641
5846
|
if (a === null || a.length === 0) break;
|
|
5642
5847
|
out += src.substring(lastMatchEnd, a[0]);
|
|
5643
5848
|
if (a[1] > lastMatchEnd || a[0] === 0) {
|
|
@@ -5671,8 +5876,9 @@ var RE2 = class RE2 {
|
|
|
5671
5876
|
let pos = 0;
|
|
5672
5877
|
let i = 0;
|
|
5673
5878
|
let prevMatchEnd = -1;
|
|
5879
|
+
const lbState = this.createLookbehindState();
|
|
5674
5880
|
while (i < n && pos <= end) {
|
|
5675
|
-
const matches = this.executeEngine(input, pos, RE2Flags.UNANCHORED, this.prog.numCap);
|
|
5881
|
+
const matches = this.executeEngine(input, pos, RE2Flags.UNANCHORED, this.prog.numCap, lbState);
|
|
5676
5882
|
if (matches === null || matches.length === 0) break;
|
|
5677
5883
|
let accept = true;
|
|
5678
5884
|
if (matches[1] === pos) {
|
|
@@ -5942,7 +6148,9 @@ var RE2Set = class RE2Set {
|
|
|
5942
6148
|
*/
|
|
5943
6149
|
compile() {
|
|
5944
6150
|
if (this.prog) return;
|
|
5945
|
-
|
|
6151
|
+
const prog = Compiler.compileSet(this.regexps);
|
|
6152
|
+
if (prog.numInst() > Parser.MAX_SIZE) throw new RE2JSCompileException(`${Parser.ERR_LARGE}: the set compiles to ${prog.numInst()} instructions, more than ${Parser.MAX_SIZE}`);
|
|
6153
|
+
this.prog = prog;
|
|
5946
6154
|
this.dfa = new DFA(this.prog, this.maxMem);
|
|
5947
6155
|
this.dummyRe2 = {
|
|
5948
6156
|
prog: this.prog,
|
|
@@ -6436,7 +6644,7 @@ var RE2JS = class RE2JS {
|
|
|
6436
6644
|
}
|
|
6437
6645
|
result.push(m.substring(last, m.inputLength()));
|
|
6438
6646
|
}
|
|
6439
|
-
if (limit !== 0 || result.length === 0) result.push(m.substring(last, m.inputLength()));
|
|
6647
|
+
if (limit !== 0 || result.length === 0 && !(last === m.inputLength() && last > 0)) result.push(m.substring(last, m.inputLength()));
|
|
6440
6648
|
return result;
|
|
6441
6649
|
}
|
|
6442
6650
|
/**
|