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