re2js 2.8.4 → 2.8.6
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 +31 -0
- package/build/index.cjs +127 -178
- package/build/index.d.cts +16 -13
- package/build/index.d.ts +16 -13
- package/build/index.js +127 -178
- package/build/index.umd.js +127 -178
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -228,6 +228,37 @@ matchString.group() // 'e'
|
|
|
228
228
|
matchString.find(7) // false
|
|
229
229
|
```
|
|
230
230
|
|
|
231
|
+
### Executing a Search (`exec`)
|
|
232
|
+
|
|
233
|
+
If you want a native, 1:1 drop-in replacement for JavaScript's `RegExp.prototype.exec()`, you can use the `.exec()` method.
|
|
234
|
+
|
|
235
|
+
Instead of dealing with a stateful `Matcher` object, `exec()` performs a single search and returns a standard `RegExpExecArray`-shaped result, or `null` if no match is found. It includes the `.index`, `.input`, and `.groups` properties, and accurately maps unmatched optional capture groups to `undefined` (just like native JavaScript).
|
|
236
|
+
|
|
237
|
+
```js
|
|
238
|
+
import { RE2JS } from 're2js'
|
|
239
|
+
|
|
240
|
+
const re = RE2JS.compile('(?P<first>\\w+) (?:(?P<middle>\\w+) )?(?P<last>\\w+)');
|
|
241
|
+
const result = re.exec('John Doe');
|
|
242
|
+
|
|
243
|
+
if (result !== null) {
|
|
244
|
+
console.log(result[0]); // "John Doe" (Full match)
|
|
245
|
+
console.log(result[1]); // "John" (Group 1)
|
|
246
|
+
console.log(result[2]); // undefined (Group 2 didn't match)
|
|
247
|
+
console.log(result[3]); // "Doe" (Group 3)
|
|
248
|
+
|
|
249
|
+
console.log(result.index); // 0
|
|
250
|
+
console.log(result.input); // "John Doe"
|
|
251
|
+
|
|
252
|
+
// Named groups dictionary
|
|
253
|
+
console.log(result.groups.first); // "John"
|
|
254
|
+
console.log(result.groups.middle); // undefined
|
|
255
|
+
console.log(result.groups.last); // "Doe"
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
***Performance Note:** If you are running `exec()` inside a `while` loop to manually extract multiple matches globally, it is highly recommended to use `.matchAll()` instead, as it is cleaner, strictly stateless, and avoids infinite loop pitfalls.*
|
|
261
|
+
|
|
231
262
|
### Iterating Over Matches (`matchAll`)
|
|
232
263
|
|
|
233
264
|
For a more modern, JavaScript-native developer experience, RE2JS provides a `.matchAll()` method. This returns an ES6 `IterableIterator`, allowing you to safely and cleanly iterate over matches using `for...of` loops or the array spread operator `[...]`.
|
package/build/index.cjs
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
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.6
|
|
6
6
|
* @author Oleksii Vasyliev
|
|
7
7
|
* @homepage https://github.com/le0pard/re2js#readme
|
|
8
8
|
* @repository github:le0pard/re2js
|
|
@@ -708,7 +708,7 @@ var Utils = class Utils {
|
|
|
708
708
|
static stringToUtf8ByteArray(str) {
|
|
709
709
|
if (globalThis.TextEncoder) {
|
|
710
710
|
if (!cachedNativeEncoder) cachedNativeEncoder = new TextEncoder();
|
|
711
|
-
return
|
|
711
|
+
return cachedNativeEncoder.encode(str);
|
|
712
712
|
} else {
|
|
713
713
|
let out = [], p = 0;
|
|
714
714
|
for (let i = 0; i < str.length; i++) {
|
|
@@ -1246,7 +1246,7 @@ var Matcher = class Matcher {
|
|
|
1246
1246
|
}
|
|
1247
1247
|
/**
|
|
1248
1248
|
* Resets the {@code Matcher} and changes the input.
|
|
1249
|
-
* @param {MatcherInputBase} input
|
|
1249
|
+
* @param {string|number[]|Uint8Array|MatcherInputBase} input
|
|
1250
1250
|
* @returns {Matcher} the {@code Matcher} itself, for chained method calls
|
|
1251
1251
|
*/
|
|
1252
1252
|
resetMatcherInput(input) {
|
|
@@ -1402,7 +1402,10 @@ var Matcher = class Matcher {
|
|
|
1402
1402
|
*/
|
|
1403
1403
|
genMatch(startByte, anchor) {
|
|
1404
1404
|
const res = this.patternInput.re2().matchMachineInput(this.matcherInput, startByte, this.matcherInputLength, anchor, 1);
|
|
1405
|
-
if (!res[0])
|
|
1405
|
+
if (!res[0]) {
|
|
1406
|
+
this.hasMatch = false;
|
|
1407
|
+
return false;
|
|
1408
|
+
}
|
|
1406
1409
|
this.groups = res[1];
|
|
1407
1410
|
this.hasMatch = true;
|
|
1408
1411
|
this.hasGroups = this.patternGroupCount === 0;
|
|
@@ -1465,43 +1468,47 @@ var Matcher = class Matcher {
|
|
|
1465
1468
|
let res = "";
|
|
1466
1469
|
let last = 0;
|
|
1467
1470
|
const m = replacement.length;
|
|
1468
|
-
|
|
1469
|
-
|
|
1471
|
+
let i = 0;
|
|
1472
|
+
while (i < m) {
|
|
1473
|
+
const cCode = replacement.codePointAt(i);
|
|
1474
|
+
if (cCode === Codepoint.CODES.get("\\")) {
|
|
1470
1475
|
if (last < i) res += replacement.substring(last, i);
|
|
1471
1476
|
i++;
|
|
1477
|
+
if (i >= m) throw new RE2JSGroupException("character to be escaped is missing");
|
|
1472
1478
|
last = i;
|
|
1479
|
+
i++;
|
|
1473
1480
|
continue;
|
|
1474
1481
|
}
|
|
1475
|
-
if (
|
|
1476
|
-
|
|
1477
|
-
if (
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1482
|
+
if (cCode === Codepoint.CODES.get("$")) {
|
|
1483
|
+
if (last < i) res += replacement.substring(last, i);
|
|
1484
|
+
if (i + 1 >= m) throw new RE2JSGroupException("Illegal group reference: group index is missing");
|
|
1485
|
+
const nextCode = replacement.codePointAt(i + 1);
|
|
1486
|
+
if (Codepoint.CODES.get("0") <= nextCode && nextCode <= Codepoint.CODES.get("9")) {
|
|
1487
|
+
let n = nextCode - Codepoint.CODES.get("0");
|
|
1488
|
+
let j = i + 2;
|
|
1489
|
+
for (; j < m; j++) {
|
|
1490
|
+
const digit = replacement.codePointAt(j);
|
|
1491
|
+
if (digit < Codepoint.CODES.get("0") || digit > Codepoint.CODES.get("9") || n * 10 + digit - Codepoint.CODES.get("0") > this.patternGroupCount) break;
|
|
1492
|
+
n = n * 10 + digit - Codepoint.CODES.get("0");
|
|
1484
1493
|
}
|
|
1485
1494
|
if (n > this.patternGroupCount) throw new RE2JSGroupException(`n > number of groups: ${n}`);
|
|
1486
1495
|
const group = this.group(n);
|
|
1487
1496
|
if (group !== null) res += group;
|
|
1497
|
+
i = j;
|
|
1488
1498
|
last = i;
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
if (
|
|
1493
|
-
i
|
|
1494
|
-
let j = i + 1;
|
|
1495
|
-
while (j < replacement.length && replacement.codePointAt(j) !== Codepoint.CODES.get("}") && replacement.codePointAt(j) !== Codepoint.CODES.get(" ")) j++;
|
|
1496
|
-
if (j === replacement.length || replacement.codePointAt(j) !== Codepoint.CODES.get("}")) throw new RE2JSGroupException("named capture group is missing trailing '}'");
|
|
1497
|
-
const groupName = replacement.substring(i + 1, j);
|
|
1499
|
+
} else if (nextCode === Codepoint.CODES.get("{")) {
|
|
1500
|
+
let j = i + 2;
|
|
1501
|
+
while (j < m && replacement.codePointAt(j) !== Codepoint.CODES.get("}")) j++;
|
|
1502
|
+
if (j >= m) throw new RE2JSGroupException("named capture group is missing trailing '}'");
|
|
1503
|
+
const groupName = replacement.substring(i + 2, j);
|
|
1498
1504
|
const groupVal = this.group(groupName);
|
|
1499
1505
|
if (groupVal !== null) res += groupVal;
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1506
|
+
i = j + 1;
|
|
1507
|
+
last = i;
|
|
1508
|
+
} else throw new RE2JSGroupException("Illegal group reference");
|
|
1509
|
+
continue;
|
|
1504
1510
|
}
|
|
1511
|
+
i++;
|
|
1505
1512
|
}
|
|
1506
1513
|
if (last < m) res += replacement.substring(last, m);
|
|
1507
1514
|
return res;
|
|
@@ -1812,18 +1819,18 @@ var Inst = class Inst {
|
|
|
1812
1819
|
};
|
|
1813
1820
|
//#endregion
|
|
1814
1821
|
//#region src/Machine.js
|
|
1815
|
-
var Thread = class {
|
|
1816
|
-
constructor() {
|
|
1817
|
-
this.inst = null;
|
|
1818
|
-
this.cap = null;
|
|
1819
|
-
}
|
|
1820
|
-
};
|
|
1821
1822
|
var Queue = class {
|
|
1822
1823
|
constructor(numInst) {
|
|
1823
1824
|
this.sparse = new Int32Array(numInst);
|
|
1824
1825
|
this.densePcs = new Int32Array(numInst);
|
|
1825
|
-
this.
|
|
1826
|
+
this.denseCaps = null;
|
|
1826
1827
|
this.size = 0;
|
|
1828
|
+
this.ncap = 0;
|
|
1829
|
+
}
|
|
1830
|
+
init(ncap) {
|
|
1831
|
+
this.ncap = ncap;
|
|
1832
|
+
const needed = this.densePcs.length * ncap;
|
|
1833
|
+
if (!this.denseCaps || this.denseCaps.length < needed) this.denseCaps = new Int32Array(needed);
|
|
1827
1834
|
}
|
|
1828
1835
|
contains(pc) {
|
|
1829
1836
|
const j = this.sparse[pc];
|
|
@@ -1835,12 +1842,10 @@ var Queue = class {
|
|
|
1835
1842
|
add(pc) {
|
|
1836
1843
|
const j = this.size++;
|
|
1837
1844
|
this.sparse[pc] = j;
|
|
1838
|
-
this.denseThreads[j] = null;
|
|
1839
1845
|
this.densePcs[j] = pc;
|
|
1840
1846
|
return j;
|
|
1841
1847
|
}
|
|
1842
1848
|
clear() {
|
|
1843
|
-
for (let i = 0; i < this.size; i++) this.denseThreads[i] = null;
|
|
1844
1849
|
this.size = 0;
|
|
1845
1850
|
}
|
|
1846
1851
|
toString() {
|
|
@@ -1854,15 +1859,12 @@ var Queue = class {
|
|
|
1854
1859
|
}
|
|
1855
1860
|
};
|
|
1856
1861
|
var Machine = class Machine {
|
|
1857
|
-
static THREADS_CHUNK_SIZE = 128;
|
|
1858
1862
|
static fromRE2(re2) {
|
|
1859
1863
|
const m = new Machine();
|
|
1860
1864
|
m.prog = re2.prog;
|
|
1861
1865
|
m.re2 = re2;
|
|
1862
1866
|
m.q0 = new Queue(m.prog.numInst());
|
|
1863
1867
|
m.q1 = new Queue(m.prog.numInst());
|
|
1864
|
-
m.pool = [];
|
|
1865
|
-
m.poolSize = 0;
|
|
1866
1868
|
m.matched = false;
|
|
1867
1869
|
m.matchcap = new Int32Array(m.prog.numCap < 2 ? 2 : m.prog.numCap);
|
|
1868
1870
|
m.ncap = 0;
|
|
@@ -1876,8 +1878,6 @@ var Machine = class Machine {
|
|
|
1876
1878
|
this.re2 = null;
|
|
1877
1879
|
this.q0 = null;
|
|
1878
1880
|
this.q1 = null;
|
|
1879
|
-
this.pool = [];
|
|
1880
|
-
this.poolSize = 0;
|
|
1881
1881
|
this.matched = false;
|
|
1882
1882
|
this.matchcap = null;
|
|
1883
1883
|
this.ncap = 0;
|
|
@@ -1885,51 +1885,19 @@ var Machine = class Machine {
|
|
|
1885
1885
|
}
|
|
1886
1886
|
init(ncap) {
|
|
1887
1887
|
this.ncap = ncap;
|
|
1888
|
-
if (ncap > this.matchcap.length) this.
|
|
1889
|
-
else this.
|
|
1888
|
+
if (ncap > this.matchcap.length) this.matchcap = new Int32Array(ncap).fill(-1);
|
|
1889
|
+
else this.matchcap.fill(-1);
|
|
1890
|
+
this.q0.init(ncap);
|
|
1891
|
+
this.q1.init(ncap);
|
|
1890
1892
|
if (this.prog.numLb > 0) {
|
|
1891
1893
|
if (!this.lbTable || this.lbTable.length < this.prog.numLb + 1) this.lbTable = new Int32Array(this.prog.numLb + 1);
|
|
1892
1894
|
this.lbTable.fill(-1);
|
|
1893
1895
|
}
|
|
1894
1896
|
}
|
|
1895
|
-
resetCap() {
|
|
1896
|
-
for (let i = 0; i < this.poolSize; i++) this.pool[i].cap.fill(-1);
|
|
1897
|
-
}
|
|
1898
|
-
initNewCap(ncap) {
|
|
1899
|
-
for (let i = 0; i < this.poolSize; i++) {
|
|
1900
|
-
const t = this.pool[i];
|
|
1901
|
-
t.cap = new Int32Array(ncap).fill(-1);
|
|
1902
|
-
}
|
|
1903
|
-
this.matchcap = new Int32Array(ncap).fill(-1);
|
|
1904
|
-
}
|
|
1905
1897
|
submatches() {
|
|
1906
1898
|
if (this.ncap === 0) return Utils.emptyInts();
|
|
1907
1899
|
return Utils.toArray(this.matchcap.subarray(0, this.ncap));
|
|
1908
1900
|
}
|
|
1909
|
-
alloc(inst) {
|
|
1910
|
-
if (this.poolSize === 0) {
|
|
1911
|
-
const capLen = this.matchcap.length;
|
|
1912
|
-
for (let i = 0; i < Machine.THREADS_CHUNK_SIZE; i++) {
|
|
1913
|
-
const t = new Thread();
|
|
1914
|
-
t.cap = new Int32Array(capLen);
|
|
1915
|
-
this.pool[this.poolSize++] = t;
|
|
1916
|
-
}
|
|
1917
|
-
}
|
|
1918
|
-
this.poolSize--;
|
|
1919
|
-
const t = this.pool[this.poolSize];
|
|
1920
|
-
t.inst = inst;
|
|
1921
|
-
return t;
|
|
1922
|
-
}
|
|
1923
|
-
freeQueue(queue, from = 0) {
|
|
1924
|
-
for (let i = from; i < queue.size; i++) {
|
|
1925
|
-
const t = queue.denseThreads[i];
|
|
1926
|
-
if (t !== null) this.pool[this.poolSize++] = t;
|
|
1927
|
-
}
|
|
1928
|
-
queue.clear();
|
|
1929
|
-
}
|
|
1930
|
-
freeThread(t) {
|
|
1931
|
-
this.pool[this.poolSize++] = t;
|
|
1932
|
-
}
|
|
1933
1901
|
match(input, pos, anchor) {
|
|
1934
1902
|
const startCond = this.re2.cond;
|
|
1935
1903
|
if (startCond === Utils.EMPTY_ALL) return false;
|
|
@@ -1968,13 +1936,14 @@ var Machine = class Machine {
|
|
|
1968
1936
|
r = input.step(currentPos + width);
|
|
1969
1937
|
rune1 = r >> 3;
|
|
1970
1938
|
width1 = r & 7;
|
|
1939
|
+
flag = input.context(currentPos);
|
|
1971
1940
|
}
|
|
1972
1941
|
}
|
|
1973
|
-
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,
|
|
1942
|
+
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);
|
|
1974
1943
|
if (!this.matched && (currentPos === 0 || anchor === RE2Flags.UNANCHORED)) {
|
|
1975
1944
|
if (currentPos >= matchStartPos) {
|
|
1976
1945
|
if (this.ncap > 0) this.matchcap[0] = currentPos;
|
|
1977
|
-
this.add(runq, this.prog.start, currentPos, this.matchcap,
|
|
1946
|
+
this.add(runq, this.prog.start, currentPos, this.matchcap, 0, flag);
|
|
1978
1947
|
}
|
|
1979
1948
|
}
|
|
1980
1949
|
const nextPos = currentPos + width;
|
|
@@ -1994,7 +1963,7 @@ var Machine = class Machine {
|
|
|
1994
1963
|
runq = nextq;
|
|
1995
1964
|
nextq = tmpq;
|
|
1996
1965
|
}
|
|
1997
|
-
|
|
1966
|
+
nextq.clear();
|
|
1998
1967
|
return this.matched;
|
|
1999
1968
|
}
|
|
2000
1969
|
matchSet(input, pos, anchor) {
|
|
@@ -2022,16 +1991,16 @@ var Machine = class Machine {
|
|
|
2022
1991
|
if ((startCond & Utils.EMPTY_BEGIN_TEXT) !== 0 && currentPos !== 0) break;
|
|
2023
1992
|
if ((anchor === RE2Flags.ANCHOR_START || anchor === RE2Flags.ANCHOR_BOTH) && currentPos !== 0) break;
|
|
2024
1993
|
}
|
|
2025
|
-
if (currentPos === 0 && this.prog.numLb > 0) for (let i = 0; i < this.prog.lbStarts.length; i++) this.add(runq, this.prog.lbStarts[i], currentPos, this.matchcap,
|
|
1994
|
+
if (currentPos === 0 && this.prog.numLb > 0) for (let i = 0; i < this.prog.lbStarts.length; i++) this.add(runq, this.prog.lbStarts[i], currentPos, this.matchcap, 0, flag);
|
|
2026
1995
|
if (currentPos === 0 || anchor === RE2Flags.UNANCHORED) {
|
|
2027
|
-
if (currentPos >= matchStartPos) this.add(runq, this.prog.start, currentPos, this.matchcap,
|
|
1996
|
+
if (currentPos >= matchStartPos) this.add(runq, this.prog.start, currentPos, this.matchcap, 0, flag);
|
|
2028
1997
|
}
|
|
2029
1998
|
const nextPos = currentPos + width;
|
|
2030
1999
|
flag = input.context(nextPos);
|
|
2031
2000
|
for (let j = 0; j < runq.size; j++) {
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
const
|
|
2001
|
+
const pc = runq.densePcs[j];
|
|
2002
|
+
const i = this.prog.inst[pc];
|
|
2003
|
+
const capOffset = j * this.ncap;
|
|
2035
2004
|
let add = false;
|
|
2036
2005
|
switch (i.op) {
|
|
2037
2006
|
case Inst.MATCH:
|
|
@@ -2048,15 +2017,11 @@ var Machine = class Machine {
|
|
|
2048
2017
|
add = true;
|
|
2049
2018
|
break;
|
|
2050
2019
|
case Inst.RUNE_ANY_NOT_NL:
|
|
2051
|
-
add = rune !==
|
|
2020
|
+
add = rune !== 10;
|
|
2052
2021
|
break;
|
|
2053
|
-
default:
|
|
2054
|
-
}
|
|
2055
|
-
if (add) t = this.add(nextq, i.out, nextPos, t.cap, flag, t);
|
|
2056
|
-
if (t !== null) {
|
|
2057
|
-
this.freeThread(t);
|
|
2058
|
-
runq.denseThreads[j] = null;
|
|
2022
|
+
default: continue;
|
|
2059
2023
|
}
|
|
2024
|
+
if (add) this.add(nextq, i.out, nextPos, runq.denseCaps, capOffset, flag);
|
|
2060
2025
|
}
|
|
2061
2026
|
runq.clear();
|
|
2062
2027
|
if (width === 0) break;
|
|
@@ -2072,28 +2037,25 @@ var Machine = class Machine {
|
|
|
2072
2037
|
runq = nextq;
|
|
2073
2038
|
nextq = tmpq;
|
|
2074
2039
|
}
|
|
2075
|
-
|
|
2040
|
+
nextq.clear();
|
|
2076
2041
|
return Array.from(matches).sort((a, b) => a - b);
|
|
2077
2042
|
}
|
|
2078
2043
|
step(runq, nextq, pos, nextPos, c, nextCond, anchor, atEnd) {
|
|
2079
2044
|
const longest = this.re2.longest;
|
|
2080
2045
|
for (let j = 0; j < runq.size; j++) {
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
if (longest && this.matched && this.ncap > 0 && this.matchcap[0] <
|
|
2084
|
-
|
|
2085
|
-
continue;
|
|
2086
|
-
}
|
|
2087
|
-
const i = t.inst;
|
|
2046
|
+
const pc = runq.densePcs[j];
|
|
2047
|
+
const capOffset = j * this.ncap;
|
|
2048
|
+
if (longest && this.matched && this.ncap > 0 && this.matchcap[0] < runq.denseCaps[capOffset]) continue;
|
|
2049
|
+
const i = this.prog.inst[pc];
|
|
2088
2050
|
let add = false;
|
|
2089
2051
|
switch (i.op) {
|
|
2090
2052
|
case Inst.MATCH:
|
|
2091
2053
|
if (anchor === RE2Flags.ANCHOR_BOTH && !atEnd) break;
|
|
2092
2054
|
if (this.ncap > 0 && (!longest || !this.matched || this.matchcap[1] < pos)) {
|
|
2093
|
-
|
|
2094
|
-
|
|
2055
|
+
runq.denseCaps[capOffset + 1] = pos;
|
|
2056
|
+
for (let k = 0; k < this.ncap; k++) this.matchcap[k] = runq.denseCaps[capOffset + k];
|
|
2095
2057
|
}
|
|
2096
|
-
if (!longest)
|
|
2058
|
+
if (!longest) runq.size = 0;
|
|
2097
2059
|
this.matched = true;
|
|
2098
2060
|
break;
|
|
2099
2061
|
case Inst.RUNE:
|
|
@@ -2106,29 +2068,25 @@ var Machine = class Machine {
|
|
|
2106
2068
|
add = true;
|
|
2107
2069
|
break;
|
|
2108
2070
|
case Inst.RUNE_ANY_NOT_NL:
|
|
2109
|
-
add = c !==
|
|
2071
|
+
add = c !== 10;
|
|
2110
2072
|
break;
|
|
2111
|
-
default:
|
|
2112
|
-
}
|
|
2113
|
-
if (add) t = this.add(nextq, i.out, nextPos, t.cap, nextCond, t);
|
|
2114
|
-
if (t !== null) {
|
|
2115
|
-
this.freeThread(t);
|
|
2116
|
-
runq.denseThreads[j] = null;
|
|
2073
|
+
default: continue;
|
|
2117
2074
|
}
|
|
2075
|
+
if (add) this.add(nextq, i.out, nextPos, runq.denseCaps, capOffset, nextCond);
|
|
2118
2076
|
}
|
|
2119
2077
|
runq.clear();
|
|
2120
2078
|
}
|
|
2121
|
-
add(q, pc, pos,
|
|
2079
|
+
add(q, pc, pos, capArray, capOffset, cond) {
|
|
2122
2080
|
while (true) {
|
|
2123
|
-
if (pc === 0) return
|
|
2124
|
-
if (q.contains(pc)) return
|
|
2081
|
+
if (pc === 0) return;
|
|
2082
|
+
if (q.contains(pc)) return;
|
|
2125
2083
|
const d = q.add(pc);
|
|
2126
2084
|
const inst = this.prog.inst[pc];
|
|
2127
2085
|
switch (inst.op) {
|
|
2128
|
-
case Inst.FAIL: return
|
|
2086
|
+
case Inst.FAIL: return;
|
|
2129
2087
|
case Inst.ALT:
|
|
2130
2088
|
case Inst.ALT_MATCH:
|
|
2131
|
-
|
|
2089
|
+
this.add(q, inst.out, pos, capArray, capOffset, cond);
|
|
2132
2090
|
pc = inst.arg;
|
|
2133
2091
|
continue;
|
|
2134
2092
|
case Inst.EMPTY_WIDTH:
|
|
@@ -2136,16 +2094,16 @@ var Machine = class Machine {
|
|
|
2136
2094
|
pc = inst.out;
|
|
2137
2095
|
continue;
|
|
2138
2096
|
}
|
|
2139
|
-
return
|
|
2097
|
+
return;
|
|
2140
2098
|
case Inst.NOP:
|
|
2141
2099
|
pc = inst.out;
|
|
2142
2100
|
continue;
|
|
2143
2101
|
case Inst.CAPTURE: if (inst.arg < this.ncap) {
|
|
2144
|
-
const opos =
|
|
2145
|
-
|
|
2146
|
-
this.add(q, inst.out, pos,
|
|
2147
|
-
|
|
2148
|
-
return
|
|
2102
|
+
const opos = capArray[capOffset + inst.arg];
|
|
2103
|
+
capArray[capOffset + inst.arg] = pos;
|
|
2104
|
+
this.add(q, inst.out, pos, capArray, capOffset, cond);
|
|
2105
|
+
capArray[capOffset + inst.arg] = opos;
|
|
2106
|
+
return;
|
|
2149
2107
|
} else {
|
|
2150
2108
|
pc = inst.out;
|
|
2151
2109
|
continue;
|
|
@@ -2164,19 +2122,18 @@ var Machine = class Machine {
|
|
|
2164
2122
|
pc = inst.out;
|
|
2165
2123
|
continue;
|
|
2166
2124
|
}
|
|
2167
|
-
return
|
|
2125
|
+
return;
|
|
2168
2126
|
case Inst.MATCH:
|
|
2169
2127
|
case Inst.RUNE:
|
|
2170
2128
|
case Inst.RUNE1:
|
|
2171
2129
|
case Inst.RUNE_ANY:
|
|
2172
2130
|
case Inst.RUNE_ANY_NOT_NL:
|
|
2173
|
-
if (
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
default: throw new Error("unhandled");
|
|
2131
|
+
if (this.ncap > 0) {
|
|
2132
|
+
const destOffset = d * this.ncap;
|
|
2133
|
+
for (let c = 0; c < this.ncap; c++) q.denseCaps[destOffset + c] = capArray[capOffset + c];
|
|
2134
|
+
}
|
|
2135
|
+
return;
|
|
2136
|
+
default: throw new RE2JSInternalException("unhandled");
|
|
2180
2137
|
}
|
|
2181
2138
|
}
|
|
2182
2139
|
}
|
|
@@ -2773,7 +2730,9 @@ const makeOnePass = (p) => {
|
|
|
2773
2730
|
m[pc] = true;
|
|
2774
2731
|
inst.op = Inst.ALT_MATCH;
|
|
2775
2732
|
}
|
|
2776
|
-
const
|
|
2733
|
+
const leftRunes = onePassRunes[inst.out] || [];
|
|
2734
|
+
const rightRunes = onePassRunes[inst.arg] || [];
|
|
2735
|
+
const mergeRes = mergeRuneSets(leftRunes, rightRunes, inst.out, inst.arg);
|
|
2777
2736
|
if (!mergeRes) return false;
|
|
2778
2737
|
onePassRunes[pc] = mergeRes.merged;
|
|
2779
2738
|
inst.next = new Uint32Array(mergeRes.next);
|
|
@@ -5365,24 +5324,6 @@ var Parser = class Parser {
|
|
|
5365
5324
|
};
|
|
5366
5325
|
//#endregion
|
|
5367
5326
|
//#region src/RE2.js
|
|
5368
|
-
var AtomicReference = class {
|
|
5369
|
-
constructor(initialValue) {
|
|
5370
|
-
this.value = initialValue;
|
|
5371
|
-
}
|
|
5372
|
-
get() {
|
|
5373
|
-
return this.value;
|
|
5374
|
-
}
|
|
5375
|
-
set(newValue) {
|
|
5376
|
-
this.value = newValue;
|
|
5377
|
-
}
|
|
5378
|
-
compareAndSet(expect, update) {
|
|
5379
|
-
if (this.value === expect) {
|
|
5380
|
-
this.value = update;
|
|
5381
|
-
return true;
|
|
5382
|
-
}
|
|
5383
|
-
return false;
|
|
5384
|
-
}
|
|
5385
|
-
};
|
|
5386
5327
|
/**
|
|
5387
5328
|
* An RE2 class instance is a compiled representation of an RE2 regular expression, independent of
|
|
5388
5329
|
* the public Java-like Pattern/Matcher API.
|
|
@@ -5471,7 +5412,7 @@ var RE2 = class RE2 {
|
|
|
5471
5412
|
this.prefixUTF8 = null;
|
|
5472
5413
|
this.prefixComplete = false;
|
|
5473
5414
|
this.prefixRune = 0;
|
|
5474
|
-
this.
|
|
5415
|
+
this.machinePool = [];
|
|
5475
5416
|
this.dfa = new DFA(this.prog);
|
|
5476
5417
|
this.onepass = OnePass.compile(this.prog);
|
|
5477
5418
|
this.prefilter = null;
|
|
@@ -5535,42 +5476,23 @@ var RE2 = class RE2 {
|
|
|
5535
5476
|
return this.prog.numInst();
|
|
5536
5477
|
}
|
|
5537
5478
|
get() {
|
|
5538
|
-
|
|
5539
|
-
do
|
|
5540
|
-
head = this.pooled.get();
|
|
5541
|
-
while (head && !this.pooled.compareAndSet(head, head.next));
|
|
5542
|
-
return head;
|
|
5479
|
+
return this.machinePool.length > 0 ? this.machinePool.pop() : null;
|
|
5543
5480
|
}
|
|
5544
5481
|
reset() {
|
|
5545
|
-
this.
|
|
5546
|
-
}
|
|
5547
|
-
put(m
|
|
5548
|
-
|
|
5549
|
-
do {
|
|
5550
|
-
head = this.pooled.get();
|
|
5551
|
-
if (!isNew && head) {
|
|
5552
|
-
m = Machine.fromMachine(m);
|
|
5553
|
-
isNew = true;
|
|
5554
|
-
}
|
|
5555
|
-
if (m.next !== head) m.next = head;
|
|
5556
|
-
} while (!this.pooled.compareAndSet(head, m));
|
|
5482
|
+
this.machinePool.length = 0;
|
|
5483
|
+
}
|
|
5484
|
+
put(m) {
|
|
5485
|
+
this.machinePool.push(m);
|
|
5557
5486
|
}
|
|
5558
5487
|
toString() {
|
|
5559
5488
|
return this.expr;
|
|
5560
5489
|
}
|
|
5561
5490
|
doExecuteNFA(input, pos, anchor, ncap) {
|
|
5562
5491
|
let m = this.get();
|
|
5563
|
-
|
|
5564
|
-
if (!m) {
|
|
5565
|
-
m = Machine.fromRE2(this);
|
|
5566
|
-
isNew = true;
|
|
5567
|
-
} else if (m.next !== null) {
|
|
5568
|
-
m = Machine.fromMachine(m);
|
|
5569
|
-
isNew = true;
|
|
5570
|
-
}
|
|
5492
|
+
if (!m) m = Machine.fromRE2(this);
|
|
5571
5493
|
m.init(ncap);
|
|
5572
5494
|
const cap = m.match(input, pos, anchor) ? m.submatches() : null;
|
|
5573
|
-
this.put(m
|
|
5495
|
+
this.put(m);
|
|
5574
5496
|
return cap;
|
|
5575
5497
|
}
|
|
5576
5498
|
match(s) {
|
|
@@ -6366,6 +6288,33 @@ var RE2JS = class RE2JS {
|
|
|
6366
6288
|
return this.re2Input.executeEngine(machineInput, 0, RE2Flags.ANCHOR_BOTH, 0) !== null;
|
|
6367
6289
|
}
|
|
6368
6290
|
/**
|
|
6291
|
+
* Executes a search for a match in a specified string.
|
|
6292
|
+
* Returns a result array, or null if no match is found.
|
|
6293
|
+
* The returned array perfectly mirrors standard JavaScript `RegExpExecArray`,
|
|
6294
|
+
* including `.index`, `.input`, and `.groups` properties.
|
|
6295
|
+
*
|
|
6296
|
+
* @param {string|number[]|Uint8Array} input the input string or byte array
|
|
6297
|
+
* @returns {Array|null} the match array with index, input, and groups properties, or null
|
|
6298
|
+
*/
|
|
6299
|
+
exec(input) {
|
|
6300
|
+
const m = this.matcher(input);
|
|
6301
|
+
if (!m.find()) return null;
|
|
6302
|
+
const result = [m.group(0)];
|
|
6303
|
+
for (let i = 1; i <= m.groupCount(); i++) {
|
|
6304
|
+
const val = m.group(i);
|
|
6305
|
+
result.push(val === null ? void 0 : val);
|
|
6306
|
+
}
|
|
6307
|
+
result.index = m.start(0);
|
|
6308
|
+
result.input = input;
|
|
6309
|
+
const namedGroups = this.namedGroups();
|
|
6310
|
+
if (Object.keys(namedGroups).length > 0) {
|
|
6311
|
+
const parsedGroups = m.getNamedGroups();
|
|
6312
|
+
for (const key in parsedGroups) if (parsedGroups[key] === null) parsedGroups[key] = void 0;
|
|
6313
|
+
result.groups = parsedGroups;
|
|
6314
|
+
} else result.groups = void 0;
|
|
6315
|
+
return result;
|
|
6316
|
+
}
|
|
6317
|
+
/**
|
|
6369
6318
|
* Splits input around instances of the regular expression. It returns an array giving the strings
|
|
6370
6319
|
* that occur before, between, and after instances of the regular expression.
|
|
6371
6320
|
*
|
|
@@ -6409,7 +6358,7 @@ var RE2JS = class RE2JS {
|
|
|
6409
6358
|
}
|
|
6410
6359
|
result.push(m.substring(last, m.inputLength()));
|
|
6411
6360
|
}
|
|
6412
|
-
if (limit !== 0 || result.length === 0) result.push(m.substring(last, m.inputLength()));
|
|
6361
|
+
if (limit !== 0 || result.length === 0 && !(last === m.inputLength() && last > 0)) result.push(m.substring(last, m.inputLength()));
|
|
6413
6362
|
return result;
|
|
6414
6363
|
}
|
|
6415
6364
|
/**
|
|
@@ -6417,7 +6366,7 @@ var RE2JS = class RE2JS {
|
|
|
6417
6366
|
* including capturing groups.
|
|
6418
6367
|
*
|
|
6419
6368
|
* @param {string|number[]|Uint8Array} input the input string or byte array
|
|
6420
|
-
* @returns {IterableIterator<
|
|
6369
|
+
* @returns {IterableIterator<RegExpMatchArray>}
|
|
6421
6370
|
*/
|
|
6422
6371
|
*matchAll(input) {
|
|
6423
6372
|
const m = this.matcher(input);
|
package/build/index.d.cts
CHANGED
|
@@ -221,10 +221,10 @@ export class Matcher {
|
|
|
221
221
|
anchorFlag: number;
|
|
222
222
|
/**
|
|
223
223
|
* Resets the {@code Matcher} and changes the input.
|
|
224
|
-
* @param {MatcherInputBase} input
|
|
224
|
+
* @param {string|number[]|Uint8Array|MatcherInputBase} input
|
|
225
225
|
* @returns {Matcher} the {@code Matcher} itself, for chained method calls
|
|
226
226
|
*/
|
|
227
|
-
resetMatcherInput(input: MatcherInputBase): Matcher;
|
|
227
|
+
resetMatcherInput(input: string | number[] | Uint8Array | MatcherInputBase): Matcher;
|
|
228
228
|
matcherInput: MatcherInputBase;
|
|
229
229
|
/**
|
|
230
230
|
* Returns the start of the named group of the most recent match, or -1 if the group was not
|
|
@@ -503,7 +503,7 @@ declare class RE2 {
|
|
|
503
503
|
prefixUTF8: any;
|
|
504
504
|
prefixComplete: boolean;
|
|
505
505
|
prefixRune: number;
|
|
506
|
-
|
|
506
|
+
machinePool: any[];
|
|
507
507
|
dfa: DFA;
|
|
508
508
|
onepass: {
|
|
509
509
|
start: any;
|
|
@@ -523,7 +523,7 @@ declare class RE2 {
|
|
|
523
523
|
numberOfInstructions(): any;
|
|
524
524
|
get(): any;
|
|
525
525
|
reset(): void;
|
|
526
|
-
put(m: any
|
|
526
|
+
put(m: any): void;
|
|
527
527
|
toString(): any;
|
|
528
528
|
doExecuteNFA(input: any, pos: any, anchor: any, ncap: any): any;
|
|
529
529
|
match(s: any): boolean;
|
|
@@ -699,13 +699,6 @@ declare class RE2 {
|
|
|
699
699
|
*/
|
|
700
700
|
findAllSubmatchIndex(s: any, n: any): any[];
|
|
701
701
|
}
|
|
702
|
-
declare class AtomicReference {
|
|
703
|
-
constructor(initialValue: any);
|
|
704
|
-
value: any;
|
|
705
|
-
get(): any;
|
|
706
|
-
set(newValue: any): void;
|
|
707
|
-
compareAndSet(expect: any, update: any): boolean;
|
|
708
|
-
}
|
|
709
702
|
/**
|
|
710
703
|
* Creates an RE2JS regex directly from a template literal.
|
|
711
704
|
* @overload
|
|
@@ -873,6 +866,16 @@ export class RE2JS {
|
|
|
873
866
|
* @returns {boolean} `true` if the exact input string fully matches the pattern, `false` otherwise.
|
|
874
867
|
*/
|
|
875
868
|
testExact(input: string | number[] | Uint8Array): boolean;
|
|
869
|
+
/**
|
|
870
|
+
* Executes a search for a match in a specified string.
|
|
871
|
+
* Returns a result array, or null if no match is found.
|
|
872
|
+
* The returned array perfectly mirrors standard JavaScript `RegExpExecArray`,
|
|
873
|
+
* including `.index`, `.input`, and `.groups` properties.
|
|
874
|
+
*
|
|
875
|
+
* @param {string|number[]|Uint8Array} input the input string or byte array
|
|
876
|
+
* @returns {Array|null} the match array with index, input, and groups properties, or null
|
|
877
|
+
*/
|
|
878
|
+
exec(input: string | number[] | Uint8Array): any[] | null;
|
|
876
879
|
/**
|
|
877
880
|
* Splits input around instances of the regular expression. It returns an array giving the strings
|
|
878
881
|
* that occur before, between, and after instances of the regular expression.
|
|
@@ -892,9 +895,9 @@ export class RE2JS {
|
|
|
892
895
|
* including capturing groups.
|
|
893
896
|
*
|
|
894
897
|
* @param {string|number[]|Uint8Array} input the input string or byte array
|
|
895
|
-
* @returns {IterableIterator<
|
|
898
|
+
* @returns {IterableIterator<RegExpMatchArray>}
|
|
896
899
|
*/
|
|
897
|
-
matchAll(input: string | number[] | Uint8Array): IterableIterator<
|
|
900
|
+
matchAll(input: string | number[] | Uint8Array): IterableIterator<RegExpMatchArray>;
|
|
898
901
|
/**
|
|
899
902
|
*
|
|
900
903
|
* @returns {string}
|