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