re2js 2.8.6 → 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 +863 -577
- package/build/index.d.cts +284 -219
- package/build/index.d.ts +284 -219
- package/build/index.js +863 -577
- package/build/index.umd.js +863 -577
- package/package.json +30 -24
package/build/index.umd.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
|
(function(global, factory) {
|
|
@@ -503,6 +503,10 @@
|
|
|
503
503
|
*/
|
|
504
504
|
var Unicode = class Unicode {
|
|
505
505
|
static MAX_RUNE = 1114111;
|
|
506
|
+
static RUNE_ERROR = 65533;
|
|
507
|
+
static isUnsearchable(r) {
|
|
508
|
+
return r === Unicode.RUNE_ERROR || r >= Unicode.MIN_HIGH_SURROGATE && r <= Unicode.MAX_LOW_SURROGATE;
|
|
509
|
+
}
|
|
506
510
|
static MAX_ASCII = 127;
|
|
507
511
|
static MAX_LATIN1 = 255;
|
|
508
512
|
static MAX_BMP = 65535;
|
|
@@ -605,7 +609,7 @@
|
|
|
605
609
|
return [];
|
|
606
610
|
}
|
|
607
611
|
static isByteArray(input) {
|
|
608
|
-
return Array.isArray(input) || input
|
|
612
|
+
return Array.isArray(input) || Object.prototype.toString.call(input) === "[object Uint8Array]";
|
|
609
613
|
}
|
|
610
614
|
static isalnum(c) {
|
|
611
615
|
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");
|
|
@@ -664,7 +668,7 @@
|
|
|
664
668
|
runes.push(cp);
|
|
665
669
|
i += cp > Unicode.MAX_BMP ? 2 : 1;
|
|
666
670
|
}
|
|
667
|
-
return runes;
|
|
671
|
+
return new Int32Array(runes);
|
|
668
672
|
}
|
|
669
673
|
static runeToString(r) {
|
|
670
674
|
return String.fromCodePoint(r);
|
|
@@ -791,7 +795,7 @@
|
|
|
791
795
|
asCharSequence() {
|
|
792
796
|
throw Error("not implemented");
|
|
793
797
|
}
|
|
794
|
-
/** @returns {Uint8Array|number[]} */
|
|
798
|
+
/** @returns {Uint8Array|number[]|null} */
|
|
795
799
|
asBytes() {
|
|
796
800
|
throw Error("not implemented");
|
|
797
801
|
}
|
|
@@ -922,7 +926,8 @@
|
|
|
922
926
|
return 0;
|
|
923
927
|
}
|
|
924
928
|
};
|
|
925
|
-
var MachineUTF8Input = class extends MachineInputBase {
|
|
929
|
+
var MachineUTF8Input = class MachineUTF8Input extends MachineInputBase {
|
|
930
|
+
static RUNE_ERROR_STEP = Unicode.RUNE_ERROR << 3 | 1;
|
|
926
931
|
constructor(bytes, start = 0, end = bytes.length) {
|
|
927
932
|
super();
|
|
928
933
|
this.bytes = bytes;
|
|
@@ -936,33 +941,46 @@
|
|
|
936
941
|
return idx !== -1 && idx <= this.end - target.length;
|
|
937
942
|
}
|
|
938
943
|
hasAnyString(prefilter, pos) {
|
|
939
|
-
|
|
940
|
-
return prefilter.ac8.searchUTF8(this.bytes, this.start + pos, this.end);
|
|
944
|
+
return prefilter.automaton8().searchUTF8(this.bytes, this.start + pos, this.end);
|
|
941
945
|
}
|
|
942
946
|
step(pos) {
|
|
943
947
|
pos += this.start;
|
|
944
948
|
if (pos >= this.end) return MachineInputBase.EOF();
|
|
945
949
|
const c = this.bytes[pos] & 255;
|
|
946
950
|
if (c < 128) return c << 3 | 1;
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
951
|
+
let size;
|
|
952
|
+
let rune;
|
|
953
|
+
let lo = 128;
|
|
954
|
+
let hi = 191;
|
|
955
|
+
if (c >= 194 && c <= 223) {
|
|
956
|
+
size = 2;
|
|
957
|
+
rune = c & 31;
|
|
958
|
+
} else if (c >= 224 && c <= 239) {
|
|
959
|
+
size = 3;
|
|
960
|
+
rune = c & 15;
|
|
961
|
+
if (c === 224) lo = 160;
|
|
962
|
+
else if (c === 237) hi = 159;
|
|
963
|
+
} else if (c >= 240 && c <= 244) {
|
|
964
|
+
size = 4;
|
|
965
|
+
rune = c & 7;
|
|
966
|
+
if (c === 240) lo = 144;
|
|
967
|
+
else if (c === 244) hi = 143;
|
|
968
|
+
} else return MachineUTF8Input.RUNE_ERROR_STEP;
|
|
969
|
+
if (pos + size > this.end) return MachineUTF8Input.RUNE_ERROR_STEP;
|
|
970
|
+
const c1 = this.bytes[pos + 1] & 255;
|
|
971
|
+
if (c1 < lo || c1 > hi) return MachineUTF8Input.RUNE_ERROR_STEP;
|
|
972
|
+
rune = rune << 6 | c1 & 63;
|
|
973
|
+
if (size > 2) {
|
|
960
974
|
const c2 = this.bytes[pos + 2] & 255;
|
|
961
|
-
if ((c2 & 192) !== 128) return
|
|
962
|
-
|
|
963
|
-
if (
|
|
964
|
-
|
|
965
|
-
|
|
975
|
+
if ((c2 & 192) !== 128) return MachineUTF8Input.RUNE_ERROR_STEP;
|
|
976
|
+
rune = rune << 6 | c2 & 63;
|
|
977
|
+
if (size > 3) {
|
|
978
|
+
const c3 = this.bytes[pos + 3] & 255;
|
|
979
|
+
if ((c3 & 192) !== 128) return MachineUTF8Input.RUNE_ERROR_STEP;
|
|
980
|
+
rune = rune << 6 | c3 & 63;
|
|
981
|
+
}
|
|
982
|
+
}
|
|
983
|
+
return rune << 3 | size;
|
|
966
984
|
}
|
|
967
985
|
index(re2, pos) {
|
|
968
986
|
pos += this.start;
|
|
@@ -1027,8 +1045,7 @@
|
|
|
1027
1045
|
return idx !== -1 && idx <= this.end - prefilter.str.length;
|
|
1028
1046
|
}
|
|
1029
1047
|
hasAnyString(prefilter, pos) {
|
|
1030
|
-
|
|
1031
|
-
return prefilter.ac16.searchUTF16(this.charSequence, this.start + pos, this.end);
|
|
1048
|
+
return prefilter.automaton16().searchUTF16(this.charSequence, this.start + pos, this.end);
|
|
1032
1049
|
}
|
|
1033
1050
|
step(pos) {
|
|
1034
1051
|
pos += this.start;
|
|
@@ -1221,6 +1238,8 @@
|
|
|
1221
1238
|
this.namedGroups = re2.namedGroups;
|
|
1222
1239
|
/** @type {number} */
|
|
1223
1240
|
this.numberOfInstructions = re2.numberOfInstructions();
|
|
1241
|
+
/** @type {import('./Machine.js').LookbehindState|null} */
|
|
1242
|
+
this.lookbehindState = null;
|
|
1224
1243
|
if (input instanceof MatcherInputBase) this.resetMatcherInput(input);
|
|
1225
1244
|
else if (Utils.isByteArray(input)) this.resetMatcherInput(MatcherInput.utf8(input));
|
|
1226
1245
|
else this.resetMatcherInput(MatcherInput.utf16(input));
|
|
@@ -1254,9 +1273,13 @@
|
|
|
1254
1273
|
*/
|
|
1255
1274
|
resetMatcherInput(input) {
|
|
1256
1275
|
if (input === null) throw new Error("input is null");
|
|
1257
|
-
if (!(input instanceof MatcherInputBase))
|
|
1258
|
-
|
|
1276
|
+
if (!(input instanceof MatcherInputBase)) {
|
|
1277
|
+
if (Utils.isByteArray(input)) input = MatcherInput.utf8(input);
|
|
1278
|
+
else input = MatcherInput.utf16(input);
|
|
1279
|
+
}
|
|
1259
1280
|
this.matcherInput = input;
|
|
1281
|
+
if (this.lookbehindState !== null) this.lookbehindState.reset();
|
|
1282
|
+
else this.lookbehindState = this.patternInput.re2().createLookbehindState();
|
|
1260
1283
|
this.reset();
|
|
1261
1284
|
return this;
|
|
1262
1285
|
}
|
|
@@ -1344,11 +1367,11 @@
|
|
|
1344
1367
|
* @private
|
|
1345
1368
|
*/
|
|
1346
1369
|
loadGroup(group) {
|
|
1347
|
-
if (group < 0 || group > this.patternGroupCount) throw new RE2JSGroupException(`Group index out of bounds: ${group}`);
|
|
1370
|
+
if (!Number.isInteger(group) || group < 0 || group > this.patternGroupCount) throw new RE2JSGroupException(`Group index out of bounds: ${group}`);
|
|
1348
1371
|
if (!this.hasMatch) throw new RE2JSGroupException("perhaps no match attempted");
|
|
1349
1372
|
if (group === 0 || this.hasGroups) return;
|
|
1350
1373
|
const end = this.matcherInputLength;
|
|
1351
|
-
const res = this.patternInput.re2().matchMachineInput(this.matcherInput, this.groups[0], end, this.anchorFlag, 1 + this.patternGroupCount);
|
|
1374
|
+
const res = this.patternInput.re2().matchMachineInput(this.matcherInput, this.groups[0], end, this.anchorFlag, 1 + this.patternGroupCount, this.lookbehindState);
|
|
1352
1375
|
if (!res[0]) throw new RE2JSGroupException("inconsistency in matching group data");
|
|
1353
1376
|
this.groups = res[1];
|
|
1354
1377
|
this.hasGroups = true;
|
|
@@ -1381,7 +1404,7 @@
|
|
|
1381
1404
|
*/
|
|
1382
1405
|
find(start = null) {
|
|
1383
1406
|
if (start !== null) {
|
|
1384
|
-
if (start < 0 || start > this.matcherInputLength) throw new RE2JSGroupException(`start index out of bounds: ${start}`);
|
|
1407
|
+
if (!Number.isInteger(start) || start < 0 || start > this.matcherInputLength) throw new RE2JSGroupException(`start index out of bounds: ${start}`);
|
|
1385
1408
|
this.reset();
|
|
1386
1409
|
return this.genMatch(start, 0);
|
|
1387
1410
|
}
|
|
@@ -1404,7 +1427,7 @@
|
|
|
1404
1427
|
* @private
|
|
1405
1428
|
*/
|
|
1406
1429
|
genMatch(startByte, anchor) {
|
|
1407
|
-
const res = this.patternInput.re2().matchMachineInput(this.matcherInput, startByte, this.matcherInputLength, anchor, 1);
|
|
1430
|
+
const res = this.patternInput.re2().matchMachineInput(this.matcherInput, startByte, this.matcherInputLength, anchor, 1, this.lookbehindState);
|
|
1408
1431
|
if (!res[0]) {
|
|
1409
1432
|
this.hasMatch = false;
|
|
1410
1433
|
return false;
|
|
@@ -1733,7 +1756,8 @@
|
|
|
1733
1756
|
this.op = op;
|
|
1734
1757
|
this.out = 0;
|
|
1735
1758
|
this.arg = 0;
|
|
1736
|
-
|
|
1759
|
+
/** @type {Int32Array} */
|
|
1760
|
+
this.runes = /* @__PURE__ */ new Int32Array(0);
|
|
1737
1761
|
/** @type {Uint32Array | number[] | null} */
|
|
1738
1762
|
this.next = null;
|
|
1739
1763
|
}
|
|
@@ -1822,19 +1846,27 @@
|
|
|
1822
1846
|
};
|
|
1823
1847
|
//#endregion
|
|
1824
1848
|
//#region src/Machine.js
|
|
1825
|
-
var Queue = class {
|
|
1849
|
+
var Queue = class Queue {
|
|
1826
1850
|
constructor(numInst) {
|
|
1827
1851
|
this.sparse = new Int32Array(numInst);
|
|
1828
1852
|
this.densePcs = new Int32Array(numInst);
|
|
1829
1853
|
this.denseCaps = null;
|
|
1830
1854
|
this.size = 0;
|
|
1831
1855
|
this.ncap = 0;
|
|
1856
|
+
this.mainThreads = 0;
|
|
1832
1857
|
}
|
|
1858
|
+
static INITIAL_THREADS = 32;
|
|
1833
1859
|
init(ncap) {
|
|
1834
1860
|
this.ncap = ncap;
|
|
1835
|
-
const needed = this.densePcs.length * ncap;
|
|
1861
|
+
const needed = Math.min(this.densePcs.length, Queue.INITIAL_THREADS) * ncap;
|
|
1836
1862
|
if (!this.denseCaps || this.denseCaps.length < needed) this.denseCaps = new Int32Array(needed);
|
|
1837
1863
|
}
|
|
1864
|
+
growCaps(needed) {
|
|
1865
|
+
const limit = this.densePcs.length * this.ncap;
|
|
1866
|
+
const grown = new Int32Array(Math.min(limit, Math.max(needed, 2 * this.denseCaps.length)));
|
|
1867
|
+
grown.set(this.denseCaps);
|
|
1868
|
+
this.denseCaps = grown;
|
|
1869
|
+
}
|
|
1838
1870
|
contains(pc) {
|
|
1839
1871
|
const j = this.sparse[pc];
|
|
1840
1872
|
return j < this.size && this.densePcs[j] === pc;
|
|
@@ -1850,6 +1882,7 @@
|
|
|
1850
1882
|
}
|
|
1851
1883
|
clear() {
|
|
1852
1884
|
this.size = 0;
|
|
1885
|
+
this.mainThreads = 0;
|
|
1853
1886
|
}
|
|
1854
1887
|
toString() {
|
|
1855
1888
|
let out = "{";
|
|
@@ -1861,6 +1894,18 @@
|
|
|
1861
1894
|
return out;
|
|
1862
1895
|
}
|
|
1863
1896
|
};
|
|
1897
|
+
var LookbehindState = class {
|
|
1898
|
+
constructor(prog) {
|
|
1899
|
+
this.pos = -1;
|
|
1900
|
+
this.pcs = new Int32Array(prog.numInst());
|
|
1901
|
+
this.size = 0;
|
|
1902
|
+
this.lbTable = new Int32Array(prog.numLb + 1);
|
|
1903
|
+
}
|
|
1904
|
+
reset() {
|
|
1905
|
+
this.pos = -1;
|
|
1906
|
+
this.size = 0;
|
|
1907
|
+
}
|
|
1908
|
+
};
|
|
1864
1909
|
var Machine = class Machine {
|
|
1865
1910
|
static fromRE2(re2) {
|
|
1866
1911
|
const m = new Machine();
|
|
@@ -1868,19 +1913,18 @@
|
|
|
1868
1913
|
m.re2 = re2;
|
|
1869
1914
|
m.q0 = new Queue(m.prog.numInst());
|
|
1870
1915
|
m.q1 = new Queue(m.prog.numInst());
|
|
1916
|
+
m.addStack = new Int32Array(2 * (m.prog.numInst() + 1));
|
|
1871
1917
|
m.matched = false;
|
|
1872
1918
|
m.matchcap = new Int32Array(m.prog.numCap < 2 ? 2 : m.prog.numCap);
|
|
1873
1919
|
m.ncap = 0;
|
|
1874
1920
|
return m;
|
|
1875
1921
|
}
|
|
1876
|
-
static fromMachine(machine) {
|
|
1877
|
-
return Machine.fromRE2(machine.re2);
|
|
1878
|
-
}
|
|
1879
1922
|
constructor() {
|
|
1880
1923
|
this.prog = null;
|
|
1881
1924
|
this.re2 = null;
|
|
1882
1925
|
this.q0 = null;
|
|
1883
1926
|
this.q1 = null;
|
|
1927
|
+
this.addStack = null;
|
|
1884
1928
|
this.matched = false;
|
|
1885
1929
|
this.matchcap = null;
|
|
1886
1930
|
this.ncap = 0;
|
|
@@ -1901,14 +1945,23 @@
|
|
|
1901
1945
|
if (this.ncap === 0) return Utils.emptyInts();
|
|
1902
1946
|
return Utils.toArray(this.matchcap.subarray(0, this.ncap));
|
|
1903
1947
|
}
|
|
1904
|
-
match(input, pos, anchor) {
|
|
1948
|
+
match(input, pos, anchor, lbState = null) {
|
|
1905
1949
|
const startCond = this.re2.cond;
|
|
1906
1950
|
if (startCond === Utils.EMPTY_ALL) return false;
|
|
1907
1951
|
if ((anchor === RE2Flags.ANCHOR_START || anchor === RE2Flags.ANCHOR_BOTH) && pos !== 0) return false;
|
|
1908
1952
|
this.matched = false;
|
|
1909
1953
|
this.matchcap.fill(-1);
|
|
1910
|
-
|
|
1911
|
-
|
|
1954
|
+
const hasLookbehinds = this.prog.numLb > 0;
|
|
1955
|
+
const matchStartPos = pos;
|
|
1956
|
+
let currentPos = pos;
|
|
1957
|
+
let resumeLookbehinds = false;
|
|
1958
|
+
if (hasLookbehinds) {
|
|
1959
|
+
if (lbState !== null && lbState.pos >= 0 && lbState.pos <= pos) {
|
|
1960
|
+
currentPos = lbState.pos;
|
|
1961
|
+
resumeLookbehinds = true;
|
|
1962
|
+
} else currentPos = 0;
|
|
1963
|
+
}
|
|
1964
|
+
let saveLookbehinds = hasLookbehinds && lbState !== null;
|
|
1912
1965
|
let runq = this.q0;
|
|
1913
1966
|
let nextq = this.q1;
|
|
1914
1967
|
let r = input.step(currentPos);
|
|
@@ -1924,12 +1977,16 @@
|
|
|
1924
1977
|
let flag;
|
|
1925
1978
|
if (currentPos === 0) flag = Utils.emptyOpContext(-1, rune);
|
|
1926
1979
|
else flag = input.context(currentPos);
|
|
1980
|
+
if (hasLookbehinds) {
|
|
1981
|
+
if (resumeLookbehinds) this.restoreLookbehinds(lbState, runq, flag);
|
|
1982
|
+
else this.spawnLookbehinds(runq, currentPos, flag);
|
|
1983
|
+
}
|
|
1927
1984
|
while (true) {
|
|
1928
|
-
if (runq.
|
|
1985
|
+
if (runq.mainThreads === 0) {
|
|
1929
1986
|
if ((startCond & Utils.EMPTY_BEGIN_TEXT) !== 0 && currentPos !== 0) break;
|
|
1930
1987
|
if ((anchor === RE2Flags.ANCHOR_START || anchor === RE2Flags.ANCHOR_BOTH) && currentPos !== 0) break;
|
|
1931
1988
|
if (this.matched) break;
|
|
1932
|
-
if (this.prog.numLb === 0 && !(this.re2.prefix.length === 0) && rune1 !== this.re2.prefixRune && input.canCheckPrefix()) {
|
|
1989
|
+
if (this.prog.numLb === 0 && runq.isEmpty() && !(this.re2.prefix.length === 0) && rune1 !== this.re2.prefixRune && input.canCheckPrefix()) {
|
|
1933
1990
|
const advance = input.index(this.re2, currentPos);
|
|
1934
1991
|
if (advance < 0) break;
|
|
1935
1992
|
currentPos += advance;
|
|
@@ -1942,9 +1999,12 @@
|
|
|
1942
1999
|
flag = input.context(currentPos);
|
|
1943
2000
|
}
|
|
1944
2001
|
}
|
|
1945
|
-
if (currentPos
|
|
1946
|
-
|
|
1947
|
-
|
|
2002
|
+
if (currentPos >= matchStartPos) {
|
|
2003
|
+
if (saveLookbehinds) {
|
|
2004
|
+
this.saveLookbehinds(lbState, runq, currentPos);
|
|
2005
|
+
saveLookbehinds = false;
|
|
2006
|
+
}
|
|
2007
|
+
if (!this.matched && (currentPos === 0 || anchor === RE2Flags.UNANCHORED)) {
|
|
1948
2008
|
if (this.ncap > 0) this.matchcap[0] = currentPos;
|
|
1949
2009
|
this.add(runq, this.prog.start, currentPos, this.matchcap, 0, flag);
|
|
1950
2010
|
}
|
|
@@ -1966,6 +2026,7 @@
|
|
|
1966
2026
|
runq = nextq;
|
|
1967
2027
|
nextq = tmpq;
|
|
1968
2028
|
}
|
|
2029
|
+
runq.clear();
|
|
1969
2030
|
nextq.clear();
|
|
1970
2031
|
return this.matched;
|
|
1971
2032
|
}
|
|
@@ -1989,12 +2050,12 @@
|
|
|
1989
2050
|
}
|
|
1990
2051
|
let flag = currentPos === 0 ? Utils.emptyOpContext(-1, rune) : input.context(currentPos);
|
|
1991
2052
|
const matches = /* @__PURE__ */ new Set();
|
|
2053
|
+
if (this.prog.numLb > 0) this.spawnLookbehinds(runq, currentPos, flag);
|
|
1992
2054
|
while (true) {
|
|
1993
|
-
if (runq.
|
|
2055
|
+
if (runq.mainThreads === 0) {
|
|
1994
2056
|
if ((startCond & Utils.EMPTY_BEGIN_TEXT) !== 0 && currentPos !== 0) break;
|
|
1995
2057
|
if ((anchor === RE2Flags.ANCHOR_START || anchor === RE2Flags.ANCHOR_BOTH) && currentPos !== 0) break;
|
|
1996
2058
|
}
|
|
1997
|
-
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, 0, flag);
|
|
1998
2059
|
if (currentPos === 0 || anchor === RE2Flags.UNANCHORED) {
|
|
1999
2060
|
if (currentPos >= matchStartPos) this.add(runq, this.prog.start, currentPos, this.matchcap, 0, flag);
|
|
2000
2061
|
}
|
|
@@ -2079,65 +2140,85 @@
|
|
|
2079
2140
|
}
|
|
2080
2141
|
runq.clear();
|
|
2081
2142
|
}
|
|
2143
|
+
spawnLookbehinds(q, pos, flag) {
|
|
2144
|
+
for (let i = 0; i < this.prog.lbStarts.length; i++) this.add(q, this.prog.lbStarts[i], pos, this.matchcap, 0, flag);
|
|
2145
|
+
}
|
|
2146
|
+
restoreLookbehinds(lbState, q, flag) {
|
|
2147
|
+
this.lbTable.set(lbState.lbTable);
|
|
2148
|
+
for (let j = 0; j < lbState.size; j++) this.add(q, lbState.pcs[j], lbState.pos, this.matchcap, 0, flag);
|
|
2149
|
+
}
|
|
2150
|
+
saveLookbehinds(lbState, q, pos) {
|
|
2151
|
+
let size = 0;
|
|
2152
|
+
for (let j = 0; j < q.size; j++) {
|
|
2153
|
+
const pc = q.densePcs[j];
|
|
2154
|
+
if (this.prog.lbInst[pc] === 1 && Inst.isRuneOp(this.prog.inst[pc].op)) lbState.pcs[size++] = pc;
|
|
2155
|
+
}
|
|
2156
|
+
lbState.size = size;
|
|
2157
|
+
lbState.pos = pos;
|
|
2158
|
+
lbState.lbTable.set(this.lbTable);
|
|
2159
|
+
}
|
|
2082
2160
|
add(q, pc, pos, capArray, capOffset, cond) {
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2161
|
+
const stk = this.addStack;
|
|
2162
|
+
let nstk = 0;
|
|
2163
|
+
for (;;) {
|
|
2164
|
+
while (pc !== 0 && !q.contains(pc)) {
|
|
2165
|
+
const d = q.add(pc);
|
|
2166
|
+
const inst = this.prog.inst[pc];
|
|
2167
|
+
switch (inst.op) {
|
|
2168
|
+
case Inst.FAIL:
|
|
2169
|
+
pc = 0;
|
|
2170
|
+
break;
|
|
2171
|
+
case Inst.ALT:
|
|
2172
|
+
case Inst.ALT_MATCH:
|
|
2173
|
+
stk[nstk++] = inst.arg;
|
|
2174
|
+
stk[nstk++] = 0;
|
|
2097
2175
|
pc = inst.out;
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
} else {
|
|
2111
|
-
pc = inst.out;
|
|
2112
|
-
continue;
|
|
2113
|
-
}
|
|
2114
|
-
case Inst.LB_WRITE:
|
|
2115
|
-
this.lbTable[Math.abs(inst.arg)] = pos;
|
|
2116
|
-
pc = inst.out;
|
|
2117
|
-
continue;
|
|
2118
|
-
case Inst.LB_CHECK:
|
|
2119
|
-
if (inst.arg > 0) {
|
|
2120
|
-
if (this.lbTable[inst.arg] === pos) {
|
|
2121
|
-
pc = inst.out;
|
|
2122
|
-
continue;
|
|
2176
|
+
break;
|
|
2177
|
+
case Inst.EMPTY_WIDTH:
|
|
2178
|
+
pc = (inst.arg & ~cond) === 0 ? inst.out : 0;
|
|
2179
|
+
break;
|
|
2180
|
+
case Inst.NOP:
|
|
2181
|
+
pc = inst.out;
|
|
2182
|
+
break;
|
|
2183
|
+
case Inst.CAPTURE:
|
|
2184
|
+
if (inst.arg < this.ncap) {
|
|
2185
|
+
stk[nstk++] = -inst.arg - 1;
|
|
2186
|
+
stk[nstk++] = capArray[capOffset + inst.arg];
|
|
2187
|
+
capArray[capOffset + inst.arg] = pos;
|
|
2123
2188
|
}
|
|
2124
|
-
} else if (this.lbTable[-inst.arg] !== pos) {
|
|
2125
2189
|
pc = inst.out;
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2190
|
+
break;
|
|
2191
|
+
case Inst.LB_WRITE:
|
|
2192
|
+
this.lbTable[Math.abs(inst.arg)] = pos;
|
|
2193
|
+
pc = inst.out;
|
|
2194
|
+
break;
|
|
2195
|
+
case Inst.LB_CHECK:
|
|
2196
|
+
if (inst.arg > 0) pc = this.lbTable[inst.arg] === pos ? inst.out : 0;
|
|
2197
|
+
else pc = this.lbTable[-inst.arg] !== pos ? inst.out : 0;
|
|
2198
|
+
break;
|
|
2199
|
+
case Inst.MATCH:
|
|
2200
|
+
case Inst.RUNE:
|
|
2201
|
+
case Inst.RUNE1:
|
|
2202
|
+
case Inst.RUNE_ANY:
|
|
2203
|
+
case Inst.RUNE_ANY_NOT_NL:
|
|
2204
|
+
if (this.prog.lbInst[pc] === 0) q.mainThreads++;
|
|
2205
|
+
if (this.ncap > 0) {
|
|
2206
|
+
const destOffset = d * this.ncap;
|
|
2207
|
+
if (destOffset + this.ncap > q.denseCaps.length) q.growCaps(destOffset + this.ncap);
|
|
2208
|
+
for (let c = 0; c < this.ncap; c++) q.denseCaps[destOffset + c] = capArray[capOffset + c];
|
|
2209
|
+
}
|
|
2210
|
+
pc = 0;
|
|
2211
|
+
break;
|
|
2212
|
+
default: throw new RE2JSInternalException("unhandled");
|
|
2213
|
+
}
|
|
2140
2214
|
}
|
|
2215
|
+
if (nstk === 0) return;
|
|
2216
|
+
nstk -= 2;
|
|
2217
|
+
const entry = stk[nstk];
|
|
2218
|
+
if (entry < 0) {
|
|
2219
|
+
capArray[capOffset - entry - 1] = stk[nstk + 1];
|
|
2220
|
+
pc = 0;
|
|
2221
|
+
} else pc = entry;
|
|
2141
2222
|
}
|
|
2142
2223
|
}
|
|
2143
2224
|
};
|
|
@@ -2157,35 +2238,85 @@
|
|
|
2157
2238
|
return true;
|
|
2158
2239
|
};
|
|
2159
2240
|
var DFAState = class {
|
|
2160
|
-
constructor(nfaStates, isMatch, matchIDs
|
|
2241
|
+
constructor(nfaStates, isMatch, matchIDs) {
|
|
2161
2242
|
this.nfaStates = nfaStates;
|
|
2162
2243
|
this.isMatch = isMatch;
|
|
2163
2244
|
this.matchIDs = matchIDs;
|
|
2164
|
-
this.
|
|
2165
|
-
this.
|
|
2166
|
-
this.transKeys = [];
|
|
2167
|
-
this.transVals = [];
|
|
2168
|
-
this.lastSeen = 0;
|
|
2245
|
+
this.next = null;
|
|
2246
|
+
this.nextAnchored = null;
|
|
2169
2247
|
}
|
|
2170
2248
|
};
|
|
2171
2249
|
var DFA = class DFA {
|
|
2172
|
-
static
|
|
2173
|
-
static
|
|
2250
|
+
static STATE_OVERHEAD = 160;
|
|
2251
|
+
static TABLE_OVERHEAD = 16;
|
|
2252
|
+
static PROGRESS_PER_STATE = 10;
|
|
2174
2253
|
constructor(prog, maxMem = 8388608) {
|
|
2175
2254
|
this.prog = prog;
|
|
2255
|
+
this.maxMem = maxMem;
|
|
2176
2256
|
this.stateCache = /* @__PURE__ */ new Map();
|
|
2177
2257
|
this.stateCount = 0;
|
|
2178
2258
|
this.startState = null;
|
|
2179
|
-
this.stateLimit = Math.max(1, Math.floor(maxMem / DFA.STATE_MEMORY_ESTIMATE));
|
|
2180
|
-
this.cacheClears = 0;
|
|
2181
2259
|
this.failed = false;
|
|
2182
|
-
|
|
2260
|
+
for (let pc = 0; pc < prog.numInst(); pc++) {
|
|
2261
|
+
const op = prog.getInst(pc).op;
|
|
2262
|
+
if (op === Inst.EMPTY_WIDTH || op === Inst.LB_WRITE || op === Inst.LB_CHECK) {
|
|
2263
|
+
this.failed = true;
|
|
2264
|
+
break;
|
|
2265
|
+
}
|
|
2266
|
+
}
|
|
2267
|
+
this.computeRuneClasses();
|
|
2268
|
+
this.stateBudget = maxMem;
|
|
2269
|
+
this.memBudget = maxMem;
|
|
2270
|
+
}
|
|
2271
|
+
computeRuneClasses() {
|
|
2272
|
+
const bounds = /* @__PURE__ */ new Set();
|
|
2273
|
+
const addRune = (r) => {
|
|
2274
|
+
bounds.add(r);
|
|
2275
|
+
bounds.add(r + 1);
|
|
2276
|
+
};
|
|
2277
|
+
for (let pc = 0; pc < this.prog.numInst(); pc++) {
|
|
2278
|
+
const inst = this.prog.getInst(pc);
|
|
2279
|
+
switch (inst.op) {
|
|
2280
|
+
case Inst.RUNE:
|
|
2281
|
+
case Inst.RUNE1:
|
|
2282
|
+
if (inst.runes.length === 1) {
|
|
2283
|
+
addRune(inst.runes[0]);
|
|
2284
|
+
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);
|
|
2285
|
+
} else for (let j = 0; j < inst.runes.length; j += 2) {
|
|
2286
|
+
bounds.add(inst.runes[j]);
|
|
2287
|
+
bounds.add(inst.runes[j + 1] + 1);
|
|
2288
|
+
}
|
|
2289
|
+
break;
|
|
2290
|
+
case Inst.RUNE_ANY_NOT_NL: addRune(10);
|
|
2291
|
+
}
|
|
2292
|
+
}
|
|
2293
|
+
bounds.delete(0);
|
|
2294
|
+
this.classBounds = Int32Array.from(bounds).sort();
|
|
2295
|
+
this.numClasses = this.classBounds.length + 1;
|
|
2296
|
+
const latin1Class = new Int32Array(Unicode.MAX_LATIN1 + 1);
|
|
2297
|
+
for (let r = 0; r <= Unicode.MAX_LATIN1; r++) latin1Class[r] = this.searchClass(r);
|
|
2298
|
+
this.latin1Class = latin1Class;
|
|
2299
|
+
}
|
|
2300
|
+
runeClass(r) {
|
|
2301
|
+
if (r <= Unicode.MAX_LATIN1) return this.latin1Class[r];
|
|
2302
|
+
return this.searchClass(r);
|
|
2303
|
+
}
|
|
2304
|
+
searchClass(r) {
|
|
2305
|
+
const bounds = this.classBounds;
|
|
2306
|
+
let lo = 0;
|
|
2307
|
+
let hi = bounds.length;
|
|
2308
|
+
while (lo < hi) {
|
|
2309
|
+
const mid = lo + hi >> 1;
|
|
2310
|
+
if (bounds[mid] <= r) lo = mid + 1;
|
|
2311
|
+
else hi = mid;
|
|
2312
|
+
}
|
|
2313
|
+
return lo;
|
|
2183
2314
|
}
|
|
2184
2315
|
computeClosure(pcs) {
|
|
2185
2316
|
const closure = /* @__PURE__ */ new Set();
|
|
2186
2317
|
const stack = [...pcs];
|
|
2187
2318
|
let isMatch = false;
|
|
2188
|
-
const matchIDs =
|
|
2319
|
+
const matchIDs = /* @__PURE__ */ new Set();
|
|
2189
2320
|
while (stack.length > 0) {
|
|
2190
2321
|
const pc = stack.pop();
|
|
2191
2322
|
if (closure.has(pc)) continue;
|
|
@@ -2194,7 +2325,7 @@
|
|
|
2194
2325
|
switch (inst.op) {
|
|
2195
2326
|
case Inst.MATCH:
|
|
2196
2327
|
isMatch = true;
|
|
2197
|
-
|
|
2328
|
+
matchIDs.add(inst.arg);
|
|
2198
2329
|
break;
|
|
2199
2330
|
case Inst.ALT:
|
|
2200
2331
|
case Inst.ALT_MATCH:
|
|
@@ -2211,11 +2342,11 @@
|
|
|
2211
2342
|
}
|
|
2212
2343
|
}
|
|
2213
2344
|
const sortedPCs = Int32Array.from(closure).sort();
|
|
2214
|
-
matchIDs.sort((a, b) => a - b);
|
|
2345
|
+
const ids = Array.from(matchIDs).sort((a, b) => a - b);
|
|
2215
2346
|
return {
|
|
2216
2347
|
pcs: sortedPCs,
|
|
2217
2348
|
isMatch,
|
|
2218
|
-
matchIDs
|
|
2349
|
+
matchIDs: ids
|
|
2219
2350
|
};
|
|
2220
2351
|
}
|
|
2221
2352
|
getState(pcs) {
|
|
@@ -2226,156 +2357,126 @@
|
|
|
2226
2357
|
let bucket = this.stateCache.get(hash);
|
|
2227
2358
|
if (bucket) for (let i = 0; i < bucket.length; i++) {
|
|
2228
2359
|
const state = bucket[i];
|
|
2229
|
-
if (arraysEqual(state.nfaStates, sortedPCs))
|
|
2230
|
-
state.lastSeen = ++this.clock;
|
|
2231
|
-
return state;
|
|
2232
|
-
}
|
|
2360
|
+
if (arraysEqual(state.nfaStates, sortedPCs)) return state;
|
|
2233
2361
|
}
|
|
2234
|
-
|
|
2362
|
+
const cost = DFA.STATE_OVERHEAD + 4 * sortedPCs.length + 8 * closureResult.matchIDs.length;
|
|
2363
|
+
if (this.memBudget < cost) return null;
|
|
2364
|
+
this.memBudget -= cost;
|
|
2365
|
+
if (!bucket) {
|
|
2235
2366
|
bucket = [];
|
|
2236
2367
|
this.stateCache.set(hash, bucket);
|
|
2237
2368
|
}
|
|
2238
|
-
if (this.failed) return null;
|
|
2239
|
-
if (this.stateCount >= this.stateLimit) {
|
|
2240
|
-
this.cacheClears++;
|
|
2241
|
-
if (this.cacheClears >= DFA.MAX_CACHE_CLEARS) {
|
|
2242
|
-
this.failed = true;
|
|
2243
|
-
this.stateCache.clear();
|
|
2244
|
-
this.stateCount = 0;
|
|
2245
|
-
this.startState = null;
|
|
2246
|
-
return null;
|
|
2247
|
-
}
|
|
2248
|
-
this.evictCache();
|
|
2249
|
-
bucket = this.stateCache.get(hash);
|
|
2250
|
-
if (!bucket) {
|
|
2251
|
-
bucket = [];
|
|
2252
|
-
this.stateCache.set(hash, bucket);
|
|
2253
|
-
}
|
|
2254
|
-
}
|
|
2255
2369
|
const state = new DFAState(sortedPCs, closureResult.isMatch, closureResult.matchIDs);
|
|
2256
|
-
state.lastSeen = ++this.clock;
|
|
2257
2370
|
bucket.push(state);
|
|
2258
2371
|
this.stateCount++;
|
|
2259
2372
|
return state;
|
|
2260
2373
|
}
|
|
2261
|
-
|
|
2262
|
-
const
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
const
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2374
|
+
allocTable(state, anchor) {
|
|
2375
|
+
const cost = DFA.TABLE_OVERHEAD + 8 * this.numClasses;
|
|
2376
|
+
if (this.memBudget < cost) return null;
|
|
2377
|
+
this.memBudget -= cost;
|
|
2378
|
+
const table = new Array(this.numClasses).fill(null);
|
|
2379
|
+
if (anchor === RE2Flags.UNANCHORED) state.next = table;
|
|
2380
|
+
else state.nextAnchored = table;
|
|
2381
|
+
return table;
|
|
2382
|
+
}
|
|
2383
|
+
clearCache() {
|
|
2269
2384
|
this.stateCache.clear();
|
|
2270
2385
|
this.stateCount = 0;
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
state.nextLatin1.fill(null);
|
|
2274
|
-
state.nextLatin1Anchored.fill(null);
|
|
2275
|
-
state.transKeys.length = 0;
|
|
2276
|
-
state.transVals.length = 0;
|
|
2277
|
-
const hash = hashPCs(state.nfaStates);
|
|
2278
|
-
let bucket = this.stateCache.get(hash);
|
|
2279
|
-
if (!bucket) {
|
|
2280
|
-
bucket = [];
|
|
2281
|
-
this.stateCache.set(hash, bucket);
|
|
2282
|
-
}
|
|
2283
|
-
bucket.push(state);
|
|
2284
|
-
this.stateCount++;
|
|
2285
|
-
}
|
|
2286
|
-
if (this.startState && !survivors.has(this.startState)) this.startState = null;
|
|
2386
|
+
this.startState = null;
|
|
2387
|
+
this.memBudget = this.stateBudget;
|
|
2287
2388
|
}
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2389
|
+
resetCache(current) {
|
|
2390
|
+
this.clearCache();
|
|
2391
|
+
return this.getState(current.nfaStates);
|
|
2392
|
+
}
|
|
2393
|
+
step(state, cls, rune, anchor) {
|
|
2394
|
+
let table = anchor === RE2Flags.UNANCHORED ? state.next : state.nextAnchored;
|
|
2395
|
+
if (table !== null) {
|
|
2396
|
+
const cached = table[cls];
|
|
2397
|
+
if (cached !== null) return cached;
|
|
2292
2398
|
} else {
|
|
2293
|
-
|
|
2294
|
-
if (
|
|
2295
|
-
}
|
|
2296
|
-
else {
|
|
2297
|
-
const key = charCode + (anchor === RE2Flags.UNANCHORED ? 0 : Unicode.MAX_RUNE + 1);
|
|
2298
|
-
const keys = state.transKeys;
|
|
2299
|
-
const len = keys.length;
|
|
2300
|
-
for (let i = 0; i < len; i++) if (keys[i] === key) return state.transVals[i];
|
|
2399
|
+
table = this.allocTable(state, anchor);
|
|
2400
|
+
if (table === null) return null;
|
|
2301
2401
|
}
|
|
2302
2402
|
const nextPCs = [];
|
|
2303
2403
|
for (let i = 0; i < state.nfaStates.length; i++) {
|
|
2304
2404
|
const pc = state.nfaStates[i];
|
|
2305
2405
|
const inst = this.prog.getInst(pc);
|
|
2306
|
-
if (Inst.isRuneOp(inst.op) && inst.matchRune(
|
|
2406
|
+
if (Inst.isRuneOp(inst.op) && inst.matchRune(rune)) nextPCs.push(inst.out);
|
|
2307
2407
|
}
|
|
2308
2408
|
if (anchor === RE2Flags.UNANCHORED) nextPCs.push(this.prog.start);
|
|
2309
2409
|
const nextState = this.getState(nextPCs);
|
|
2310
|
-
if (
|
|
2311
|
-
|
|
2312
|
-
else {
|
|
2313
|
-
const key = charCode + (anchor === RE2Flags.UNANCHORED ? 0 : Unicode.MAX_RUNE + 1);
|
|
2314
|
-
state.transKeys.push(key);
|
|
2315
|
-
state.transVals.push(nextState);
|
|
2316
|
-
}
|
|
2410
|
+
if (nextState === null) return null;
|
|
2411
|
+
table[cls] = nextState;
|
|
2317
2412
|
return nextState;
|
|
2318
2413
|
}
|
|
2319
|
-
|
|
2320
|
-
if (
|
|
2321
|
-
if (!this.startState) {
|
|
2414
|
+
start() {
|
|
2415
|
+
if (this.startState === null) {
|
|
2322
2416
|
this.startState = this.getState([this.prog.start]);
|
|
2323
|
-
if (
|
|
2417
|
+
if (this.startState === null && !this.failed) {
|
|
2418
|
+
this.clearCache();
|
|
2419
|
+
this.startState = this.getState([this.prog.start]);
|
|
2420
|
+
}
|
|
2324
2421
|
}
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2422
|
+
return this.startState;
|
|
2423
|
+
}
|
|
2424
|
+
run(input, pos, anchor, state, onState, noMatch) {
|
|
2425
|
+
const endPos = input.endPos();
|
|
2426
|
+
const latin1Class = this.latin1Class;
|
|
2427
|
+
let resetPos = -1;
|
|
2330
2428
|
let i = pos;
|
|
2331
2429
|
while (i < endPos) {
|
|
2332
2430
|
const r = input.step(i);
|
|
2333
2431
|
const rune = r >> 3;
|
|
2334
2432
|
const width = r & 7;
|
|
2335
2433
|
if (width === 0) break;
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
if (
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2434
|
+
const cls = rune <= Unicode.MAX_LATIN1 ? latin1Class[rune] : this.runeClass(rune);
|
|
2435
|
+
let next = anchor === RE2Flags.UNANCHORED && state.next !== null ? state.next[cls] : null;
|
|
2436
|
+
if (next === null) {
|
|
2437
|
+
next = this.step(state, cls, rune, anchor);
|
|
2438
|
+
if (next === null) {
|
|
2439
|
+
if (resetPos >= 0 && i - resetPos < DFA.PROGRESS_PER_STATE * this.stateCount) return null;
|
|
2440
|
+
resetPos = i;
|
|
2441
|
+
state = this.resetCache(state);
|
|
2442
|
+
if (state === null) return null;
|
|
2443
|
+
next = this.step(state, cls, rune, anchor);
|
|
2444
|
+
if (next === null) return null;
|
|
2445
|
+
}
|
|
2344
2446
|
}
|
|
2447
|
+
state = next;
|
|
2345
2448
|
i += width;
|
|
2449
|
+
const result = onState(state, i);
|
|
2450
|
+
if (result !== null) return result;
|
|
2451
|
+
if (state.nfaStates.length === 0 && anchor !== RE2Flags.UNANCHORED) return noMatch;
|
|
2346
2452
|
}
|
|
2347
|
-
return
|
|
2453
|
+
return noMatch;
|
|
2454
|
+
}
|
|
2455
|
+
match(input, pos, anchor) {
|
|
2456
|
+
if (this.failed) return null;
|
|
2457
|
+
if ((anchor === RE2Flags.ANCHOR_START || anchor === RE2Flags.ANCHOR_BOTH) && pos !== 0) return false;
|
|
2458
|
+
const startState = this.start();
|
|
2459
|
+
if (startState === null) return null;
|
|
2460
|
+
const endPos = input.endPos();
|
|
2461
|
+
if (startState.isMatch && (anchor !== RE2Flags.ANCHOR_BOTH || pos === endPos)) return true;
|
|
2462
|
+
return this.run(input, pos, anchor, startState, (state, nextPos) => {
|
|
2463
|
+
if (state.isMatch && (anchor !== RE2Flags.ANCHOR_BOTH || nextPos === endPos)) return true;
|
|
2464
|
+
return null;
|
|
2465
|
+
}, false);
|
|
2348
2466
|
}
|
|
2349
2467
|
matchSet(input, pos, anchor) {
|
|
2468
|
+
if (this.failed) return null;
|
|
2350
2469
|
if ((anchor === RE2Flags.ANCHOR_START || anchor === RE2Flags.ANCHOR_BOTH) && pos !== 0) return [];
|
|
2351
|
-
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
}
|
|
2355
|
-
let endPos = input.endPos();
|
|
2356
|
-
let currentState = this.startState;
|
|
2470
|
+
const startState = this.start();
|
|
2471
|
+
if (startState === null) return null;
|
|
2472
|
+
const endPos = input.endPos();
|
|
2357
2473
|
const matches = /* @__PURE__ */ new Set();
|
|
2358
|
-
const
|
|
2359
|
-
if (state.isMatch
|
|
2360
|
-
|
|
2361
|
-
} else state.matchIDs.forEach((id) => matches.add(id));
|
|
2474
|
+
const collect = (state, currentPos) => {
|
|
2475
|
+
if (state.isMatch && (anchor !== RE2Flags.ANCHOR_BOTH || currentPos === endPos)) for (let k = 0; k < state.matchIDs.length; k++) matches.add(state.matchIDs[k]);
|
|
2476
|
+
return null;
|
|
2362
2477
|
};
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
while (i < endPos) {
|
|
2366
|
-
const r = input.step(i);
|
|
2367
|
-
const rune = r >> 3;
|
|
2368
|
-
const width = r & 7;
|
|
2369
|
-
if (width === 0) break;
|
|
2370
|
-
currentState = anchor === RE2Flags.UNANCHORED && rune <= Unicode.MAX_LATIN1 && currentState.nextLatin1[rune] || this.step(currentState, rune, anchor);
|
|
2371
|
-
if (currentState === null) return null;
|
|
2372
|
-
currentState.lastSeen = ++this.clock;
|
|
2373
|
-
i += width;
|
|
2374
|
-
checkMatch(currentState, i);
|
|
2375
|
-
if (currentState.nfaStates.length === 0) {
|
|
2376
|
-
if (anchor !== RE2Flags.UNANCHORED) break;
|
|
2377
|
-
}
|
|
2378
|
-
}
|
|
2478
|
+
collect(startState, pos);
|
|
2479
|
+
if (this.run(input, pos, anchor, startState, collect, false) === null) return null;
|
|
2379
2480
|
return Array.from(matches).sort((a, b) => a - b);
|
|
2380
2481
|
}
|
|
2381
2482
|
};
|
|
@@ -2384,7 +2485,7 @@
|
|
|
2384
2485
|
const VISITED_BITS = 32;
|
|
2385
2486
|
const MAX_BACKTRACK_PROG = 500;
|
|
2386
2487
|
const INITIAL_JOB_CAPACITY = 256;
|
|
2387
|
-
const MAX_BACKTRACK_VECTOR =
|
|
2488
|
+
const MAX_BACKTRACK_VECTOR = 262144;
|
|
2388
2489
|
var BitState = class {
|
|
2389
2490
|
constructor() {
|
|
2390
2491
|
this.end = 0;
|
|
@@ -2667,7 +2768,7 @@
|
|
|
2667
2768
|
const inst = new Inst(orig.op);
|
|
2668
2769
|
inst.out = orig.out;
|
|
2669
2770
|
inst.arg = orig.arg;
|
|
2670
|
-
inst.runes = orig.runes ? orig.runes
|
|
2771
|
+
inst.runes = orig.runes ? new Int32Array(orig.runes) : /* @__PURE__ */ new Int32Array(0);
|
|
2671
2772
|
inst.next = null;
|
|
2672
2773
|
this.inst[i] = inst;
|
|
2673
2774
|
}
|
|
@@ -2737,7 +2838,7 @@
|
|
|
2737
2838
|
const rightRunes = onePassRunes[inst.arg] || [];
|
|
2738
2839
|
const mergeRes = mergeRuneSets(leftRunes, rightRunes, inst.out, inst.arg);
|
|
2739
2840
|
if (!mergeRes) return false;
|
|
2740
|
-
onePassRunes[pc] = mergeRes.merged;
|
|
2841
|
+
onePassRunes[pc] = new Int32Array(mergeRes.merged);
|
|
2741
2842
|
inst.next = new Uint32Array(mergeRes.next);
|
|
2742
2843
|
break;
|
|
2743
2844
|
}
|
|
@@ -2746,7 +2847,7 @@
|
|
|
2746
2847
|
case Inst.NOP:
|
|
2747
2848
|
ok = check(inst.out);
|
|
2748
2849
|
m[pc] = m[inst.out];
|
|
2749
|
-
onePassRunes[pc] = onePassRunes[inst.out] ? onePassRunes[inst.out]
|
|
2850
|
+
onePassRunes[pc] = onePassRunes[inst.out] ? new Int32Array(onePassRunes[inst.out]) : /* @__PURE__ */ new Int32Array(0);
|
|
2750
2851
|
inst.next = new Uint32Array(Math.floor(onePassRunes[pc].length / 2) + 1).fill(inst.out);
|
|
2751
2852
|
break;
|
|
2752
2853
|
case Inst.MATCH:
|
|
@@ -2758,7 +2859,7 @@
|
|
|
2758
2859
|
if (inst.next && inst.next.length > 0) break;
|
|
2759
2860
|
instQueue.insert(inst.out);
|
|
2760
2861
|
if (!inst.runes || inst.runes.length === 0) {
|
|
2761
|
-
onePassRunes[pc] =
|
|
2862
|
+
onePassRunes[pc] = /* @__PURE__ */ new Int32Array(0);
|
|
2762
2863
|
inst.next = new Uint32Array([inst.out]);
|
|
2763
2864
|
break;
|
|
2764
2865
|
}
|
|
@@ -2769,7 +2870,7 @@
|
|
|
2769
2870
|
for (let r1 = Unicode.simpleFold(r0); r1 !== r0; r1 = Unicode.simpleFold(r1)) runes.push(r1, r1);
|
|
2770
2871
|
runes.sort((a, b) => a - b);
|
|
2771
2872
|
} else for (let j = 0; j < inst.runes.length; j++) runes.push(inst.runes[j]);
|
|
2772
|
-
onePassRunes[pc] = runes;
|
|
2873
|
+
onePassRunes[pc] = new Int32Array(runes);
|
|
2773
2874
|
inst.next = new Uint32Array(Math.floor(runes.length / 2) + 1).fill(inst.out);
|
|
2774
2875
|
inst.op = Inst.RUNE;
|
|
2775
2876
|
break;
|
|
@@ -2785,7 +2886,7 @@
|
|
|
2785
2886
|
for (let r1 = Unicode.simpleFold(r0); r1 !== r0; r1 = Unicode.simpleFold(r1)) runes.push(r1, r1);
|
|
2786
2887
|
runes.sort((a, b) => a - b);
|
|
2787
2888
|
} else runes.push(inst.runes[0], inst.runes[0]);
|
|
2788
|
-
onePassRunes[pc] = runes;
|
|
2889
|
+
onePassRunes[pc] = new Int32Array(runes);
|
|
2789
2890
|
inst.next = new Uint32Array(Math.floor(runes.length / 2) + 1).fill(inst.out);
|
|
2790
2891
|
inst.op = Inst.RUNE;
|
|
2791
2892
|
break;
|
|
@@ -2794,21 +2895,20 @@
|
|
|
2794
2895
|
m[pc] = false;
|
|
2795
2896
|
if (inst.next && inst.next.length > 0) break;
|
|
2796
2897
|
instQueue.insert(inst.out);
|
|
2797
|
-
onePassRunes[pc] = [0, Unicode.MAX_RUNE];
|
|
2898
|
+
onePassRunes[pc] = new Int32Array([0, Unicode.MAX_RUNE]);
|
|
2798
2899
|
inst.next = new Uint32Array([inst.out]);
|
|
2799
2900
|
break;
|
|
2800
2901
|
case Inst.RUNE_ANY_NOT_NL:
|
|
2801
2902
|
m[pc] = false;
|
|
2802
2903
|
if (inst.next && inst.next.length > 0) break;
|
|
2803
2904
|
instQueue.insert(inst.out);
|
|
2804
|
-
onePassRunes[pc] = [
|
|
2905
|
+
onePassRunes[pc] = new Int32Array([
|
|
2805
2906
|
0,
|
|
2806
2907
|
9,
|
|
2807
2908
|
11,
|
|
2808
2909
|
Unicode.MAX_RUNE
|
|
2809
|
-
];
|
|
2910
|
+
]);
|
|
2810
2911
|
inst.next = new Uint32Array(Math.floor(onePassRunes[pc].length / 2) + 1).fill(inst.out);
|
|
2811
|
-
break;
|
|
2812
2912
|
}
|
|
2813
2913
|
return ok;
|
|
2814
2914
|
};
|
|
@@ -2840,8 +2940,7 @@
|
|
|
2840
2940
|
case Inst.RUNE_ANY_NOT_NL:
|
|
2841
2941
|
p.inst[ix].next = null;
|
|
2842
2942
|
p.inst[ix].op = instOriginal.op;
|
|
2843
|
-
p.inst[ix].runes = instOriginal.runes ? instOriginal.runes
|
|
2844
|
-
break;
|
|
2943
|
+
p.inst[ix].runes = instOriginal.runes ? new Int32Array(instOriginal.runes) : /* @__PURE__ */ new Int32Array(0);
|
|
2845
2944
|
}
|
|
2846
2945
|
}
|
|
2847
2946
|
};
|
|
@@ -2870,9 +2969,7 @@
|
|
|
2870
2969
|
return null;
|
|
2871
2970
|
}
|
|
2872
2971
|
break;
|
|
2873
|
-
default:
|
|
2874
|
-
if (opOut === Inst.MATCH && hasAlt) return null;
|
|
2875
|
-
break;
|
|
2972
|
+
default: if (opOut === Inst.MATCH && hasAlt) return null;
|
|
2876
2973
|
}
|
|
2877
2974
|
}
|
|
2878
2975
|
let p = onePassCopy(prog);
|
|
@@ -3023,7 +3120,7 @@
|
|
|
3023
3120
|
this.op = op;
|
|
3024
3121
|
this.flags = 0;
|
|
3025
3122
|
this.subs = Regexp.emptySubs();
|
|
3026
|
-
this.runes =
|
|
3123
|
+
this.runes = /* @__PURE__ */ new Int32Array(0);
|
|
3027
3124
|
this.min = 0;
|
|
3028
3125
|
this.max = 0;
|
|
3029
3126
|
this.cap = 0;
|
|
@@ -3034,7 +3131,7 @@
|
|
|
3034
3131
|
reinit() {
|
|
3035
3132
|
this.flags = 0;
|
|
3036
3133
|
this.subs = Regexp.emptySubs();
|
|
3037
|
-
this.runes =
|
|
3134
|
+
this.runes = /* @__PURE__ */ new Int32Array(0);
|
|
3038
3135
|
this.cap = 0;
|
|
3039
3136
|
this.min = 0;
|
|
3040
3137
|
this.max = 0;
|
|
@@ -3078,7 +3175,6 @@
|
|
|
3078
3175
|
if (this.max >= 0) out += this.max;
|
|
3079
3176
|
}
|
|
3080
3177
|
out += "}";
|
|
3081
|
-
break;
|
|
3082
3178
|
}
|
|
3083
3179
|
if ((this.flags & RE2Flags.NON_GREEDY) !== 0) out += "?";
|
|
3084
3180
|
break;
|
|
@@ -3171,9 +3267,7 @@
|
|
|
3171
3267
|
}
|
|
3172
3268
|
out += "]";
|
|
3173
3269
|
break;
|
|
3174
|
-
default:
|
|
3175
|
-
out += this.op;
|
|
3176
|
-
break;
|
|
3270
|
+
default: out += this.op;
|
|
3177
3271
|
}
|
|
3178
3272
|
return out;
|
|
3179
3273
|
}
|
|
@@ -3217,70 +3311,158 @@
|
|
|
3217
3311
|
if (this.cap !== that.cap || (this.name === null ? that.name !== null : this.name !== that.name) || !this.subs[0].equals(that.subs[0])) return false;
|
|
3218
3312
|
break;
|
|
3219
3313
|
case Regexp.Op.PLB:
|
|
3220
|
-
case Regexp.Op.NLB:
|
|
3221
|
-
if (this.lb !== that.lb || !this.subs[0].equals(that.subs[0])) return false;
|
|
3222
|
-
break;
|
|
3314
|
+
case Regexp.Op.NLB: if (this.lb !== that.lb || !this.subs[0].equals(that.subs[0])) return false;
|
|
3223
3315
|
}
|
|
3224
3316
|
return true;
|
|
3225
3317
|
}
|
|
3226
3318
|
};
|
|
3227
3319
|
//#endregion
|
|
3320
|
+
//#region src/RegexpWalker.js
|
|
3321
|
+
/**
|
|
3322
|
+
* Walks a Regexp tree without recursion, visiting nodes in the same order a recursive walk
|
|
3323
|
+
* would (RE2: re2/walker-inl.h, "Helper class for traversing Regexps without recursion").
|
|
3324
|
+
*
|
|
3325
|
+
* The handler sees a node without subexpressions once, through `leaf(re)`, which returns its
|
|
3326
|
+
* result. Any other node is seen up to three times:
|
|
3327
|
+
* - `enter(re)` before its children. It returns the state kept for `re` while its children are
|
|
3328
|
+
* visited; a state whose `result` is already set skips the children.
|
|
3329
|
+
* - `child(re, state, result, i)` after child `i` produced `result`. Setting `state.result`
|
|
3330
|
+
* stops visiting the remaining children.
|
|
3331
|
+
* - `leave(re, state)` after the last child; it returns the result for `re`.
|
|
3332
|
+
*
|
|
3333
|
+
* Counted repetitions expand into one nesting level per copy, so the simplified tree can be
|
|
3334
|
+
* thousands of levels deep; recursion over it would overflow the JS stack, which has no fixed
|
|
3335
|
+
* relation to the parser's nesting limit. This walk keeps its frames on the heap instead.
|
|
3336
|
+
*/
|
|
3337
|
+
var RegexpWalker = class {
|
|
3338
|
+
static walk(root, handler) {
|
|
3339
|
+
const stack = [];
|
|
3340
|
+
let re = root;
|
|
3341
|
+
let result;
|
|
3342
|
+
for (;;) {
|
|
3343
|
+
if (re.subs.length === 0) result = handler.leaf(re);
|
|
3344
|
+
else {
|
|
3345
|
+
const state = handler.enter(re);
|
|
3346
|
+
if (state.result === void 0) {
|
|
3347
|
+
stack.push({
|
|
3348
|
+
re,
|
|
3349
|
+
state,
|
|
3350
|
+
i: 0
|
|
3351
|
+
});
|
|
3352
|
+
re = re.subs[0];
|
|
3353
|
+
continue;
|
|
3354
|
+
}
|
|
3355
|
+
result = state.result;
|
|
3356
|
+
}
|
|
3357
|
+
for (;;) {
|
|
3358
|
+
if (stack.length === 0) return result;
|
|
3359
|
+
const frame = stack[stack.length - 1];
|
|
3360
|
+
handler.child(frame.re, frame.state, result, frame.i);
|
|
3361
|
+
frame.i++;
|
|
3362
|
+
if (frame.state.result === void 0 && frame.i < frame.re.subs.length) {
|
|
3363
|
+
re = frame.re.subs[frame.i];
|
|
3364
|
+
break;
|
|
3365
|
+
}
|
|
3366
|
+
stack.pop();
|
|
3367
|
+
result = frame.state.result !== void 0 ? frame.state.result : handler.leave(frame.re, frame.state);
|
|
3368
|
+
}
|
|
3369
|
+
}
|
|
3370
|
+
}
|
|
3371
|
+
};
|
|
3372
|
+
//#endregion
|
|
3228
3373
|
//#region src/Prefilter.js
|
|
3229
3374
|
var AhoCorasick = class {
|
|
3230
|
-
constructor(
|
|
3231
|
-
|
|
3232
|
-
|
|
3233
|
-
|
|
3234
|
-
|
|
3375
|
+
constructor(words, alphabetSize) {
|
|
3376
|
+
const edges = /* @__PURE__ */ new Map();
|
|
3377
|
+
const parent = [0];
|
|
3378
|
+
const unit = [0];
|
|
3379
|
+
const depth = [0];
|
|
3380
|
+
const terminal = [0];
|
|
3381
|
+
for (const word of words) {
|
|
3235
3382
|
let node = 0;
|
|
3236
3383
|
for (let i = 0; i < word.length; i++) {
|
|
3237
|
-
const
|
|
3238
|
-
|
|
3239
|
-
|
|
3240
|
-
|
|
3241
|
-
|
|
3242
|
-
|
|
3384
|
+
const key = node * alphabetSize + word[i];
|
|
3385
|
+
let child = edges.get(key);
|
|
3386
|
+
if (child === void 0) {
|
|
3387
|
+
child = parent.length;
|
|
3388
|
+
edges.set(key, child);
|
|
3389
|
+
parent.push(node);
|
|
3390
|
+
unit.push(word[i]);
|
|
3391
|
+
depth.push(depth[node] + 1);
|
|
3392
|
+
terminal.push(0);
|
|
3243
3393
|
}
|
|
3244
|
-
node =
|
|
3394
|
+
node = child;
|
|
3245
3395
|
}
|
|
3246
|
-
|
|
3247
|
-
}
|
|
3248
|
-
const
|
|
3249
|
-
|
|
3250
|
-
|
|
3251
|
-
|
|
3252
|
-
|
|
3253
|
-
|
|
3254
|
-
|
|
3255
|
-
|
|
3256
|
-
|
|
3257
|
-
|
|
3258
|
-
|
|
3259
|
-
|
|
3260
|
-
|
|
3261
|
-
|
|
3262
|
-
|
|
3263
|
-
|
|
3396
|
+
terminal[node] = 1;
|
|
3397
|
+
}
|
|
3398
|
+
const numNodes = parent.length;
|
|
3399
|
+
const children = new Int32Array(numNodes - 1);
|
|
3400
|
+
for (let c = 1; c < numNodes; c++) children[c - 1] = c;
|
|
3401
|
+
children.sort((a, b) => parent[a] - parent[b] || unit[a] - unit[b]);
|
|
3402
|
+
const childStart = new Int32Array(numNodes + 1);
|
|
3403
|
+
for (let c = 1; c < numNodes; c++) childStart[parent[c] + 1]++;
|
|
3404
|
+
for (let n = 0; n < numNodes; n++) childStart[n + 1] += childStart[n];
|
|
3405
|
+
const childUnit = new Int32Array(numNodes - 1);
|
|
3406
|
+
for (let k = 0; k < children.length; k++) childUnit[k] = unit[children[k]];
|
|
3407
|
+
this.childStart = childStart;
|
|
3408
|
+
this.childUnit = childUnit;
|
|
3409
|
+
this.childNode = children;
|
|
3410
|
+
const byDepth = new Int32Array(numNodes);
|
|
3411
|
+
for (let n = 0; n < numNodes; n++) byDepth[n] = n;
|
|
3412
|
+
byDepth.sort((a, b) => depth[a] - depth[b]);
|
|
3413
|
+
const fail = new Int32Array(numNodes);
|
|
3414
|
+
const match = Uint8Array.from(terminal);
|
|
3415
|
+
for (let k = 1; k < numNodes; k++) {
|
|
3416
|
+
const c = byDepth[k];
|
|
3417
|
+
const p = parent[c];
|
|
3418
|
+
if (p !== 0) {
|
|
3419
|
+
let f = fail[p];
|
|
3420
|
+
let next = this.next(f, unit[c]);
|
|
3421
|
+
while (next < 0 && f !== 0) {
|
|
3422
|
+
f = fail[f];
|
|
3423
|
+
next = this.next(f, unit[c]);
|
|
3424
|
+
}
|
|
3425
|
+
fail[c] = next >= 0 ? next : 0;
|
|
3264
3426
|
}
|
|
3427
|
+
match[c] |= match[fail[c]];
|
|
3428
|
+
}
|
|
3429
|
+
this.fail = fail;
|
|
3430
|
+
this.match = match;
|
|
3431
|
+
}
|
|
3432
|
+
next(node, u) {
|
|
3433
|
+
let lo = this.childStart[node];
|
|
3434
|
+
let hi = this.childStart[node + 1];
|
|
3435
|
+
const units = this.childUnit;
|
|
3436
|
+
while (lo < hi) {
|
|
3437
|
+
const mid = lo + hi >> 1;
|
|
3438
|
+
const m = units[mid];
|
|
3439
|
+
if (m === u) return this.childNode[mid];
|
|
3440
|
+
if (m < u) lo = mid + 1;
|
|
3441
|
+
else hi = mid;
|
|
3442
|
+
}
|
|
3443
|
+
return -1;
|
|
3444
|
+
}
|
|
3445
|
+
advance(node, u) {
|
|
3446
|
+
for (;;) {
|
|
3447
|
+
const next = this.next(node, u);
|
|
3448
|
+
if (next >= 0) return next;
|
|
3449
|
+
if (node === 0) return 0;
|
|
3450
|
+
node = this.fail[node];
|
|
3265
3451
|
}
|
|
3266
3452
|
}
|
|
3267
3453
|
searchUTF16(charSeq, start, end) {
|
|
3268
3454
|
let node = 0;
|
|
3269
3455
|
for (let i = start; i < end; i++) {
|
|
3270
|
-
|
|
3271
|
-
|
|
3272
|
-
if (val in this.next[node]) node = this.next[node][val];
|
|
3273
|
-
if (this.match[node]) return true;
|
|
3456
|
+
node = this.advance(node, charSeq.charCodeAt(i));
|
|
3457
|
+
if (this.match[node] === 1) return true;
|
|
3274
3458
|
}
|
|
3275
3459
|
return false;
|
|
3276
3460
|
}
|
|
3277
3461
|
searchUTF8(bytes, start, end) {
|
|
3278
3462
|
let node = 0;
|
|
3279
3463
|
for (let i = start; i < end; i++) {
|
|
3280
|
-
|
|
3281
|
-
|
|
3282
|
-
if (val in this.next[node]) node = this.next[node][val];
|
|
3283
|
-
if (this.match[node]) return true;
|
|
3464
|
+
node = this.advance(node, bytes[i]);
|
|
3465
|
+
if (this.match[node] === 1) return true;
|
|
3284
3466
|
}
|
|
3285
3467
|
return false;
|
|
3286
3468
|
}
|
|
@@ -3292,14 +3474,33 @@
|
|
|
3292
3474
|
AND: 2,
|
|
3293
3475
|
OR: 3
|
|
3294
3476
|
};
|
|
3477
|
+
static MAX_SCANS = 32;
|
|
3478
|
+
static MAX_AC_UNITS = 1 << 18;
|
|
3295
3479
|
constructor(type) {
|
|
3296
3480
|
this.type = type;
|
|
3297
3481
|
this.subs = [];
|
|
3298
3482
|
this.str = "";
|
|
3299
3483
|
this.bytes = null;
|
|
3484
|
+
this.cost = type === Prefilter.Type.EXACT ? 1 : 0;
|
|
3485
|
+
this.allExact = false;
|
|
3300
3486
|
this.ac16 = null;
|
|
3301
3487
|
this.ac8 = null;
|
|
3302
3488
|
}
|
|
3489
|
+
automaton16() {
|
|
3490
|
+
if (this.ac16 === null) {
|
|
3491
|
+
const words = this.subs.map((s) => {
|
|
3492
|
+
const arr = new Array(s.str.length);
|
|
3493
|
+
for (let i = 0; i < s.str.length; i++) arr[i] = s.str.charCodeAt(i);
|
|
3494
|
+
return arr;
|
|
3495
|
+
});
|
|
3496
|
+
this.ac16 = new AhoCorasick(words, 65536);
|
|
3497
|
+
}
|
|
3498
|
+
return this.ac16;
|
|
3499
|
+
}
|
|
3500
|
+
automaton8() {
|
|
3501
|
+
if (this.ac8 === null) this.ac8 = new AhoCorasick(this.subs.map((s) => s.bytes), 256);
|
|
3502
|
+
return this.ac8;
|
|
3503
|
+
}
|
|
3303
3504
|
eval(input, pos) {
|
|
3304
3505
|
switch (this.type) {
|
|
3305
3506
|
case Prefilter.Type.NONE: return true;
|
|
@@ -3308,7 +3509,7 @@
|
|
|
3308
3509
|
for (let i = 0; i < this.subs.length; i++) if (!this.subs[i].eval(input, pos)) return false;
|
|
3309
3510
|
return true;
|
|
3310
3511
|
case Prefilter.Type.OR:
|
|
3311
|
-
if (this.
|
|
3512
|
+
if (this.allExact) return input.hasAnyString(this, pos);
|
|
3312
3513
|
for (let i = 0; i < this.subs.length; i++) if (this.subs[i].eval(input, pos)) return true;
|
|
3313
3514
|
return false;
|
|
3314
3515
|
default: return true;
|
|
@@ -3317,100 +3518,115 @@
|
|
|
3317
3518
|
};
|
|
3318
3519
|
var PrefilterTree = class PrefilterTree {
|
|
3319
3520
|
static build(re) {
|
|
3320
|
-
const pf = PrefilterTree.fromRegexp(re);
|
|
3321
|
-
return PrefilterTree.simplify(pf);
|
|
3322
|
-
}
|
|
3323
|
-
static fromRegexp(re) {
|
|
3324
3521
|
if (!re) return new Prefilter(Prefilter.Type.NONE);
|
|
3522
|
+
return RegexpWalker.walk(re, PrefilterTree.WALKER);
|
|
3523
|
+
}
|
|
3524
|
+
static WALKER = {
|
|
3525
|
+
leaf: (re) => PrefilterTree.leaf(re),
|
|
3526
|
+
enter: (re) => PrefilterTree.enter(re),
|
|
3527
|
+
child: (re, state, result) => PrefilterTree.child(re, state, result),
|
|
3528
|
+
leave: (re, state) => PrefilterTree.leave(re, state)
|
|
3529
|
+
};
|
|
3530
|
+
static leaf(re) {
|
|
3531
|
+
if (re.op !== Regexp.Op.LITERAL) return new Prefilter(Prefilter.Type.NONE);
|
|
3532
|
+
if (re.runes.length === 0 || (re.flags & RE2Flags.FOLD_CASE) !== 0) return new Prefilter(Prefilter.Type.NONE);
|
|
3533
|
+
let str = "";
|
|
3534
|
+
for (let i = 0; i < re.runes.length; i++) {
|
|
3535
|
+
if (Unicode.isUnsearchable(re.runes[i])) return new Prefilter(Prefilter.Type.NONE);
|
|
3536
|
+
str += String.fromCodePoint(re.runes[i]);
|
|
3537
|
+
}
|
|
3538
|
+
const pf = new Prefilter(Prefilter.Type.EXACT);
|
|
3539
|
+
pf.str = str;
|
|
3540
|
+
pf.bytes = Utils.stringToUtf8ByteArray(pf.str);
|
|
3541
|
+
return pf;
|
|
3542
|
+
}
|
|
3543
|
+
static enter(re) {
|
|
3325
3544
|
switch (re.op) {
|
|
3326
|
-
case Regexp.Op.PLB:
|
|
3327
|
-
case Regexp.Op.NLB:
|
|
3328
|
-
case Regexp.Op.NO_MATCH:
|
|
3329
|
-
case Regexp.Op.EMPTY_MATCH:
|
|
3330
|
-
case Regexp.Op.BEGIN_LINE:
|
|
3331
|
-
case Regexp.Op.END_LINE:
|
|
3332
|
-
case Regexp.Op.BEGIN_TEXT:
|
|
3333
|
-
case Regexp.Op.END_TEXT:
|
|
3334
|
-
case Regexp.Op.WORD_BOUNDARY:
|
|
3335
|
-
case Regexp.Op.NO_WORD_BOUNDARY:
|
|
3336
|
-
case Regexp.Op.CHAR_CLASS:
|
|
3337
|
-
case Regexp.Op.ANY_CHAR_NOT_NL:
|
|
3338
|
-
case Regexp.Op.ANY_CHAR: return new Prefilter(Prefilter.Type.NONE);
|
|
3339
|
-
case Regexp.Op.LITERAL: {
|
|
3340
|
-
if (re.runes.length === 0 || (re.flags & RE2Flags.FOLD_CASE) !== 0) return new Prefilter(Prefilter.Type.NONE);
|
|
3341
|
-
const pf = new Prefilter(Prefilter.Type.EXACT);
|
|
3342
|
-
let str = "";
|
|
3343
|
-
for (let i = 0; i < re.runes.length; i++) str += String.fromCodePoint(re.runes[i]);
|
|
3344
|
-
pf.str = str;
|
|
3345
|
-
pf.bytes = Utils.stringToUtf8ByteArray(pf.str);
|
|
3346
|
-
return pf;
|
|
3347
|
-
}
|
|
3348
3545
|
case Regexp.Op.CAPTURE:
|
|
3349
|
-
case Regexp.Op.PLUS: return
|
|
3546
|
+
case Regexp.Op.PLUS: return { sub: null };
|
|
3350
3547
|
case Regexp.Op.REPEAT:
|
|
3351
|
-
if (re.min >= 1) return
|
|
3352
|
-
return new Prefilter(Prefilter.Type.NONE);
|
|
3353
|
-
case Regexp.Op.CONCAT: {
|
|
3354
|
-
|
|
3355
|
-
|
|
3356
|
-
|
|
3548
|
+
if (re.min >= 1) return { sub: null };
|
|
3549
|
+
return { result: new Prefilter(Prefilter.Type.NONE) };
|
|
3550
|
+
case Regexp.Op.CONCAT: return {
|
|
3551
|
+
pf: new Prefilter(Prefilter.Type.AND),
|
|
3552
|
+
subs: []
|
|
3553
|
+
};
|
|
3554
|
+
case Regexp.Op.ALTERNATE: return {
|
|
3555
|
+
pf: new Prefilter(Prefilter.Type.OR),
|
|
3556
|
+
subs: []
|
|
3557
|
+
};
|
|
3558
|
+
default: return { result: new Prefilter(Prefilter.Type.NONE) };
|
|
3559
|
+
}
|
|
3560
|
+
}
|
|
3561
|
+
static child(re, state, s) {
|
|
3562
|
+
if (state.subs === void 0) {
|
|
3563
|
+
state.sub = s;
|
|
3564
|
+
return;
|
|
3565
|
+
}
|
|
3566
|
+
if (state.pf.type === Prefilter.Type.AND) {
|
|
3567
|
+
if (s.type === Prefilter.Type.NONE) return;
|
|
3568
|
+
if (s.type === Prefilter.Type.AND) {
|
|
3569
|
+
for (let j = 0; j < s.subs.length; j++) state.subs.push(s.subs[j]);
|
|
3570
|
+
return;
|
|
3357
3571
|
}
|
|
3358
|
-
|
|
3359
|
-
|
|
3360
|
-
|
|
3361
|
-
|
|
3572
|
+
state.subs.push(s);
|
|
3573
|
+
return;
|
|
3574
|
+
}
|
|
3575
|
+
if (s.type === Prefilter.Type.NONE) {
|
|
3576
|
+
state.result = new Prefilter(Prefilter.Type.NONE);
|
|
3577
|
+
return;
|
|
3578
|
+
}
|
|
3579
|
+
if (s.type === Prefilter.Type.OR) {
|
|
3580
|
+
for (let j = 0; j < s.subs.length; j++) state.subs.push(s.subs[j]);
|
|
3581
|
+
return;
|
|
3582
|
+
}
|
|
3583
|
+
state.subs.push(s);
|
|
3584
|
+
}
|
|
3585
|
+
static leave(re, state) {
|
|
3586
|
+
if (state.subs === void 0) return state.sub;
|
|
3587
|
+
const pf = state.pf;
|
|
3588
|
+
const seen = /* @__PURE__ */ new Set();
|
|
3589
|
+
const subs = [];
|
|
3590
|
+
for (const sub of state.subs) {
|
|
3591
|
+
if (sub.type === Prefilter.Type.EXACT) {
|
|
3592
|
+
if (seen.has(sub.str)) continue;
|
|
3593
|
+
seen.add(sub.str);
|
|
3362
3594
|
}
|
|
3363
|
-
|
|
3595
|
+
subs.push(sub);
|
|
3364
3596
|
}
|
|
3365
|
-
}
|
|
3366
|
-
static simplify(pf) {
|
|
3367
|
-
if (pf.type === Prefilter.Type.EXACT || pf.type === Prefilter.Type.NONE) return pf;
|
|
3368
3597
|
if (pf.type === Prefilter.Type.AND) {
|
|
3369
|
-
const
|
|
3370
|
-
|
|
3371
|
-
|
|
3372
|
-
if (
|
|
3373
|
-
|
|
3598
|
+
const kept = [];
|
|
3599
|
+
let cost = 0;
|
|
3600
|
+
for (const sub of subs) {
|
|
3601
|
+
if (cost + sub.cost > Prefilter.MAX_SCANS) continue;
|
|
3602
|
+
kept.push(sub);
|
|
3603
|
+
cost += sub.cost;
|
|
3374
3604
|
}
|
|
3375
|
-
if (
|
|
3376
|
-
if (
|
|
3377
|
-
pf.subs =
|
|
3605
|
+
if (kept.length === 0) return new Prefilter(Prefilter.Type.NONE);
|
|
3606
|
+
if (kept.length === 1) return kept[0];
|
|
3607
|
+
pf.subs = kept;
|
|
3608
|
+
pf.cost = cost;
|
|
3378
3609
|
return pf;
|
|
3379
3610
|
}
|
|
3380
|
-
if (
|
|
3381
|
-
|
|
3382
|
-
|
|
3383
|
-
|
|
3384
|
-
|
|
3385
|
-
|
|
3386
|
-
|
|
3387
|
-
|
|
3388
|
-
|
|
3389
|
-
|
|
3390
|
-
|
|
3391
|
-
|
|
3392
|
-
|
|
3393
|
-
|
|
3394
|
-
|
|
3395
|
-
uniqueSubs.push(sub);
|
|
3396
|
-
}
|
|
3397
|
-
} else uniqueSubs.push(sub);
|
|
3398
|
-
pf.subs = uniqueSubs;
|
|
3399
|
-
let allExact = true;
|
|
3400
|
-
for (const sub of uniqueSubs) if (sub.type !== Prefilter.Type.EXACT) {
|
|
3401
|
-
allExact = false;
|
|
3402
|
-
break;
|
|
3403
|
-
}
|
|
3404
|
-
if (allExact && uniqueSubs.length > 1) {
|
|
3405
|
-
pf.ac16 = new AhoCorasick(uniqueSubs.map((s) => {
|
|
3406
|
-
const arr = [];
|
|
3407
|
-
for (let i = 0; i < s.str.length; i++) arr.push(s.str.charCodeAt(i));
|
|
3408
|
-
return arr;
|
|
3409
|
-
}));
|
|
3410
|
-
pf.ac8 = new AhoCorasick(uniqueSubs.map((s) => s.bytes));
|
|
3411
|
-
}
|
|
3611
|
+
if (subs.length === 0) return new Prefilter(Prefilter.Type.NONE);
|
|
3612
|
+
if (subs.length === 1) return subs[0];
|
|
3613
|
+
pf.subs = subs;
|
|
3614
|
+
let allExact = true;
|
|
3615
|
+
let cost = 0;
|
|
3616
|
+
let units = 0;
|
|
3617
|
+
for (const sub of subs) {
|
|
3618
|
+
if (sub.type !== Prefilter.Type.EXACT) allExact = false;
|
|
3619
|
+
else units += sub.bytes.length;
|
|
3620
|
+
cost += sub.cost;
|
|
3621
|
+
}
|
|
3622
|
+
if (allExact) {
|
|
3623
|
+
if (units > Prefilter.MAX_AC_UNITS) return new Prefilter(Prefilter.Type.NONE);
|
|
3624
|
+
pf.allExact = true;
|
|
3625
|
+
pf.cost = 1;
|
|
3412
3626
|
return pf;
|
|
3413
3627
|
}
|
|
3628
|
+
if (cost > Prefilter.MAX_SCANS) return new Prefilter(Prefilter.Type.NONE);
|
|
3629
|
+
pf.cost = cost;
|
|
3414
3630
|
return pf;
|
|
3415
3631
|
}
|
|
3416
3632
|
};
|
|
@@ -3446,6 +3662,7 @@
|
|
|
3446
3662
|
this.numCap = 2;
|
|
3447
3663
|
this.lbStarts = [];
|
|
3448
3664
|
this.numLb = 0;
|
|
3665
|
+
this.lbInst = null;
|
|
3449
3666
|
}
|
|
3450
3667
|
getInst(pc) {
|
|
3451
3668
|
return this.inst[pc];
|
|
@@ -3456,6 +3673,26 @@
|
|
|
3456
3673
|
addInst(op) {
|
|
3457
3674
|
this.inst.push(new Inst(op));
|
|
3458
3675
|
}
|
|
3676
|
+
markLookbehindInsts() {
|
|
3677
|
+
const lbInst = new Uint8Array(this.inst.length);
|
|
3678
|
+
const pending = this.lbStarts.slice();
|
|
3679
|
+
while (pending.length > 0) {
|
|
3680
|
+
const pc = pending.pop();
|
|
3681
|
+
if (pc === 0 || lbInst[pc] === 1) continue;
|
|
3682
|
+
lbInst[pc] = 1;
|
|
3683
|
+
const i = this.inst[pc];
|
|
3684
|
+
switch (i.op) {
|
|
3685
|
+
case Inst.ALT:
|
|
3686
|
+
case Inst.ALT_MATCH:
|
|
3687
|
+
pending.push(i.out, i.arg);
|
|
3688
|
+
break;
|
|
3689
|
+
case Inst.MATCH:
|
|
3690
|
+
case Inst.FAIL: break;
|
|
3691
|
+
default: pending.push(i.out);
|
|
3692
|
+
}
|
|
3693
|
+
}
|
|
3694
|
+
this.lbInst = lbInst;
|
|
3695
|
+
}
|
|
3459
3696
|
skipNop(pc) {
|
|
3460
3697
|
let i = this.inst[pc];
|
|
3461
3698
|
while (i.op === Inst.NOP || i.op === Inst.CAPTURE) {
|
|
@@ -3468,7 +3705,7 @@
|
|
|
3468
3705
|
let prefix = "";
|
|
3469
3706
|
let i = this.skipNop(this.start);
|
|
3470
3707
|
if (!Inst.isRuneOp(i.op) || i.runes.length !== 1) return [i.op === Inst.MATCH, prefix];
|
|
3471
|
-
while (Inst.isRuneOp(i.op) && i.runes.length === 1 && (i.arg & RE2Flags.FOLD_CASE) === 0) {
|
|
3708
|
+
while (Inst.isRuneOp(i.op) && i.runes.length === 1 && (i.arg & RE2Flags.FOLD_CASE) === 0 && !Unicode.isUnsearchable(i.runes[0])) {
|
|
3472
3709
|
prefix += String.fromCodePoint(i.runes[0]);
|
|
3473
3710
|
i = this.skipNop(i.out);
|
|
3474
3711
|
}
|
|
@@ -3532,6 +3769,13 @@
|
|
|
3532
3769
|
};
|
|
3533
3770
|
//#endregion
|
|
3534
3771
|
//#region src/Compiler.js
|
|
3772
|
+
const ANY_RUNE_NOT_NL = new Int32Array([
|
|
3773
|
+
0,
|
|
3774
|
+
Codepoint.CODES.get("\n") - 1,
|
|
3775
|
+
Codepoint.CODES.get("\n") + 1,
|
|
3776
|
+
Unicode.MAX_RUNE
|
|
3777
|
+
]);
|
|
3778
|
+
const ANY_RUNE = new Int32Array([0, Unicode.MAX_RUNE]);
|
|
3535
3779
|
/**
|
|
3536
3780
|
* A fragment of a compiled regular expression program.
|
|
3537
3781
|
*
|
|
@@ -3551,28 +3795,19 @@
|
|
|
3551
3795
|
* The only entry point is {@link #compileRegexp}.
|
|
3552
3796
|
*/
|
|
3553
3797
|
var Compiler = class Compiler {
|
|
3554
|
-
static ANY_RUNE_NOT_NL() {
|
|
3555
|
-
return [
|
|
3556
|
-
0,
|
|
3557
|
-
Codepoint.CODES.get("\n") - 1,
|
|
3558
|
-
Codepoint.CODES.get("\n") + 1,
|
|
3559
|
-
Unicode.MAX_RUNE
|
|
3560
|
-
];
|
|
3561
|
-
}
|
|
3562
|
-
static ANY_RUNE() {
|
|
3563
|
-
return [0, Unicode.MAX_RUNE];
|
|
3564
|
-
}
|
|
3565
3798
|
static compileRegexp(re) {
|
|
3566
3799
|
const c = new Compiler();
|
|
3567
3800
|
const f = c.compile(re);
|
|
3568
3801
|
c.prog.patch(f.out, c.newInst(Inst.MATCH).i);
|
|
3569
3802
|
c.prog.start = f.i;
|
|
3803
|
+
c.prog.markLookbehindInsts();
|
|
3570
3804
|
return c.prog;
|
|
3571
3805
|
}
|
|
3572
3806
|
static compileSet(regexps) {
|
|
3573
3807
|
const c = new Compiler();
|
|
3574
3808
|
if (regexps.length === 0) {
|
|
3575
3809
|
c.prog.start = c.newInst(Inst.FAIL).i;
|
|
3810
|
+
c.prog.markLookbehindInsts();
|
|
3576
3811
|
return c.prog;
|
|
3577
3812
|
}
|
|
3578
3813
|
let starts = [];
|
|
@@ -3592,11 +3827,19 @@
|
|
|
3592
3827
|
start = f.i;
|
|
3593
3828
|
}
|
|
3594
3829
|
c.prog.start = start;
|
|
3830
|
+
c.prog.markLookbehindInsts();
|
|
3595
3831
|
return c.prog;
|
|
3596
3832
|
}
|
|
3597
3833
|
constructor() {
|
|
3598
3834
|
this.prog = new Prog();
|
|
3599
3835
|
this.newInst(Inst.FAIL);
|
|
3836
|
+
this.runeCache = /* @__PURE__ */ new Map();
|
|
3837
|
+
this.walker = {
|
|
3838
|
+
leaf: (re) => this.leaf(re),
|
|
3839
|
+
enter: (re) => this.enter(re),
|
|
3840
|
+
child: (re, state, result) => this.child(re, state, result),
|
|
3841
|
+
leave: (re, state) => this.leave(re, state)
|
|
3842
|
+
};
|
|
3600
3843
|
}
|
|
3601
3844
|
newInst(op) {
|
|
3602
3845
|
this.prog.addInst(op);
|
|
@@ -3689,7 +3932,7 @@
|
|
|
3689
3932
|
lookBehind(a, lb) {
|
|
3690
3933
|
const id = this.newInst(Inst.LB_WRITE);
|
|
3691
3934
|
this.prog.getInst(id.i).arg = lb;
|
|
3692
|
-
const any = this.rune(
|
|
3935
|
+
const any = this.rune(ANY_RUNE, 0);
|
|
3693
3936
|
const dotStar = this.star(any, true);
|
|
3694
3937
|
const lbAutomaton = this.cat(dotStar, a);
|
|
3695
3938
|
this.prog.patch(lbAutomaton.out, id.i);
|
|
@@ -3701,56 +3944,74 @@
|
|
|
3701
3944
|
return checkId;
|
|
3702
3945
|
}
|
|
3703
3946
|
compile(re) {
|
|
3947
|
+
return RegexpWalker.walk(re, this.walker);
|
|
3948
|
+
}
|
|
3949
|
+
leaf(re) {
|
|
3704
3950
|
switch (re.op) {
|
|
3705
3951
|
case Regexp.Op.NO_MATCH: return this.fail();
|
|
3706
3952
|
case Regexp.Op.EMPTY_MATCH: return this.nop();
|
|
3707
|
-
case Regexp.Op.LITERAL:
|
|
3708
|
-
|
|
3953
|
+
case Regexp.Op.LITERAL: {
|
|
3954
|
+
if (re.runes.length === 0) return this.nop();
|
|
3709
3955
|
let f = null;
|
|
3710
3956
|
for (let r of re.runes) {
|
|
3711
|
-
|
|
3957
|
+
let singleRune = this.runeCache.get(r);
|
|
3958
|
+
if (singleRune === void 0) {
|
|
3959
|
+
singleRune = new Int32Array([r]);
|
|
3960
|
+
this.runeCache.set(r, singleRune);
|
|
3961
|
+
}
|
|
3962
|
+
const f1 = this.rune(singleRune, re.flags);
|
|
3712
3963
|
f = f === null ? f1 : this.cat(f, f1);
|
|
3713
3964
|
}
|
|
3714
3965
|
return f;
|
|
3715
3966
|
}
|
|
3716
3967
|
case Regexp.Op.CHAR_CLASS: return this.rune(re.runes, re.flags);
|
|
3717
|
-
case Regexp.Op.ANY_CHAR_NOT_NL: return this.rune(
|
|
3718
|
-
case Regexp.Op.ANY_CHAR: return this.rune(
|
|
3968
|
+
case Regexp.Op.ANY_CHAR_NOT_NL: return this.rune(ANY_RUNE_NOT_NL, 0);
|
|
3969
|
+
case Regexp.Op.ANY_CHAR: return this.rune(ANY_RUNE, 0);
|
|
3719
3970
|
case Regexp.Op.BEGIN_LINE: return this.empty(Utils.EMPTY_BEGIN_LINE);
|
|
3720
3971
|
case Regexp.Op.END_LINE: return this.empty(Utils.EMPTY_END_LINE);
|
|
3721
3972
|
case Regexp.Op.BEGIN_TEXT: return this.empty(Utils.EMPTY_BEGIN_TEXT);
|
|
3722
3973
|
case Regexp.Op.END_TEXT: return this.empty(Utils.EMPTY_END_TEXT);
|
|
3723
3974
|
case Regexp.Op.WORD_BOUNDARY: return this.empty(Utils.EMPTY_WORD_BOUNDARY);
|
|
3724
3975
|
case Regexp.Op.NO_WORD_BOUNDARY: return this.empty(Utils.EMPTY_NO_WORD_BOUNDARY);
|
|
3976
|
+
case Regexp.Op.CONCAT:
|
|
3977
|
+
case Regexp.Op.ALTERNATE: return this.nop();
|
|
3978
|
+
default: throw new RE2JSCompileException("regexp: unhandled case in compile");
|
|
3979
|
+
}
|
|
3980
|
+
}
|
|
3981
|
+
enter(re) {
|
|
3982
|
+
switch (re.op) {
|
|
3983
|
+
case Regexp.Op.PLB:
|
|
3984
|
+
case Regexp.Op.NLB:
|
|
3985
|
+
case Regexp.Op.STAR:
|
|
3986
|
+
case Regexp.Op.PLUS:
|
|
3987
|
+
case Regexp.Op.QUEST: return { sub: null };
|
|
3988
|
+
case Regexp.Op.CAPTURE: return {
|
|
3989
|
+
bra: this.cap(re.cap << 1),
|
|
3990
|
+
sub: null
|
|
3991
|
+
};
|
|
3992
|
+
case Regexp.Op.CONCAT:
|
|
3993
|
+
case Regexp.Op.ALTERNATE: return { f: null };
|
|
3994
|
+
default: throw new RE2JSCompileException("regexp: unhandled case in compile");
|
|
3995
|
+
}
|
|
3996
|
+
}
|
|
3997
|
+
child(re, state, f1) {
|
|
3998
|
+
if (re.op === Regexp.Op.CONCAT) state.f = state.f === null ? f1 : this.cat(state.f, f1);
|
|
3999
|
+
else if (re.op === Regexp.Op.ALTERNATE) state.f = state.f === null ? f1 : this.alt(state.f, f1);
|
|
4000
|
+
else state.sub = f1;
|
|
4001
|
+
}
|
|
4002
|
+
leave(re, state) {
|
|
4003
|
+
switch (re.op) {
|
|
3725
4004
|
case Regexp.Op.PLB:
|
|
3726
|
-
case Regexp.Op.NLB: return this.lookBehind(
|
|
4005
|
+
case Regexp.Op.NLB: return this.lookBehind(state.sub, re.lb);
|
|
3727
4006
|
case Regexp.Op.CAPTURE: {
|
|
3728
|
-
const bra = this.cap(re.cap << 1);
|
|
3729
|
-
const sub = this.compile(re.subs[0]);
|
|
3730
4007
|
const ket = this.cap(re.cap << 1 | 1);
|
|
3731
|
-
return this.cat(this.cat(bra, sub), ket);
|
|
3732
|
-
}
|
|
3733
|
-
case Regexp.Op.STAR: return this.star(this.compile(re.subs[0]), (re.flags & RE2Flags.NON_GREEDY) !== 0);
|
|
3734
|
-
case Regexp.Op.PLUS: return this.plus(this.compile(re.subs[0]), (re.flags & RE2Flags.NON_GREEDY) !== 0);
|
|
3735
|
-
case Regexp.Op.QUEST: return this.quest(this.compile(re.subs[0]), (re.flags & RE2Flags.NON_GREEDY) !== 0);
|
|
3736
|
-
case Regexp.Op.CONCAT: if (re.subs.length === 0) return this.nop();
|
|
3737
|
-
else {
|
|
3738
|
-
let f = null;
|
|
3739
|
-
for (let sub of re.subs) {
|
|
3740
|
-
const f1 = this.compile(sub);
|
|
3741
|
-
f = f === null ? f1 : this.cat(f, f1);
|
|
3742
|
-
}
|
|
3743
|
-
return f;
|
|
3744
|
-
}
|
|
3745
|
-
case Regexp.Op.ALTERNATE: if (re.subs.length === 0) return this.nop();
|
|
3746
|
-
else {
|
|
3747
|
-
let f = null;
|
|
3748
|
-
for (let sub of re.subs) {
|
|
3749
|
-
const f1 = this.compile(sub);
|
|
3750
|
-
f = f === null ? f1 : this.alt(f, f1);
|
|
3751
|
-
}
|
|
3752
|
-
return f;
|
|
4008
|
+
return this.cat(this.cat(state.bra, state.sub), ket);
|
|
3753
4009
|
}
|
|
4010
|
+
case Regexp.Op.STAR: return this.star(state.sub, (re.flags & RE2Flags.NON_GREEDY) !== 0);
|
|
4011
|
+
case Regexp.Op.PLUS: return this.plus(state.sub, (re.flags & RE2Flags.NON_GREEDY) !== 0);
|
|
4012
|
+
case Regexp.Op.QUEST: return this.quest(state.sub, (re.flags & RE2Flags.NON_GREEDY) !== 0);
|
|
4013
|
+
case Regexp.Op.CONCAT:
|
|
4014
|
+
case Regexp.Op.ALTERNATE: return state.f;
|
|
3754
4015
|
default: throw new RE2JSCompileException("regexp: unhandled case in compile");
|
|
3755
4016
|
}
|
|
3756
4017
|
}
|
|
@@ -3760,111 +4021,149 @@
|
|
|
3760
4021
|
var Simplify = class Simplify {
|
|
3761
4022
|
static simplify(re) {
|
|
3762
4023
|
if (re === null) return null;
|
|
4024
|
+
return RegexpWalker.walk(re, Simplify.WALKER);
|
|
4025
|
+
}
|
|
4026
|
+
static WALKER = {
|
|
4027
|
+
leaf: (re) => Simplify.leaf(re),
|
|
4028
|
+
enter: (re) => Simplify.enter(re),
|
|
4029
|
+
child: (re, state, result, i) => Simplify.child(re, state, result, i),
|
|
4030
|
+
leave: (re, state) => Simplify.leave(re, state)
|
|
4031
|
+
};
|
|
4032
|
+
static leaf(re) {
|
|
4033
|
+
if (re.op === Regexp.Op.CHAR_CLASS) {
|
|
4034
|
+
if (re.runes === null) return re;
|
|
4035
|
+
if (re.runes.length === 0) return new Regexp(Regexp.Op.NO_MATCH);
|
|
4036
|
+
if (re.runes.length === 2 && re.runes[0] === 0 && re.runes[1] === Unicode.MAX_RUNE) return new Regexp(Regexp.Op.ANY_CHAR);
|
|
4037
|
+
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);
|
|
4038
|
+
}
|
|
4039
|
+
return re;
|
|
4040
|
+
}
|
|
4041
|
+
static enter(re) {
|
|
4042
|
+
switch (re.op) {
|
|
4043
|
+
case Regexp.Op.PLB:
|
|
4044
|
+
case Regexp.Op.NLB:
|
|
4045
|
+
case Regexp.Op.CAPTURE:
|
|
4046
|
+
case Regexp.Op.STAR:
|
|
4047
|
+
case Regexp.Op.PLUS:
|
|
4048
|
+
case Regexp.Op.QUEST: return { sub: null };
|
|
4049
|
+
case Regexp.Op.CONCAT:
|
|
4050
|
+
case Regexp.Op.ALTERNATE: return {
|
|
4051
|
+
subs: [],
|
|
4052
|
+
changed: false
|
|
4053
|
+
};
|
|
4054
|
+
case Regexp.Op.REPEAT:
|
|
4055
|
+
if (re.min === 0 && re.max === 0) return { result: new Regexp(Regexp.Op.EMPTY_MATCH) };
|
|
4056
|
+
return { sub: null };
|
|
4057
|
+
default: return { result: re };
|
|
4058
|
+
}
|
|
4059
|
+
}
|
|
4060
|
+
static child(re, state, nsub, i) {
|
|
4061
|
+
if (state.subs === void 0) {
|
|
4062
|
+
state.sub = nsub;
|
|
4063
|
+
return;
|
|
4064
|
+
}
|
|
4065
|
+
if (nsub !== re.subs[i]) state.changed = true;
|
|
4066
|
+
if (re.op === Regexp.Op.CONCAT) {
|
|
4067
|
+
if (nsub.op === Regexp.Op.NO_MATCH) {
|
|
4068
|
+
state.result = new Regexp(Regexp.Op.NO_MATCH);
|
|
4069
|
+
return;
|
|
4070
|
+
}
|
|
4071
|
+
if (nsub.op === Regexp.Op.EMPTY_MATCH) {
|
|
4072
|
+
state.changed = true;
|
|
4073
|
+
return;
|
|
4074
|
+
}
|
|
4075
|
+
if (nsub.op === Regexp.Op.CONCAT) {
|
|
4076
|
+
state.changed = true;
|
|
4077
|
+
for (let j = 0; j < nsub.subs.length; j++) state.subs.push(nsub.subs[j]);
|
|
4078
|
+
return;
|
|
4079
|
+
}
|
|
4080
|
+
} else {
|
|
4081
|
+
if (nsub.op === Regexp.Op.NO_MATCH) {
|
|
4082
|
+
state.changed = true;
|
|
4083
|
+
return;
|
|
4084
|
+
}
|
|
4085
|
+
if (nsub.op === Regexp.Op.ALTERNATE) {
|
|
4086
|
+
state.changed = true;
|
|
4087
|
+
for (let j = 0; j < nsub.subs.length; j++) state.subs.push(nsub.subs[j]);
|
|
4088
|
+
return;
|
|
4089
|
+
}
|
|
4090
|
+
}
|
|
4091
|
+
state.subs.push(nsub);
|
|
4092
|
+
}
|
|
4093
|
+
static leave(re, state) {
|
|
3763
4094
|
switch (re.op) {
|
|
3764
4095
|
case Regexp.Op.PLB:
|
|
3765
4096
|
case Regexp.Op.NLB:
|
|
3766
4097
|
case Regexp.Op.CAPTURE: {
|
|
3767
|
-
const sub =
|
|
4098
|
+
const sub = state.sub;
|
|
3768
4099
|
if (sub !== re.subs[0]) {
|
|
3769
4100
|
const nre = Regexp.fromRegexp(re);
|
|
3770
|
-
nre.runes =
|
|
4101
|
+
nre.runes = /* @__PURE__ */ new Int32Array(0);
|
|
3771
4102
|
nre.subs = [sub];
|
|
3772
4103
|
return nre;
|
|
3773
4104
|
}
|
|
3774
4105
|
return re;
|
|
3775
4106
|
}
|
|
3776
4107
|
case Regexp.Op.CONCAT:
|
|
3777
|
-
case Regexp.Op.ALTERNATE:
|
|
3778
|
-
|
|
3779
|
-
|
|
3780
|
-
for (let i = 0; i < re.subs.length; i++) {
|
|
3781
|
-
const sub = re.subs[i];
|
|
3782
|
-
const nsub = Simplify.simplify(sub);
|
|
3783
|
-
if (nsub !== sub) changed = true;
|
|
3784
|
-
if (re.op === Regexp.Op.CONCAT) {
|
|
3785
|
-
if (nsub.op === Regexp.Op.NO_MATCH) return new Regexp(Regexp.Op.NO_MATCH);
|
|
3786
|
-
if (nsub.op === Regexp.Op.EMPTY_MATCH) {
|
|
3787
|
-
changed = true;
|
|
3788
|
-
continue;
|
|
3789
|
-
}
|
|
3790
|
-
if (nsub.op === Regexp.Op.CONCAT) {
|
|
3791
|
-
changed = true;
|
|
3792
|
-
for (let j = 0; j < nsub.subs.length; j++) newSubs.push(nsub.subs[j]);
|
|
3793
|
-
continue;
|
|
3794
|
-
}
|
|
3795
|
-
} else if (re.op === Regexp.Op.ALTERNATE) {
|
|
3796
|
-
if (nsub.op === Regexp.Op.NO_MATCH) {
|
|
3797
|
-
changed = true;
|
|
3798
|
-
continue;
|
|
3799
|
-
}
|
|
3800
|
-
if (nsub.op === Regexp.Op.ALTERNATE) {
|
|
3801
|
-
changed = true;
|
|
3802
|
-
for (let j = 0; j < nsub.subs.length; j++) newSubs.push(nsub.subs[j]);
|
|
3803
|
-
continue;
|
|
3804
|
-
}
|
|
3805
|
-
}
|
|
3806
|
-
newSubs.push(nsub);
|
|
3807
|
-
}
|
|
3808
|
-
if (changed) {
|
|
4108
|
+
case Regexp.Op.ALTERNATE:
|
|
4109
|
+
if (state.changed) {
|
|
4110
|
+
const newSubs = state.subs;
|
|
3809
4111
|
if (newSubs.length === 0) return new Regexp(re.op === Regexp.Op.CONCAT ? Regexp.Op.EMPTY_MATCH : Regexp.Op.NO_MATCH);
|
|
3810
4112
|
if (newSubs.length === 1) return newSubs[0];
|
|
3811
4113
|
const nre = Regexp.fromRegexp(re);
|
|
3812
|
-
nre.runes =
|
|
4114
|
+
nre.runes = /* @__PURE__ */ new Int32Array(0);
|
|
3813
4115
|
nre.subs = newSubs;
|
|
3814
4116
|
return nre;
|
|
3815
4117
|
}
|
|
3816
4118
|
return re;
|
|
3817
|
-
}
|
|
3818
|
-
case Regexp.Op.CHAR_CLASS:
|
|
3819
|
-
if (re.runes === null) return re;
|
|
3820
|
-
if (re.runes.length === 0) return new Regexp(Regexp.Op.NO_MATCH);
|
|
3821
|
-
if (re.runes.length === 2 && re.runes[0] === 0 && re.runes[1] === Unicode.MAX_RUNE) return new Regexp(Regexp.Op.ANY_CHAR);
|
|
3822
|
-
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);
|
|
3823
|
-
return re;
|
|
3824
4119
|
case Regexp.Op.STAR:
|
|
3825
4120
|
case Regexp.Op.PLUS:
|
|
3826
|
-
case Regexp.Op.QUEST:
|
|
3827
|
-
|
|
3828
|
-
|
|
3829
|
-
|
|
3830
|
-
|
|
3831
|
-
|
|
3832
|
-
|
|
3833
|
-
|
|
3834
|
-
|
|
3835
|
-
|
|
3836
|
-
|
|
3837
|
-
|
|
3838
|
-
|
|
3839
|
-
|
|
3840
|
-
|
|
3841
|
-
|
|
3842
|
-
|
|
3843
|
-
|
|
3844
|
-
|
|
3845
|
-
|
|
3846
|
-
|
|
3847
|
-
|
|
3848
|
-
|
|
3849
|
-
|
|
3850
|
-
|
|
3851
|
-
|
|
3852
|
-
|
|
3853
|
-
|
|
3854
|
-
|
|
3855
|
-
|
|
3856
|
-
|
|
3857
|
-
|
|
3858
|
-
|
|
3859
|
-
|
|
3860
|
-
|
|
3861
|
-
|
|
3862
|
-
|
|
3863
|
-
|
|
3864
|
-
return new Regexp(Regexp.Op.NO_MATCH);
|
|
4121
|
+
case Regexp.Op.QUEST: return Simplify.simplify1(re.op, re.flags, state.sub, re);
|
|
4122
|
+
case Regexp.Op.REPEAT: return Simplify.simplifyRepeat(re, state.sub);
|
|
4123
|
+
default: return re;
|
|
4124
|
+
}
|
|
4125
|
+
}
|
|
4126
|
+
static simplifyRepeat(re, sub) {
|
|
4127
|
+
if (re.max === -1) {
|
|
4128
|
+
if (re.min === 0) return Simplify.simplify1(Regexp.Op.STAR, re.flags, sub, null);
|
|
4129
|
+
if (re.min === 1) return Simplify.simplify1(Regexp.Op.PLUS, re.flags, sub, null);
|
|
4130
|
+
const subs = [];
|
|
4131
|
+
for (let i = 0; i < re.min - 1; i++) subs.push(sub);
|
|
4132
|
+
subs.push(Simplify.simplify1(Regexp.Op.PLUS, re.flags, sub, null));
|
|
4133
|
+
return Simplify.concat(subs);
|
|
4134
|
+
}
|
|
4135
|
+
if (re.min === 1 && re.max === 1) return sub;
|
|
4136
|
+
let prefixSubs = null;
|
|
4137
|
+
if (re.min > 0) {
|
|
4138
|
+
prefixSubs = [];
|
|
4139
|
+
for (let i = 0; i < re.min; i++) prefixSubs.push(sub);
|
|
4140
|
+
}
|
|
4141
|
+
if (re.max > re.min) {
|
|
4142
|
+
let suffix = Simplify.simplify1(Regexp.Op.QUEST, re.flags, sub, null);
|
|
4143
|
+
for (let i = re.min + 1; i < re.max; i++) suffix = Simplify.simplify1(Regexp.Op.QUEST, re.flags, Simplify.concat([sub, suffix]), null);
|
|
4144
|
+
if (prefixSubs === null) return suffix;
|
|
4145
|
+
prefixSubs.push(suffix);
|
|
4146
|
+
}
|
|
4147
|
+
if (prefixSubs !== null) return Simplify.concat(prefixSubs);
|
|
4148
|
+
return new Regexp(Regexp.Op.NO_MATCH);
|
|
4149
|
+
}
|
|
4150
|
+
static concat(subs) {
|
|
4151
|
+
const newSubs = [];
|
|
4152
|
+
for (let i = 0; i < subs.length; i++) {
|
|
4153
|
+
const sub = subs[i];
|
|
4154
|
+
if (sub.op === Regexp.Op.NO_MATCH) return new Regexp(Regexp.Op.NO_MATCH);
|
|
4155
|
+
if (sub.op === Regexp.Op.EMPTY_MATCH) continue;
|
|
4156
|
+
if (sub.op === Regexp.Op.CONCAT) {
|
|
4157
|
+
for (let j = 0; j < sub.subs.length; j++) newSubs.push(sub.subs[j]);
|
|
4158
|
+
continue;
|
|
3865
4159
|
}
|
|
4160
|
+
newSubs.push(sub);
|
|
3866
4161
|
}
|
|
3867
|
-
return
|
|
4162
|
+
if (newSubs.length === 0) return new Regexp(Regexp.Op.EMPTY_MATCH);
|
|
4163
|
+
if (newSubs.length === 1) return newSubs[0];
|
|
4164
|
+
const nre = new Regexp(Regexp.Op.CONCAT);
|
|
4165
|
+
nre.subs = newSubs;
|
|
4166
|
+
return nre;
|
|
3868
4167
|
}
|
|
3869
4168
|
static simplify1(op, flags, sub, re) {
|
|
3870
4169
|
if (sub.op === Regexp.Op.EMPTY_MATCH) return sub;
|
|
@@ -4032,46 +4331,35 @@
|
|
|
4032
4331
|
result += "]";
|
|
4033
4332
|
return result;
|
|
4034
4333
|
}
|
|
4035
|
-
static
|
|
4036
|
-
const
|
|
4037
|
-
|
|
4038
|
-
|
|
4039
|
-
|
|
4040
|
-
const
|
|
4041
|
-
|
|
4042
|
-
|
|
4043
|
-
|
|
4044
|
-
let j = right;
|
|
4045
|
-
while (i <= j) {
|
|
4046
|
-
while (i < right && CharClass.cmp(array, i, pivotFrom, pivotTo) < 0) i += 2;
|
|
4047
|
-
while (j > left && CharClass.cmp(array, j, pivotFrom, pivotTo) > 0) j -= 2;
|
|
4048
|
-
if (i <= j) {
|
|
4049
|
-
if (i !== j) {
|
|
4050
|
-
let temp = array[i];
|
|
4051
|
-
array[i] = array[j];
|
|
4052
|
-
array[j] = temp;
|
|
4053
|
-
temp = array[i + 1];
|
|
4054
|
-
array[i + 1] = array[j + 1];
|
|
4055
|
-
array[j + 1] = temp;
|
|
4056
|
-
}
|
|
4057
|
-
i += 2;
|
|
4058
|
-
j -= 2;
|
|
4059
|
-
}
|
|
4334
|
+
static sortRanges(array, len) {
|
|
4335
|
+
const n = len >> 1;
|
|
4336
|
+
const order = new Array(n);
|
|
4337
|
+
for (let i = 0; i < n; i++) order[i] = i;
|
|
4338
|
+
order.sort((a, b) => array[2 * a] - array[2 * b] || array[2 * b + 1] - array[2 * a + 1]);
|
|
4339
|
+
const sorted = array.slice(0, len);
|
|
4340
|
+
for (let i = 0; i < n; i++) {
|
|
4341
|
+
array[2 * i] = sorted[2 * order[i]];
|
|
4342
|
+
array[2 * i + 1] = sorted[2 * order[i] + 1];
|
|
4060
4343
|
}
|
|
4061
|
-
if (left < j) CharClass.qsortIntPair(array, left, j);
|
|
4062
|
-
if (i < right) CharClass.qsortIntPair(array, i, right);
|
|
4063
4344
|
}
|
|
4064
4345
|
constructor(r = Utils.emptyInts()) {
|
|
4065
4346
|
this.r = r;
|
|
4066
4347
|
this.len = r.length;
|
|
4067
4348
|
}
|
|
4068
4349
|
toArray() {
|
|
4069
|
-
if (this.len === this.r.length
|
|
4070
|
-
|
|
4350
|
+
if (this.r instanceof Int32Array) return this.len === this.r.length ? this.r : this.r.subarray(0, this.len);
|
|
4351
|
+
return new Int32Array(this.len === this.r.length ? this.r : this.r.slice(0, this.len));
|
|
4352
|
+
}
|
|
4353
|
+
toGrowableArray() {
|
|
4354
|
+
if (Array.isArray(this.r)) {
|
|
4355
|
+
this.r.length = this.len;
|
|
4356
|
+
return this.r;
|
|
4357
|
+
}
|
|
4358
|
+
return Array.from(this.r.subarray(0, this.len));
|
|
4071
4359
|
}
|
|
4072
4360
|
cleanClass() {
|
|
4073
4361
|
if (this.len < 4) return this;
|
|
4074
|
-
CharClass.
|
|
4362
|
+
CharClass.sortRanges(this.r, this.len);
|
|
4075
4363
|
let w = 2;
|
|
4076
4364
|
for (let i = 2; i < this.len; i += 2) {
|
|
4077
4365
|
const lo = this.r[i];
|
|
@@ -4275,7 +4563,7 @@
|
|
|
4275
4563
|
static ERR_LARGE = "expression too large";
|
|
4276
4564
|
static ERR_INVALID_CAPTURE_IN_LOOKBEHIND = "invalid capture in lookbehind";
|
|
4277
4565
|
static MAX_HEIGHT = 1e3;
|
|
4278
|
-
static MAX_SIZE =
|
|
4566
|
+
static MAX_SIZE = 1398101;
|
|
4279
4567
|
static MAX_RUNES = 33554432;
|
|
4280
4568
|
static ANY_TABLE = new UnicodeRangeTable(new Uint32Array([
|
|
4281
4569
|
0,
|
|
@@ -4417,15 +4705,17 @@
|
|
|
4417
4705
|
case Regexp.Op.ANY_CHAR_NOT_NL:
|
|
4418
4706
|
if (Parser.matchRune(src, Codepoint.CODES.get("\n"))) dst.op = Regexp.Op.ANY_CHAR;
|
|
4419
4707
|
break;
|
|
4420
|
-
case Regexp.Op.CHAR_CLASS:
|
|
4421
|
-
|
|
4422
|
-
|
|
4708
|
+
case Regexp.Op.CHAR_CLASS: {
|
|
4709
|
+
const cc = new CharClass(Array.isArray(dst.runes) ? dst.runes : Array.from(dst.runes));
|
|
4710
|
+
if (src.op === Regexp.Op.LITERAL) cc.appendLiteral(src.runes[0], src.flags);
|
|
4711
|
+
else cc.appendClass(src.runes);
|
|
4712
|
+
dst.runes = cc.toGrowableArray();
|
|
4423
4713
|
break;
|
|
4714
|
+
}
|
|
4424
4715
|
case Regexp.Op.LITERAL:
|
|
4425
4716
|
if (src.runes[0] === dst.runes[0] && src.flags === dst.flags) break;
|
|
4426
4717
|
dst.op = Regexp.Op.CHAR_CLASS;
|
|
4427
|
-
dst.runes = new CharClass().appendLiteral(dst.runes[0], dst.flags).appendLiteral(src.runes[0], src.flags).
|
|
4428
|
-
break;
|
|
4718
|
+
dst.runes = new CharClass().appendLiteral(dst.runes[0], dst.flags).appendLiteral(src.runes[0], src.flags).toGrowableArray();
|
|
4429
4719
|
}
|
|
4430
4720
|
}
|
|
4431
4721
|
static parseEscape(t) {
|
|
@@ -4482,9 +4772,7 @@
|
|
|
4482
4772
|
case Codepoint.CODES.get("r"): return Codepoint.CODES.get("\r");
|
|
4483
4773
|
case Codepoint.CODES.get("t"): return Codepoint.CODES.get(" ");
|
|
4484
4774
|
case Codepoint.CODES.get("v"): return Codepoint.CODES.get("\v");
|
|
4485
|
-
default:
|
|
4486
|
-
if (c <= Unicode.MAX_ASCII && !Utils.isalnum(c)) return c;
|
|
4487
|
-
break;
|
|
4775
|
+
default: if (c <= Unicode.MAX_ASCII && !Utils.isalnum(c)) return c;
|
|
4488
4776
|
}
|
|
4489
4777
|
throw new RE2JSSyntaxException(Parser.ERR_INVALID_ESCAPE, t.from(startPos));
|
|
4490
4778
|
}
|
|
@@ -4493,10 +4781,6 @@
|
|
|
4493
4781
|
if (t.lookingAt("\\")) return Parser.parseEscape(t);
|
|
4494
4782
|
return t.pop();
|
|
4495
4783
|
}
|
|
4496
|
-
static concatRunes(x, y) {
|
|
4497
|
-
for (let i = 0; i < y.length; i++) x.push(y[i]);
|
|
4498
|
-
return x;
|
|
4499
|
-
}
|
|
4500
4784
|
static hasCapture(re) {
|
|
4501
4785
|
if (re === null) return false;
|
|
4502
4786
|
if (re.op === Regexp.Op.CAPTURE) return true;
|
|
@@ -4627,9 +4911,7 @@
|
|
|
4627
4911
|
const n = this.stack.length;
|
|
4628
4912
|
let i = n;
|
|
4629
4913
|
while (i > 0 && !Regexp.isPseudoOp(this.stack[i - 1].op)) i--;
|
|
4630
|
-
|
|
4631
|
-
this.stack = this.stack.slice(0, i);
|
|
4632
|
-
return r;
|
|
4914
|
+
return this.stack.splice(i, n - i);
|
|
4633
4915
|
}
|
|
4634
4916
|
push(re) {
|
|
4635
4917
|
this.numRunes += re.runes.length;
|
|
@@ -4654,7 +4936,8 @@
|
|
|
4654
4936
|
const re1 = this.stack[n - 1];
|
|
4655
4937
|
const re2 = this.stack[n - 2];
|
|
4656
4938
|
if (re1.op !== Regexp.Op.LITERAL || re2.op !== Regexp.Op.LITERAL || (re1.flags & RE2Flags.FOLD_CASE) !== (re2.flags & RE2Flags.FOLD_CASE)) return false;
|
|
4657
|
-
re2.runes =
|
|
4939
|
+
if (!Array.isArray(re2.runes)) re2.runes = Array.from(re2.runes);
|
|
4940
|
+
for (let i = 0; i < re1.runes.length; i++) re2.runes.push(re1.runes[i]);
|
|
4658
4941
|
if (r >= 0) {
|
|
4659
4942
|
re1.runes = [r];
|
|
4660
4943
|
re1.flags = flags;
|
|
@@ -4726,12 +5009,12 @@
|
|
|
4726
5009
|
}
|
|
4727
5010
|
cleanAlt(re) {
|
|
4728
5011
|
if (re.op === Regexp.Op.CHAR_CLASS) {
|
|
4729
|
-
re.runes = new CharClass(re.runes).cleanClass().toArray();
|
|
5012
|
+
re.runes = new CharClass(Array.from(re.runes)).cleanClass().toArray();
|
|
4730
5013
|
if (re.runes.length === 2 && re.runes[0] === 0 && re.runes[1] === Unicode.MAX_RUNE) {
|
|
4731
|
-
re.runes =
|
|
5014
|
+
re.runes = /* @__PURE__ */ new Int32Array(0);
|
|
4732
5015
|
re.op = Regexp.Op.ANY_CHAR;
|
|
4733
5016
|
} 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) {
|
|
4734
|
-
re.runes =
|
|
5017
|
+
re.runes = /* @__PURE__ */ new Int32Array(0);
|
|
4735
5018
|
re.op = Regexp.Op.ANY_CHAR_NOT_NL;
|
|
4736
5019
|
}
|
|
4737
5020
|
}
|
|
@@ -4891,9 +5174,7 @@
|
|
|
4891
5174
|
this.reuse(old);
|
|
4892
5175
|
break;
|
|
4893
5176
|
}
|
|
4894
|
-
default:
|
|
4895
|
-
re.subs = re.subs.slice(1, re.subs.length);
|
|
4896
|
-
break;
|
|
5177
|
+
default: re.subs = re.subs.slice(1, re.subs.length);
|
|
4897
5178
|
}
|
|
4898
5179
|
}
|
|
4899
5180
|
return re;
|
|
@@ -4992,9 +5273,7 @@
|
|
|
4992
5273
|
case Codepoint.CODES.get("+"):
|
|
4993
5274
|
op = Regexp.Op.PLUS;
|
|
4994
5275
|
break;
|
|
4995
|
-
case Codepoint.CODES.get("?"):
|
|
4996
|
-
op = Regexp.Op.QUEST;
|
|
4997
|
-
break;
|
|
5276
|
+
case Codepoint.CODES.get("?"): op = Regexp.Op.QUEST;
|
|
4998
5277
|
}
|
|
4999
5278
|
this.repeat(op, min, max, repeatPos, t, lastRepeatPos);
|
|
5000
5279
|
break;
|
|
@@ -5045,9 +5324,7 @@
|
|
|
5045
5324
|
case Codepoint.CODES.get("z"):
|
|
5046
5325
|
this.op(Regexp.Op.END_TEXT);
|
|
5047
5326
|
break bigswitch;
|
|
5048
|
-
default:
|
|
5049
|
-
t.rewindTo(savedPos);
|
|
5050
|
-
break;
|
|
5327
|
+
default: t.rewindTo(savedPos);
|
|
5051
5328
|
}
|
|
5052
5329
|
else t.rewindTo(savedPos);
|
|
5053
5330
|
const re = this.newRegexp(Regexp.Op.CHAR_CLASS);
|
|
@@ -5071,9 +5348,7 @@
|
|
|
5071
5348
|
this.literal(Parser.parseEscape(t));
|
|
5072
5349
|
break;
|
|
5073
5350
|
}
|
|
5074
|
-
default:
|
|
5075
|
-
this.literal(t.pop());
|
|
5076
|
-
break;
|
|
5351
|
+
default: this.literal(t.pop());
|
|
5077
5352
|
}
|
|
5078
5353
|
lastRepeatPos = repeatPos;
|
|
5079
5354
|
}
|
|
@@ -5271,7 +5546,7 @@
|
|
|
5271
5546
|
if ((this.flags & RE2Flags.FOLD_CASE) === 0 || fold === null) cc.appendTableWithSign(tab, sign);
|
|
5272
5547
|
else {
|
|
5273
5548
|
const tmp = new CharClass().appendTable(tab).appendTable(fold).cleanClass().toArray();
|
|
5274
|
-
cc.appendClassWithSign(tmp, sign);
|
|
5549
|
+
cc.appendClassWithSign(Array.from(tmp), sign);
|
|
5275
5550
|
}
|
|
5276
5551
|
return true;
|
|
5277
5552
|
}
|
|
@@ -5449,7 +5724,10 @@
|
|
|
5449
5724
|
}
|
|
5450
5725
|
return [];
|
|
5451
5726
|
}
|
|
5452
|
-
|
|
5727
|
+
createLookbehindState() {
|
|
5728
|
+
return this.prog.numLb > 0 ? new LookbehindState(this.prog) : null;
|
|
5729
|
+
}
|
|
5730
|
+
executeEngine(input, pos, anchor, ncap, lbState = null) {
|
|
5453
5731
|
if (this.prefixComplete && (ncap === 0 || this.numSubexp === 0)) return this.matchPrefixComplete(input, pos, anchor, ncap);
|
|
5454
5732
|
if (this.prefilter !== null && anchor === RE2Flags.UNANCHORED) {
|
|
5455
5733
|
if (!this.prefilter.eval(input, pos)) return null;
|
|
@@ -5457,14 +5735,14 @@
|
|
|
5457
5735
|
if (this.onepass !== null) return OnePass.execute(this, input, pos, anchor, ncap);
|
|
5458
5736
|
if (ncap > 0) {
|
|
5459
5737
|
if (this.prog.numLb === 0 && input.endPos() <= Backtracker.maxBitStateLen(this.prog)) return Backtracker.execute(this, input, pos, anchor, ncap);
|
|
5460
|
-
return this.doExecuteNFA(input, pos, anchor, ncap);
|
|
5738
|
+
return this.doExecuteNFA(input, pos, anchor, ncap, lbState);
|
|
5461
5739
|
}
|
|
5462
5740
|
if (this.prog.numLb === 0) {
|
|
5463
5741
|
const dfaResult = this.dfa.match(input, pos, anchor);
|
|
5464
5742
|
if (dfaResult !== null) return dfaResult ? [] : null;
|
|
5465
5743
|
if (input.endPos() <= Backtracker.maxBitStateLen(this.prog)) return Backtracker.execute(this, input, pos, anchor, ncap);
|
|
5466
5744
|
}
|
|
5467
|
-
return this.doExecuteNFA(input, pos, anchor, ncap);
|
|
5745
|
+
return this.doExecuteNFA(input, pos, anchor, ncap, lbState);
|
|
5468
5746
|
}
|
|
5469
5747
|
/**
|
|
5470
5748
|
* Returns the number of parenthesized subexpressions in this regular expression.
|
|
@@ -5490,11 +5768,11 @@
|
|
|
5490
5768
|
toString() {
|
|
5491
5769
|
return this.expr;
|
|
5492
5770
|
}
|
|
5493
|
-
doExecuteNFA(input, pos, anchor, ncap) {
|
|
5771
|
+
doExecuteNFA(input, pos, anchor, ncap, lbState = null) {
|
|
5494
5772
|
let m = this.get();
|
|
5495
5773
|
if (!m) m = Machine.fromRE2(this);
|
|
5496
5774
|
m.init(ncap);
|
|
5497
|
-
const cap = m.match(input, pos, anchor) ? m.submatches() : null;
|
|
5775
|
+
const cap = m.match(input, pos, anchor, lbState) ? m.submatches() : null;
|
|
5498
5776
|
this.put(m);
|
|
5499
5777
|
return cap;
|
|
5500
5778
|
}
|
|
@@ -5513,17 +5791,21 @@
|
|
|
5513
5791
|
* @param anchor the anchoring flag (UNANCHORED, ANCHOR_START, ANCHOR_BOTH)
|
|
5514
5792
|
* @param group the array to fill with submatch positions
|
|
5515
5793
|
* @param ngroup the number of array pairs to fill in
|
|
5794
|
+
* @param lbState optional state carried between successive matches over the same input (see
|
|
5795
|
+
* createLookbehindState); omit it to evaluate lookbehinds from the beginning of the input
|
|
5516
5796
|
* @returns true if a match was found
|
|
5517
5797
|
*/
|
|
5518
|
-
matchWithGroup(input, start, end, anchor, ngroup) {
|
|
5519
|
-
if (!(input instanceof MatcherInputBase))
|
|
5520
|
-
|
|
5521
|
-
|
|
5798
|
+
matchWithGroup(input, start, end, anchor, ngroup, lbState = null) {
|
|
5799
|
+
if (!(input instanceof MatcherInputBase)) {
|
|
5800
|
+
if (Utils.isByteArray(input)) input = MatcherInput.utf8(input);
|
|
5801
|
+
else input = MatcherInput.utf16(input);
|
|
5802
|
+
}
|
|
5803
|
+
return this.matchMachineInput(input, start, end, anchor, ngroup, lbState);
|
|
5522
5804
|
}
|
|
5523
|
-
matchMachineInput(input, start, end, anchor, ngroup) {
|
|
5805
|
+
matchMachineInput(input, start, end, anchor, ngroup, lbState = null) {
|
|
5524
5806
|
if (start > end) return [false, null];
|
|
5525
5807
|
const machineInput = input.isUTF16Encoding() ? MachineInput.fromUTF16(input.asCharSequence(), 0, end) : MachineInput.fromUTF8(input.asBytes(), 0, end);
|
|
5526
|
-
const groupMatch = this.executeEngine(machineInput, start, anchor, 2 * ngroup);
|
|
5808
|
+
const groupMatch = this.executeEngine(machineInput, start, anchor, 2 * ngroup, lbState);
|
|
5527
5809
|
if (groupMatch === null) return [false, null];
|
|
5528
5810
|
return [true, groupMatch];
|
|
5529
5811
|
}
|
|
@@ -5560,9 +5842,10 @@
|
|
|
5560
5842
|
let searchPos = 0;
|
|
5561
5843
|
let out = "";
|
|
5562
5844
|
const input = MachineInput.fromUTF16(src);
|
|
5845
|
+
const lbState = this.createLookbehindState();
|
|
5563
5846
|
let numReplaces = 0;
|
|
5564
5847
|
while (searchPos <= src.length) {
|
|
5565
|
-
const a = this.executeEngine(input, searchPos, RE2Flags.UNANCHORED, 2);
|
|
5848
|
+
const a = this.executeEngine(input, searchPos, RE2Flags.UNANCHORED, 2, lbState);
|
|
5566
5849
|
if (a === null || a.length === 0) break;
|
|
5567
5850
|
out += src.substring(lastMatchEnd, a[0]);
|
|
5568
5851
|
if (a[1] > lastMatchEnd || a[0] === 0) {
|
|
@@ -5596,8 +5879,9 @@
|
|
|
5596
5879
|
let pos = 0;
|
|
5597
5880
|
let i = 0;
|
|
5598
5881
|
let prevMatchEnd = -1;
|
|
5882
|
+
const lbState = this.createLookbehindState();
|
|
5599
5883
|
while (i < n && pos <= end) {
|
|
5600
|
-
const matches = this.executeEngine(input, pos, RE2Flags.UNANCHORED, this.prog.numCap);
|
|
5884
|
+
const matches = this.executeEngine(input, pos, RE2Flags.UNANCHORED, this.prog.numCap, lbState);
|
|
5601
5885
|
if (matches === null || matches.length === 0) break;
|
|
5602
5886
|
let accept = true;
|
|
5603
5887
|
if (matches[1] === pos) {
|
|
@@ -5867,7 +6151,9 @@
|
|
|
5867
6151
|
*/
|
|
5868
6152
|
compile() {
|
|
5869
6153
|
if (this.prog) return;
|
|
5870
|
-
|
|
6154
|
+
const prog = Compiler.compileSet(this.regexps);
|
|
6155
|
+
if (prog.numInst() > Parser.MAX_SIZE) throw new RE2JSCompileException(`${Parser.ERR_LARGE}: the set compiles to ${prog.numInst()} instructions, more than ${Parser.MAX_SIZE}`);
|
|
6156
|
+
this.prog = prog;
|
|
5871
6157
|
this.dfa = new DFA(this.prog, this.maxMem);
|
|
5872
6158
|
this.dummyRe2 = {
|
|
5873
6159
|
prog: this.prog,
|