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