eyeling 1.24.26 → 1.24.27
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/dist/browser/eyeling.browser.js +61 -1
- package/eyeling.js +61 -1
- package/lib/builtins.js +61 -1
- package/package.json +1 -1
- package/test/api.test.js +29 -0
|
@@ -844,6 +844,62 @@ function compileSwapRegex(pattern, extraFlags) {
|
|
|
844
844
|
}
|
|
845
845
|
}
|
|
846
846
|
|
|
847
|
+
function expandSwapRegexReplacement(template, captures) {
|
|
848
|
+
// SWAP/N3 examples use $1-style capture references, but tests also rely on
|
|
849
|
+
// Perl-ish escaping in replacement strings: \\$ means a literal dollar sign
|
|
850
|
+
// and \\ means a literal backslash. JavaScript's replacement strings do not
|
|
851
|
+
// interpret those escapes, so expand the replacement explicitly in a callback.
|
|
852
|
+
let out = '';
|
|
853
|
+
const text = String(template);
|
|
854
|
+
|
|
855
|
+
for (let i = 0; i < text.length; i++) {
|
|
856
|
+
const ch = text[i];
|
|
857
|
+
|
|
858
|
+
if (ch === '\\') {
|
|
859
|
+
if (i + 1 < text.length && (text[i + 1] === '$' || text[i + 1] === '\\')) {
|
|
860
|
+
out += text[++i];
|
|
861
|
+
} else {
|
|
862
|
+
out += ch;
|
|
863
|
+
}
|
|
864
|
+
continue;
|
|
865
|
+
}
|
|
866
|
+
|
|
867
|
+
if (ch === '$') {
|
|
868
|
+
if (i + 1 < text.length && text[i + 1] === '$') {
|
|
869
|
+
out += '$';
|
|
870
|
+
i++;
|
|
871
|
+
continue;
|
|
872
|
+
}
|
|
873
|
+
|
|
874
|
+
let j = i + 1;
|
|
875
|
+
while (j < text.length && /[0-9]/.test(text[j])) j++;
|
|
876
|
+
if (j > i + 1) {
|
|
877
|
+
const digits = text.slice(i + 1, j);
|
|
878
|
+
let chosen = null;
|
|
879
|
+
for (let k = digits.length; k > 0; k--) {
|
|
880
|
+
const n = Number(digits.slice(0, k));
|
|
881
|
+
if (n > 0 && n < captures.length) {
|
|
882
|
+
chosen = { n, len: k };
|
|
883
|
+
break;
|
|
884
|
+
}
|
|
885
|
+
}
|
|
886
|
+
if (chosen) {
|
|
887
|
+
out += captures[chosen.n] == null ? '' : String(captures[chosen.n]);
|
|
888
|
+
out += digits.slice(chosen.len);
|
|
889
|
+
} else {
|
|
890
|
+
out += '$' + digits;
|
|
891
|
+
}
|
|
892
|
+
i = j - 1;
|
|
893
|
+
continue;
|
|
894
|
+
}
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
out += ch;
|
|
898
|
+
}
|
|
899
|
+
|
|
900
|
+
return out;
|
|
901
|
+
}
|
|
902
|
+
|
|
847
903
|
// -----------------------------------------------------------------------------
|
|
848
904
|
// Strict numeric literal parsing for math: builtins
|
|
849
905
|
// -----------------------------------------------------------------------------
|
|
@@ -4222,7 +4278,11 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen, maxResults) {
|
|
|
4222
4278
|
const re = compileSwapRegex(searchStr, 'g');
|
|
4223
4279
|
if (!re) return [];
|
|
4224
4280
|
|
|
4225
|
-
const outStr = dataStr.replace(re,
|
|
4281
|
+
const outStr = dataStr.replace(re, (...args) => {
|
|
4282
|
+
const captureEnd = args.length - (typeof args.at(-1) === 'object' ? 3 : 2);
|
|
4283
|
+
const captures = args.slice(0, Math.max(1, captureEnd));
|
|
4284
|
+
return expandSwapRegexReplacement(replStr, captures);
|
|
4285
|
+
});
|
|
4226
4286
|
const lit = makeStringLiteral(outStr);
|
|
4227
4287
|
|
|
4228
4288
|
if (g.o instanceof Var) {
|
package/eyeling.js
CHANGED
|
@@ -844,6 +844,62 @@ function compileSwapRegex(pattern, extraFlags) {
|
|
|
844
844
|
}
|
|
845
845
|
}
|
|
846
846
|
|
|
847
|
+
function expandSwapRegexReplacement(template, captures) {
|
|
848
|
+
// SWAP/N3 examples use $1-style capture references, but tests also rely on
|
|
849
|
+
// Perl-ish escaping in replacement strings: \\$ means a literal dollar sign
|
|
850
|
+
// and \\ means a literal backslash. JavaScript's replacement strings do not
|
|
851
|
+
// interpret those escapes, so expand the replacement explicitly in a callback.
|
|
852
|
+
let out = '';
|
|
853
|
+
const text = String(template);
|
|
854
|
+
|
|
855
|
+
for (let i = 0; i < text.length; i++) {
|
|
856
|
+
const ch = text[i];
|
|
857
|
+
|
|
858
|
+
if (ch === '\\') {
|
|
859
|
+
if (i + 1 < text.length && (text[i + 1] === '$' || text[i + 1] === '\\')) {
|
|
860
|
+
out += text[++i];
|
|
861
|
+
} else {
|
|
862
|
+
out += ch;
|
|
863
|
+
}
|
|
864
|
+
continue;
|
|
865
|
+
}
|
|
866
|
+
|
|
867
|
+
if (ch === '$') {
|
|
868
|
+
if (i + 1 < text.length && text[i + 1] === '$') {
|
|
869
|
+
out += '$';
|
|
870
|
+
i++;
|
|
871
|
+
continue;
|
|
872
|
+
}
|
|
873
|
+
|
|
874
|
+
let j = i + 1;
|
|
875
|
+
while (j < text.length && /[0-9]/.test(text[j])) j++;
|
|
876
|
+
if (j > i + 1) {
|
|
877
|
+
const digits = text.slice(i + 1, j);
|
|
878
|
+
let chosen = null;
|
|
879
|
+
for (let k = digits.length; k > 0; k--) {
|
|
880
|
+
const n = Number(digits.slice(0, k));
|
|
881
|
+
if (n > 0 && n < captures.length) {
|
|
882
|
+
chosen = { n, len: k };
|
|
883
|
+
break;
|
|
884
|
+
}
|
|
885
|
+
}
|
|
886
|
+
if (chosen) {
|
|
887
|
+
out += captures[chosen.n] == null ? '' : String(captures[chosen.n]);
|
|
888
|
+
out += digits.slice(chosen.len);
|
|
889
|
+
} else {
|
|
890
|
+
out += '$' + digits;
|
|
891
|
+
}
|
|
892
|
+
i = j - 1;
|
|
893
|
+
continue;
|
|
894
|
+
}
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
out += ch;
|
|
898
|
+
}
|
|
899
|
+
|
|
900
|
+
return out;
|
|
901
|
+
}
|
|
902
|
+
|
|
847
903
|
// -----------------------------------------------------------------------------
|
|
848
904
|
// Strict numeric literal parsing for math: builtins
|
|
849
905
|
// -----------------------------------------------------------------------------
|
|
@@ -4222,7 +4278,11 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen, maxResults) {
|
|
|
4222
4278
|
const re = compileSwapRegex(searchStr, 'g');
|
|
4223
4279
|
if (!re) return [];
|
|
4224
4280
|
|
|
4225
|
-
const outStr = dataStr.replace(re,
|
|
4281
|
+
const outStr = dataStr.replace(re, (...args) => {
|
|
4282
|
+
const captureEnd = args.length - (typeof args.at(-1) === 'object' ? 3 : 2);
|
|
4283
|
+
const captures = args.slice(0, Math.max(1, captureEnd));
|
|
4284
|
+
return expandSwapRegexReplacement(replStr, captures);
|
|
4285
|
+
});
|
|
4226
4286
|
const lit = makeStringLiteral(outStr);
|
|
4227
4287
|
|
|
4228
4288
|
if (g.o instanceof Var) {
|
package/lib/builtins.js
CHANGED
|
@@ -833,6 +833,62 @@ function compileSwapRegex(pattern, extraFlags) {
|
|
|
833
833
|
}
|
|
834
834
|
}
|
|
835
835
|
|
|
836
|
+
function expandSwapRegexReplacement(template, captures) {
|
|
837
|
+
// SWAP/N3 examples use $1-style capture references, but tests also rely on
|
|
838
|
+
// Perl-ish escaping in replacement strings: \\$ means a literal dollar sign
|
|
839
|
+
// and \\ means a literal backslash. JavaScript's replacement strings do not
|
|
840
|
+
// interpret those escapes, so expand the replacement explicitly in a callback.
|
|
841
|
+
let out = '';
|
|
842
|
+
const text = String(template);
|
|
843
|
+
|
|
844
|
+
for (let i = 0; i < text.length; i++) {
|
|
845
|
+
const ch = text[i];
|
|
846
|
+
|
|
847
|
+
if (ch === '\\') {
|
|
848
|
+
if (i + 1 < text.length && (text[i + 1] === '$' || text[i + 1] === '\\')) {
|
|
849
|
+
out += text[++i];
|
|
850
|
+
} else {
|
|
851
|
+
out += ch;
|
|
852
|
+
}
|
|
853
|
+
continue;
|
|
854
|
+
}
|
|
855
|
+
|
|
856
|
+
if (ch === '$') {
|
|
857
|
+
if (i + 1 < text.length && text[i + 1] === '$') {
|
|
858
|
+
out += '$';
|
|
859
|
+
i++;
|
|
860
|
+
continue;
|
|
861
|
+
}
|
|
862
|
+
|
|
863
|
+
let j = i + 1;
|
|
864
|
+
while (j < text.length && /[0-9]/.test(text[j])) j++;
|
|
865
|
+
if (j > i + 1) {
|
|
866
|
+
const digits = text.slice(i + 1, j);
|
|
867
|
+
let chosen = null;
|
|
868
|
+
for (let k = digits.length; k > 0; k--) {
|
|
869
|
+
const n = Number(digits.slice(0, k));
|
|
870
|
+
if (n > 0 && n < captures.length) {
|
|
871
|
+
chosen = { n, len: k };
|
|
872
|
+
break;
|
|
873
|
+
}
|
|
874
|
+
}
|
|
875
|
+
if (chosen) {
|
|
876
|
+
out += captures[chosen.n] == null ? '' : String(captures[chosen.n]);
|
|
877
|
+
out += digits.slice(chosen.len);
|
|
878
|
+
} else {
|
|
879
|
+
out += '$' + digits;
|
|
880
|
+
}
|
|
881
|
+
i = j - 1;
|
|
882
|
+
continue;
|
|
883
|
+
}
|
|
884
|
+
}
|
|
885
|
+
|
|
886
|
+
out += ch;
|
|
887
|
+
}
|
|
888
|
+
|
|
889
|
+
return out;
|
|
890
|
+
}
|
|
891
|
+
|
|
836
892
|
// -----------------------------------------------------------------------------
|
|
837
893
|
// Strict numeric literal parsing for math: builtins
|
|
838
894
|
// -----------------------------------------------------------------------------
|
|
@@ -4211,7 +4267,11 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen, maxResults) {
|
|
|
4211
4267
|
const re = compileSwapRegex(searchStr, 'g');
|
|
4212
4268
|
if (!re) return [];
|
|
4213
4269
|
|
|
4214
|
-
const outStr = dataStr.replace(re,
|
|
4270
|
+
const outStr = dataStr.replace(re, (...args) => {
|
|
4271
|
+
const captureEnd = args.length - (typeof args.at(-1) === 'object' ? 3 : 2);
|
|
4272
|
+
const captures = args.slice(0, Math.max(1, captureEnd));
|
|
4273
|
+
return expandSwapRegexReplacement(replStr, captures);
|
|
4274
|
+
});
|
|
4215
4275
|
const lit = makeStringLiteral(outStr);
|
|
4216
4276
|
|
|
4217
4277
|
if (g.o instanceof Var) {
|
package/package.json
CHANGED
package/test/api.test.js
CHANGED
|
@@ -1533,6 +1533,35 @@ res:CITY_Chañaral rdfs:label "Chañaral".
|
|
|
1533
1533
|
expect: [/:result\s+:has\s+:success-literal-30\s*\./, /:test\s+:is\s+true\s*\./],
|
|
1534
1534
|
},
|
|
1535
1535
|
|
|
1536
|
+
{
|
|
1537
|
+
name: '52g regression: string:replace honors escaped dollar and backslash in replacement',
|
|
1538
|
+
opt: { proofComments: false },
|
|
1539
|
+
input: `@prefix : <http://example.org/> .
|
|
1540
|
+
@prefix string: <http://www.w3.org/2000/10/swap/string#> .
|
|
1541
|
+
|
|
1542
|
+
{
|
|
1543
|
+
("abcd" "b" "\\$\\\\") string:replace "a$\\cd".
|
|
1544
|
+
}
|
|
1545
|
+
=>
|
|
1546
|
+
{
|
|
1547
|
+
:result :has :success-literal-8.
|
|
1548
|
+
}.
|
|
1549
|
+
|
|
1550
|
+
{} => {
|
|
1551
|
+
:test :contains :success-literal-8.
|
|
1552
|
+
}.
|
|
1553
|
+
|
|
1554
|
+
{
|
|
1555
|
+
:result :has :success-literal-8.
|
|
1556
|
+
}
|
|
1557
|
+
=>
|
|
1558
|
+
{
|
|
1559
|
+
:test :is true.
|
|
1560
|
+
}.
|
|
1561
|
+
`,
|
|
1562
|
+
expect: [/:result\s+:has\s+:success-literal-8\s*\./, /:test\s+:is\s+true\s*\./],
|
|
1563
|
+
},
|
|
1564
|
+
|
|
1536
1565
|
{
|
|
1537
1566
|
name: '53 --stream: prints prefixes used in input (not just derived output) before streaming triples',
|
|
1538
1567
|
opt: ['--stream', '-n'],
|