eyeling 1.29.2 → 1.30.0
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 +153 -0
- package/dist/browser/eyeling.browser.js +711 -21
- package/examples/input/rdf-surfaces-all-values-from-reverse.ttl +17 -0
- package/examples/input/rdf-surfaces-all-values-from.ttl +13 -0
- package/examples/input/rdf-surfaces-ancestor.ttl +20 -0
- package/examples/input/rdf-surfaces-city.ttl +11 -0
- package/examples/input/rdf-surfaces-domain.ttl +11 -0
- package/examples/input/rdf-surfaces-multi-premise.ttl +13 -0
- package/examples/input/rdf-surfaces-owl-all-values-from-codex.ttl +35 -0
- package/examples/input/rdf-surfaces-property-chain.ttl +13 -0
- package/examples/input/rdf-surfaces-range.ttl +11 -0
- package/examples/input/rdf-surfaces-rdfs-range-codex.ttl +18 -0
- package/examples/input/rdf-surfaces-rdfs-subclass-codex.ttl +18 -0
- package/examples/output/rdf-surfaces-all-values-from-reverse.n3 +3 -0
- package/examples/output/rdf-surfaces-all-values-from.n3 +3 -0
- package/examples/output/rdf-surfaces-ancestor.n3 +5 -0
- package/examples/output/rdf-surfaces-city.n3 +3 -0
- package/examples/output/rdf-surfaces-domain.n3 +3 -0
- package/examples/output/rdf-surfaces-multi-premise.n3 +3 -0
- package/examples/output/rdf-surfaces-owl-all-values-from-codex.n3 +6 -0
- package/examples/output/rdf-surfaces-property-chain.n3 +3 -0
- package/examples/output/rdf-surfaces-range.n3 +3 -0
- package/examples/output/rdf-surfaces-rdfs-range-codex.n3 +3 -0
- package/examples/output/rdf-surfaces-rdfs-subclass-codex.n3 +3 -0
- package/examples/rdf-surfaces-all-values-from-reverse.n3 +6 -0
- package/examples/rdf-surfaces-all-values-from.n3 +6 -0
- package/examples/rdf-surfaces-ancestor.n3 +6 -0
- package/examples/rdf-surfaces-city.n3 +6 -0
- package/examples/rdf-surfaces-domain.n3 +6 -0
- package/examples/rdf-surfaces-multi-premise.n3 +6 -0
- package/examples/rdf-surfaces-owl-all-values-from-codex.n3 +10 -0
- package/examples/rdf-surfaces-property-chain.n3 +6 -0
- package/examples/rdf-surfaces-range.n3 +6 -0
- package/examples/rdf-surfaces-rdfs-range-codex.n3 +6 -0
- package/examples/rdf-surfaces-rdfs-subclass-codex.n3 +6 -0
- package/eyeling.js +711 -21
- package/index.d.ts +4 -0
- package/index.js +2 -1
- package/lib/builtins.js +128 -3
- package/lib/cli.js +11 -4
- package/lib/engine.js +15 -7
- package/lib/lexer.js +4 -0
- package/lib/multisource.js +5 -3
- package/lib/prelude.js +18 -0
- package/lib/rdf_surfaces.js +524 -0
- package/lib/rules.js +3 -4
- package/package.json +8 -5
- package/test/builtins.test.js +36 -0
- package/test/examples.test.js +37 -5
- package/test/rdf_surfaces.test.js +204 -0
|
@@ -41,6 +41,8 @@ const {
|
|
|
41
41
|
PrefixEnv,
|
|
42
42
|
literalParts,
|
|
43
43
|
copyQuotedGraphMetadata,
|
|
44
|
+
isInternalBlankVarName,
|
|
45
|
+
internalBlankVarSuffix,
|
|
44
46
|
} = require('./prelude');
|
|
45
47
|
|
|
46
48
|
const { decodeN3StringEscapes } = require('./lexer');
|
|
@@ -143,6 +145,127 @@ function __assertBuiltinHandlerResult(iri, out) {
|
|
|
143
145
|
}
|
|
144
146
|
}
|
|
145
147
|
|
|
148
|
+
function collectVarNamesInTerm(t, acc) {
|
|
149
|
+
if (t instanceof Var) {
|
|
150
|
+
acc.add(t.name);
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
if (t instanceof ListTerm) {
|
|
154
|
+
for (const e of t.elems) collectVarNamesInTerm(e, acc);
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
if (t instanceof OpenListTerm) {
|
|
158
|
+
for (const e of t.prefix) collectVarNamesInTerm(e, acc);
|
|
159
|
+
acc.add(t.tailVar);
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
if (t instanceof GraphTerm) {
|
|
163
|
+
for (const tr of t.triples) collectVarNamesInTriple(tr, acc);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
function collectVarNamesInTriple(tr, acc) {
|
|
168
|
+
collectVarNamesInTerm(tr.s, acc);
|
|
169
|
+
collectVarNamesInTerm(tr.p, acc);
|
|
170
|
+
collectVarNamesInTerm(tr.o, acc);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
function cloneSubstWithMappedKeys(subst, keyMap, externalizeTerm) {
|
|
174
|
+
const out = Object.create(null);
|
|
175
|
+
for (const [key, val] of Object.entries(subst || {})) {
|
|
176
|
+
out[keyMap.get(key) || key] = externalizeTerm ? externalizeTerm(val) : val;
|
|
177
|
+
}
|
|
178
|
+
return out;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
function hasInternalBlankVarInSubst(subst) {
|
|
182
|
+
for (const key of Object.keys(subst || {})) {
|
|
183
|
+
if (isInternalBlankVarName(key)) return true;
|
|
184
|
+
}
|
|
185
|
+
return false;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
function makeCustomBuiltinPublicBridge(goal, subst) {
|
|
189
|
+
const used = new Set(Object.keys(subst || {}).filter((name) => !isInternalBlankVarName(name)));
|
|
190
|
+
collectVarNamesInTriple(goal, used);
|
|
191
|
+
for (const name of Array.from(used)) {
|
|
192
|
+
if (isInternalBlankVarName(name)) used.delete(name);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
const internalNames = new Set();
|
|
196
|
+
collectVarNamesInTriple(goal, internalNames);
|
|
197
|
+
for (const key of Object.keys(subst || {})) internalNames.add(key);
|
|
198
|
+
for (const name of Array.from(internalNames)) {
|
|
199
|
+
if (!isInternalBlankVarName(name)) internalNames.delete(name);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
if (internalNames.size === 0 && !hasInternalBlankVarInSubst(subst)) return null;
|
|
203
|
+
|
|
204
|
+
const internalToPublic = new Map();
|
|
205
|
+
const publicToInternal = new Map();
|
|
206
|
+
|
|
207
|
+
function allocatePublicName(internalName) {
|
|
208
|
+
const suffix = internalBlankVarSuffix(internalName) || String(internalToPublic.size + 1);
|
|
209
|
+
const base = /^[$A-Za-z_][0-9A-Za-z_]*$/u.test(`_b${suffix}`) ? `_b${suffix}` : `_b${internalToPublic.size + 1}`;
|
|
210
|
+
let name = base;
|
|
211
|
+
let n = 1;
|
|
212
|
+
while (used.has(name) || publicToInternal.has(name)) {
|
|
213
|
+
n += 1;
|
|
214
|
+
name = `${base}_${n}`;
|
|
215
|
+
}
|
|
216
|
+
used.add(name);
|
|
217
|
+
internalToPublic.set(internalName, name);
|
|
218
|
+
publicToInternal.set(name, internalName);
|
|
219
|
+
return name;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
for (const name of internalNames) allocatePublicName(name);
|
|
223
|
+
|
|
224
|
+
function externalName(name) {
|
|
225
|
+
if (!isInternalBlankVarName(name)) return name;
|
|
226
|
+
return internalToPublic.get(name) || allocatePublicName(name);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
function externalizeTerm(t) {
|
|
230
|
+
if (t instanceof Var) return new Var(externalName(t.name));
|
|
231
|
+
if (t instanceof ListTerm) return new ListTerm(t.elems.map(externalizeTerm));
|
|
232
|
+
if (t instanceof OpenListTerm) return new OpenListTerm(t.prefix.map(externalizeTerm), externalName(t.tailVar));
|
|
233
|
+
if (t instanceof GraphTerm) {
|
|
234
|
+
const triples = t.triples.map((tr) => new Triple(externalizeTerm(tr.s), externalizeTerm(tr.p), externalizeTerm(tr.o)));
|
|
235
|
+
return copyQuotedGraphMetadata(t, new GraphTerm(triples));
|
|
236
|
+
}
|
|
237
|
+
return t;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
function internalizeTerm(t) {
|
|
241
|
+
if (t instanceof Var) return new Var(publicToInternal.get(t.name) || t.name);
|
|
242
|
+
if (t instanceof ListTerm) return new ListTerm(t.elems.map(internalizeTerm));
|
|
243
|
+
if (t instanceof OpenListTerm) return new OpenListTerm(t.prefix.map(internalizeTerm), publicToInternal.get(t.tailVar) || t.tailVar);
|
|
244
|
+
if (t instanceof GraphTerm) {
|
|
245
|
+
const triples = t.triples.map((tr) => new Triple(internalizeTerm(tr.s), internalizeTerm(tr.p), internalizeTerm(tr.o)));
|
|
246
|
+
return copyQuotedGraphMetadata(t, new GraphTerm(triples));
|
|
247
|
+
}
|
|
248
|
+
return t;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
function internalizeDelta(delta) {
|
|
252
|
+
const out = Object.create(null);
|
|
253
|
+
for (const [key, val] of Object.entries(delta || {})) {
|
|
254
|
+
out[publicToInternal.get(key) || key] = internalizeTerm(val);
|
|
255
|
+
}
|
|
256
|
+
return out;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
return {
|
|
260
|
+
goal: new Triple(externalizeTerm(goal.s), externalizeTerm(goal.p), externalizeTerm(goal.o)),
|
|
261
|
+
subst: cloneSubstWithMappedKeys(subst, internalToPublic, externalizeTerm),
|
|
262
|
+
internalizeResults(out) {
|
|
263
|
+
if (out == null) return out;
|
|
264
|
+
return out.map(internalizeDelta);
|
|
265
|
+
},
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
|
|
146
269
|
function apiTermToN3(term, prefixes = PrefixEnv.newDefault()) {
|
|
147
270
|
return termToN3(term, prefixes || PrefixEnv.newDefault());
|
|
148
271
|
}
|
|
@@ -242,10 +365,11 @@ function __evalRegisteredBuiltin(pv, goal, subst, facts, backRules, depth, varGe
|
|
|
242
365
|
const handler = __customBuiltinHandlers.get(pv);
|
|
243
366
|
if (typeof handler !== 'function') return null;
|
|
244
367
|
|
|
368
|
+
const bridge = makeCustomBuiltinPublicBridge(goal, subst);
|
|
245
369
|
const ctx = {
|
|
246
370
|
iri: pv,
|
|
247
|
-
goal,
|
|
248
|
-
subst,
|
|
371
|
+
goal: bridge ? bridge.goal : goal,
|
|
372
|
+
subst: bridge ? bridge.subst : subst,
|
|
249
373
|
facts,
|
|
250
374
|
backRules,
|
|
251
375
|
depth,
|
|
@@ -255,7 +379,8 @@ function __evalRegisteredBuiltin(pv, goal, subst, facts, backRules, depth, varGe
|
|
|
255
379
|
};
|
|
256
380
|
|
|
257
381
|
try {
|
|
258
|
-
const
|
|
382
|
+
const raw = handler(ctx);
|
|
383
|
+
const out = bridge ? bridge.internalizeResults(raw) : raw;
|
|
259
384
|
if (out == null) return [];
|
|
260
385
|
__assertBuiltinHandlerResult(pv, out);
|
|
261
386
|
return out;
|
|
@@ -5965,7 +6090,7 @@ async function ingestLineBasedRdfSourceToStore(sourceLabel, store, { rdfMode = t
|
|
|
5965
6090
|
}
|
|
5966
6091
|
|
|
5967
6092
|
|
|
5968
|
-
async function runStreamMessagesMode(sourceLabels, { rdfMode, storeName = null, storePath = null, storeClear = false } = {}) {
|
|
6093
|
+
async function runStreamMessagesMode(sourceLabels, { rdfMode, rdfSurfacesMode = false, storeName = null, storePath = null, storeClear = false } = {}) {
|
|
5969
6094
|
const ordinarySourceLabels = [];
|
|
5970
6095
|
const messageSourceLabels = [];
|
|
5971
6096
|
|
|
@@ -6003,6 +6128,7 @@ async function runStreamMessagesMode(sourceLabels, { rdfMode, storeName = null,
|
|
|
6003
6128
|
keepSourceArtifacts: false,
|
|
6004
6129
|
sourceLocations: false,
|
|
6005
6130
|
rdf: rdfMode,
|
|
6131
|
+
rdfSurfaces: rdfSurfacesMode,
|
|
6006
6132
|
}),
|
|
6007
6133
|
);
|
|
6008
6134
|
} catch (e) {
|
|
@@ -6036,6 +6162,7 @@ async function runStreamMessagesMode(sourceLabels, { rdfMode, storeName = null,
|
|
|
6036
6162
|
keepSourceArtifacts: false,
|
|
6037
6163
|
sourceLocations: false,
|
|
6038
6164
|
rdf: false,
|
|
6165
|
+
rdfSurfaces: false,
|
|
6039
6166
|
});
|
|
6040
6167
|
} catch (e) {
|
|
6041
6168
|
if (e && e.name === 'N3SyntaxError') {
|
|
@@ -6090,6 +6217,7 @@ async function main() {
|
|
|
6090
6217
|
` -h, --help Show this help and exit.\n` +
|
|
6091
6218
|
` -p, --proof Enable proof explanations.\n` +
|
|
6092
6219
|
` -r, --rdf Enable RDF/TriG input/output compatibility.\n` +
|
|
6220
|
+
` --rdf-surfaces Enable RDF Surfaces %not[...%] syntax (implies --rdf).\n` +
|
|
6093
6221
|
` --stream-messages Process RDF Message Logs one message at a time under -r.\n` +
|
|
6094
6222
|
` --store <name> Use an optional persistent fact store.\n` +
|
|
6095
6223
|
` --store-clear Clear the named store before this run.\n` +
|
|
@@ -6165,7 +6293,8 @@ async function main() {
|
|
|
6165
6293
|
const showAst = argv.includes('--ast') || argv.includes('-a');
|
|
6166
6294
|
const streamMode = argv.includes('--stream') || argv.includes('-t');
|
|
6167
6295
|
const streamMessagesMode = argv.includes('--stream-messages');
|
|
6168
|
-
const
|
|
6296
|
+
const rdfSurfacesMode = argv.includes('--rdf-surfaces');
|
|
6297
|
+
const rdfMode = argv.includes('--rdf') || argv.includes('-r') || rdfSurfacesMode;
|
|
6169
6298
|
const storeName = argv.__storeName || null;
|
|
6170
6299
|
const storePath = argv.__storePath || null;
|
|
6171
6300
|
const storeClear = argv.includes('--store-clear');
|
|
@@ -6234,7 +6363,7 @@ async function main() {
|
|
|
6234
6363
|
}
|
|
6235
6364
|
|
|
6236
6365
|
if (streamMessagesMode) {
|
|
6237
|
-
await runStreamMessagesMode(sourceLabels, { rdfMode, storeName, storePath, storeClear });
|
|
6366
|
+
await runStreamMessagesMode(sourceLabels, { rdfMode, rdfSurfacesMode, storeName, storePath, storeClear });
|
|
6238
6367
|
return;
|
|
6239
6368
|
}
|
|
6240
6369
|
|
|
@@ -6288,6 +6417,7 @@ async function main() {
|
|
|
6288
6417
|
keepSourceArtifacts: false,
|
|
6289
6418
|
sourceLocations: false,
|
|
6290
6419
|
rdf: rdfMode,
|
|
6420
|
+
rdfSurfaces: rdfSurfacesMode,
|
|
6291
6421
|
}),
|
|
6292
6422
|
);
|
|
6293
6423
|
} catch (e) {
|
|
@@ -6300,7 +6430,7 @@ async function main() {
|
|
|
6300
6430
|
}
|
|
6301
6431
|
|
|
6302
6432
|
const mergedRuleDocument = mergeParsedDocuments(parsedRuleSources);
|
|
6303
|
-
const result = await engine.runStoreBacked(mergedRuleDocument, store, { rdf: rdfMode });
|
|
6433
|
+
const result = await engine.runStoreBacked(mergedRuleDocument, store, { rdf: rdfMode, rdfSurfaces: rdfSurfacesMode });
|
|
6304
6434
|
const outTriples = result.queryMode ? result.queryTriples || [] : (result.derived || []).map((df) => df.fact);
|
|
6305
6435
|
if (result.queryMode) {
|
|
6306
6436
|
const bodyText = engine.prettyPrintQueryTriples(outTriples, result.prefixes);
|
|
@@ -6335,6 +6465,7 @@ async function main() {
|
|
|
6335
6465
|
keepSourceArtifacts: false,
|
|
6336
6466
|
sourceLocations: engine.getProofCommentsEnabled(),
|
|
6337
6467
|
rdf: rdfMode,
|
|
6468
|
+
rdfSurfaces: rdfSurfacesMode,
|
|
6338
6469
|
}),
|
|
6339
6470
|
);
|
|
6340
6471
|
} catch (e) {
|
|
@@ -6435,6 +6566,7 @@ function factsContainOutputStrings(triplesForOutput) {
|
|
|
6435
6566
|
{
|
|
6436
6567
|
proof: engine.getProofCommentsEnabled(),
|
|
6437
6568
|
rdf: rdfMode,
|
|
6569
|
+
rdfSurfaces: rdfSurfacesMode,
|
|
6438
6570
|
store: { name: storeName, clear: storeClear, path: storePath || undefined },
|
|
6439
6571
|
},
|
|
6440
6572
|
);
|
|
@@ -10688,12 +10820,14 @@ function reasonStream(input, opts = {}) {
|
|
|
10688
10820
|
skipUnsupportedRdfJs = false,
|
|
10689
10821
|
builtinModules = null,
|
|
10690
10822
|
rdf = false,
|
|
10823
|
+
rdfSurfaces = false,
|
|
10691
10824
|
sourceLabel = '<input>',
|
|
10692
10825
|
} = opts;
|
|
10693
10826
|
|
|
10694
|
-
const useRdfCompatibility = !!rdf;
|
|
10827
|
+
const useRdfCompatibility = !!rdf || !!rdfSurfaces;
|
|
10828
|
+
const useRdfSurfaces = !!rdfSurfaces;
|
|
10695
10829
|
|
|
10696
|
-
const parsedSourceList = parseN3SourceList(input, { baseIri, rdf: useRdfCompatibility, sourceLocations: proof });
|
|
10830
|
+
const parsedSourceList = parseN3SourceList(input, { baseIri, rdf: useRdfCompatibility, rdfSurfaces: useRdfSurfaces, sourceLocations: proof });
|
|
10697
10831
|
const parsedTextInput = (!parsedSourceList && proof && typeof input === 'string')
|
|
10698
10832
|
? parseN3Text(input, {
|
|
10699
10833
|
baseIri: baseIri || '',
|
|
@@ -10701,6 +10835,7 @@ function reasonStream(input, opts = {}) {
|
|
|
10701
10835
|
keepSourceArtifacts: false,
|
|
10702
10836
|
sourceLocations: true,
|
|
10703
10837
|
rdf: useRdfCompatibility,
|
|
10838
|
+
rdfSurfaces: useRdfSurfaces,
|
|
10704
10839
|
})
|
|
10705
10840
|
: null;
|
|
10706
10841
|
const hasInlineN3 = input && typeof input === 'object' && !Array.isArray(input) && typeof input.n3 === 'string';
|
|
@@ -10745,6 +10880,7 @@ function reasonStream(input, opts = {}) {
|
|
|
10745
10880
|
keepSourceArtifacts: false,
|
|
10746
10881
|
sourceLocations: proof,
|
|
10747
10882
|
rdf: useRdfCompatibility,
|
|
10883
|
+
rdfSurfaces: useRdfSurfaces,
|
|
10748
10884
|
});
|
|
10749
10885
|
prefixes = directDoc.prefixes;
|
|
10750
10886
|
triples = directDoc.triples;
|
|
@@ -10856,10 +10992,11 @@ async function __parseRunAsyncInput(input, opts) {
|
|
|
10856
10992
|
baseIri = null,
|
|
10857
10993
|
proof = false,
|
|
10858
10994
|
rdf = false,
|
|
10995
|
+
rdfSurfaces = false,
|
|
10859
10996
|
sourceLabel = '<input>',
|
|
10860
10997
|
} = opts || {};
|
|
10861
10998
|
|
|
10862
|
-
const parsedSourceList = parseN3SourceList(input, { baseIri, rdf: !!rdf, sourceLocations: !!proof });
|
|
10999
|
+
const parsedSourceList = parseN3SourceList(input, { baseIri, rdf: !!rdf || !!rdfSurfaces, rdfSurfaces: !!rdfSurfaces, sourceLocations: !!proof });
|
|
10863
11000
|
if (parsedSourceList) return parsedSourceList;
|
|
10864
11001
|
|
|
10865
11002
|
const parsedObject = await normalizeParsedReasonerInputAsync(input);
|
|
@@ -10874,7 +11011,8 @@ async function __parseRunAsyncInput(input, opts) {
|
|
|
10874
11011
|
label: sourceLabel || '<input>',
|
|
10875
11012
|
keepSourceArtifacts: false,
|
|
10876
11013
|
sourceLocations: !!proof,
|
|
10877
|
-
rdf: !!rdf,
|
|
11014
|
+
rdf: !!rdf || !!rdfSurfaces,
|
|
11015
|
+
rdfSurfaces: !!rdfSurfaces,
|
|
10878
11016
|
});
|
|
10879
11017
|
}
|
|
10880
11018
|
|
|
@@ -10950,7 +11088,8 @@ async function __proveGoalsAgainstStore(goals, subst, store, backRules, localFac
|
|
|
10950
11088
|
async function runStoreBacked(input, store, opts = {}) {
|
|
10951
11089
|
const parsed = parseN3SourceList(input, {
|
|
10952
11090
|
baseIri: opts.baseIri || null,
|
|
10953
|
-
rdf: !!opts.rdf,
|
|
11091
|
+
rdf: !!opts.rdf || !!opts.rdfSurfaces,
|
|
11092
|
+
rdfSurfaces: !!opts.rdfSurfaces,
|
|
10954
11093
|
sourceLocations: !!opts.proof,
|
|
10955
11094
|
}) || input;
|
|
10956
11095
|
|
|
@@ -10995,7 +11134,7 @@ async function runStoreBacked(input, store, opts = {}) {
|
|
|
10995
11134
|
}
|
|
10996
11135
|
|
|
10997
11136
|
let queryTriples = [];
|
|
10998
|
-
|
|
11137
|
+
let queryDerived = [];
|
|
10999
11138
|
if (qrules.length) {
|
|
11000
11139
|
for (const r of qrules) {
|
|
11001
11140
|
const solutions = await __proveGoalsAgainstStore(r.premise || [], __emptySubst(), store, brules, triples, 0, varGen, {});
|
|
@@ -11067,7 +11206,8 @@ async function runAsync(input, opts = {}) {
|
|
|
11067
11206
|
if (!storeConfig) {
|
|
11068
11207
|
const normalizedInput = parseN3SourceList(input, {
|
|
11069
11208
|
baseIri: runOpts.baseIri || null,
|
|
11070
|
-
rdf: !!runOpts.rdf,
|
|
11209
|
+
rdf: !!runOpts.rdf || !!runOpts.rdfSurfaces,
|
|
11210
|
+
rdfSurfaces: !!runOpts.rdfSurfaces,
|
|
11071
11211
|
sourceLocations: !!runOpts.proof,
|
|
11072
11212
|
}) || (await normalizeReasonerInputAsync(input));
|
|
11073
11213
|
return reasonStream(normalizedInput, runOpts);
|
|
@@ -12317,6 +12457,8 @@ module.exports = { tryParseFastRdfText, parseFastRdfText, parseFastRdfMessageLog
|
|
|
12317
12457
|
|
|
12318
12458
|
'use strict';
|
|
12319
12459
|
|
|
12460
|
+
const { normalizeRdfSurfaces } = require('./rdf_surfaces');
|
|
12461
|
+
|
|
12320
12462
|
class Token {
|
|
12321
12463
|
constructor(typ, value = null, offset = null) {
|
|
12322
12464
|
this.typ = typ;
|
|
@@ -13657,7 +13799,9 @@ function isNumericLikeIdentifier(word) {
|
|
|
13657
13799
|
|
|
13658
13800
|
function lex(inputText, opts = {}) {
|
|
13659
13801
|
const rdf = !!(opts && opts.rdf);
|
|
13802
|
+
const rdfSurfaces = !!(opts && opts.rdfSurfaces);
|
|
13660
13803
|
if (rdf) inputText = normalizeRdfCompatibility(inputText);
|
|
13804
|
+
if (rdfSurfaces) inputText = normalizeRdfSurfaces(inputText);
|
|
13661
13805
|
// Avoid copying large ASCII/BMP inputs into an Array. Array.from() is
|
|
13662
13806
|
// only needed when the text contains surrogate pairs and we want the old
|
|
13663
13807
|
// code-point iteration behavior for non-BMP characters.
|
|
@@ -14440,9 +14584,10 @@ function parseN3Text(text, opts = {}) {
|
|
|
14440
14584
|
collectUsedPrefixes = false,
|
|
14441
14585
|
sourceLocations = false,
|
|
14442
14586
|
rdf = false,
|
|
14587
|
+
rdfSurfaces = false,
|
|
14443
14588
|
} = opts || {};
|
|
14444
14589
|
|
|
14445
|
-
if (rdf) {
|
|
14590
|
+
if (rdf && !rdfSurfaces) {
|
|
14446
14591
|
const fastDoc = tryParseFastRdfText(text, { baseIri, label });
|
|
14447
14592
|
if (fastDoc) {
|
|
14448
14593
|
if (sourceLocations) annotateParsedSourceLocations(fastDoc, text, label);
|
|
@@ -14451,7 +14596,7 @@ function parseN3Text(text, opts = {}) {
|
|
|
14451
14596
|
}
|
|
14452
14597
|
}
|
|
14453
14598
|
|
|
14454
|
-
const tokens = lex(text, { rdf });
|
|
14599
|
+
const tokens = lex(text, { rdf, rdfSurfaces });
|
|
14455
14600
|
const parser = new Parser(tokens);
|
|
14456
14601
|
if (baseIri) parser.prefixes.setBase(baseIri);
|
|
14457
14602
|
const [prefixes, triples, frules, brules, logQueryRules] = parser.parseDocument();
|
|
@@ -14650,7 +14795,8 @@ function parseN3SourceList(input, opts = {}) {
|
|
|
14650
14795
|
collectUsedPrefixes: true,
|
|
14651
14796
|
keepSourceArtifacts: !!opts.keepSourceArtifacts,
|
|
14652
14797
|
sourceLocations: !!opts.sourceLocations,
|
|
14653
|
-
rdf: !!opts.rdf,
|
|
14798
|
+
rdf: !!opts.rdf || !!opts.rdfSurfaces,
|
|
14799
|
+
rdfSurfaces: !!opts.rdfSurfaces,
|
|
14654
14800
|
}),
|
|
14655
14801
|
);
|
|
14656
14802
|
return mergeParsedDocuments(parsed, {
|
|
@@ -15468,6 +15614,21 @@ const DT_NS = 'https://eyereasoner.github.io/eyeling/datatype#';
|
|
|
15468
15614
|
const SKOLEM_NS = 'https://eyereasoner.github.io/.well-known/genid/';
|
|
15469
15615
|
const RDF_JSON_DT = RDF_NS + 'JSON';
|
|
15470
15616
|
|
|
15617
|
+
// Private rule-lifting variable prefix used for blank nodes that appear in
|
|
15618
|
+
// rule-body patterns. The prefix is intentionally not spellable in N3 input,
|
|
15619
|
+
// but public extension APIs should present these variables with stable,
|
|
15620
|
+
// ordinary names and translate them back internally.
|
|
15621
|
+
const INTERNAL_BLANK_VAR_PREFIX = '\uE000eyeling_b';
|
|
15622
|
+
|
|
15623
|
+
function isInternalBlankVarName(name) {
|
|
15624
|
+
return typeof name === 'string' && name.startsWith(INTERNAL_BLANK_VAR_PREFIX);
|
|
15625
|
+
}
|
|
15626
|
+
|
|
15627
|
+
function internalBlankVarSuffix(name) {
|
|
15628
|
+
if (!isInternalBlankVarName(name)) return '';
|
|
15629
|
+
return name.slice(INTERNAL_BLANK_VAR_PREFIX.length);
|
|
15630
|
+
}
|
|
15631
|
+
|
|
15471
15632
|
function parseUriReferenceForResolution(uri) {
|
|
15472
15633
|
// RFC 3986 Appendix B-style component parser, with the scheme tightened to
|
|
15473
15634
|
// the RFC scheme grammar. Capturing delimiter presence matters: `?` with an
|
|
@@ -16171,6 +16332,9 @@ module.exports = {
|
|
|
16171
16332
|
DT_NS,
|
|
16172
16333
|
SKOLEM_NS,
|
|
16173
16334
|
RDF_JSON_DT,
|
|
16335
|
+
INTERNAL_BLANK_VAR_PREFIX,
|
|
16336
|
+
isInternalBlankVarName,
|
|
16337
|
+
internalBlankVarSuffix,
|
|
16174
16338
|
resolveIriRef,
|
|
16175
16339
|
literalParts,
|
|
16176
16340
|
normalizeLiteralForTid,
|
|
@@ -16662,6 +16826,533 @@ module.exports = {
|
|
|
16662
16826
|
needsRdf12Version,
|
|
16663
16827
|
};
|
|
16664
16828
|
|
|
16829
|
+
};
|
|
16830
|
+
__modules["lib/rdf_surfaces.js"] = function(require, module, exports){
|
|
16831
|
+
/**
|
|
16832
|
+
* Eyeling Reasoner — RDF Surfaces syntax normalizer
|
|
16833
|
+
*
|
|
16834
|
+
* Implements a small RDF Surfaces text convention inspired by Hayes' BLOGIC
|
|
16835
|
+
* slides: `%not[ ... %]` surface parentheses with explicit blank mark binders
|
|
16836
|
+
* such as `_:x _:y` at the beginning of a surface. The supported fragment
|
|
16837
|
+
* covers slide 32, the slide 33 range shape, both slide 33 allValuesFrom
|
|
16838
|
+
* shapes, and top-level fuse surfaces.
|
|
16839
|
+
*
|
|
16840
|
+
* The normalizer rewrites the supported fragment into ordinary Eyeling N3:
|
|
16841
|
+
* %not[ _:x P(?x) . %not[ Q(?x) . %] %]
|
|
16842
|
+
* becomes:
|
|
16843
|
+
* { P(?x) . } => { Q(?x) . } .
|
|
16844
|
+
*
|
|
16845
|
+
* A top-level negative surface without an inner negative surface becomes an
|
|
16846
|
+
* inference fuse:
|
|
16847
|
+
* %not[ _:x P(?x) . %]
|
|
16848
|
+
* becomes:
|
|
16849
|
+
* { P(?x) . } => false .
|
|
16850
|
+
*/
|
|
16851
|
+
|
|
16852
|
+
'use strict';
|
|
16853
|
+
|
|
16854
|
+
function syntaxError(message, offset = null) {
|
|
16855
|
+
const e = new Error(message);
|
|
16856
|
+
e.name = 'N3SyntaxError';
|
|
16857
|
+
if (typeof offset === 'number') e.offset = offset;
|
|
16858
|
+
return e;
|
|
16859
|
+
}
|
|
16860
|
+
|
|
16861
|
+
function isWs(ch) {
|
|
16862
|
+
return ch != null && /\s/.test(ch);
|
|
16863
|
+
}
|
|
16864
|
+
|
|
16865
|
+
|
|
16866
|
+
function readStringAt(s, at) {
|
|
16867
|
+
const quote = s[at];
|
|
16868
|
+
let i = at;
|
|
16869
|
+
let out = quote;
|
|
16870
|
+
const long = s.startsWith(quote.repeat(3), i);
|
|
16871
|
+
if (long) {
|
|
16872
|
+
out = quote.repeat(3);
|
|
16873
|
+
i += 3;
|
|
16874
|
+
while (i < s.length) {
|
|
16875
|
+
if (s.startsWith(quote.repeat(3), i)) {
|
|
16876
|
+
out += quote.repeat(3);
|
|
16877
|
+
i += 3;
|
|
16878
|
+
return { text: out, end: i };
|
|
16879
|
+
}
|
|
16880
|
+
if (s[i] === '\\' && i + 1 < s.length) {
|
|
16881
|
+
out += s.slice(i, i + 2);
|
|
16882
|
+
i += 2;
|
|
16883
|
+
} else {
|
|
16884
|
+
out += s[i++];
|
|
16885
|
+
}
|
|
16886
|
+
}
|
|
16887
|
+
throw syntaxError('Unterminated string literal inside RDF Surface', at);
|
|
16888
|
+
}
|
|
16889
|
+
|
|
16890
|
+
i += 1;
|
|
16891
|
+
let escaped = false;
|
|
16892
|
+
while (i < s.length) {
|
|
16893
|
+
const ch = s[i++];
|
|
16894
|
+
out += ch;
|
|
16895
|
+
if (escaped) escaped = false;
|
|
16896
|
+
else if (ch === '\\') escaped = true;
|
|
16897
|
+
else if (ch === quote) return { text: out, end: i };
|
|
16898
|
+
}
|
|
16899
|
+
throw syntaxError('Unterminated string literal inside RDF Surface', at);
|
|
16900
|
+
}
|
|
16901
|
+
|
|
16902
|
+
function readIriAt(s, at) {
|
|
16903
|
+
let i = at + 1;
|
|
16904
|
+
let out = '<';
|
|
16905
|
+
while (i < s.length) {
|
|
16906
|
+
const ch = s[i++];
|
|
16907
|
+
out += ch;
|
|
16908
|
+
if (ch === '>') return { text: out, end: i };
|
|
16909
|
+
}
|
|
16910
|
+
throw syntaxError('Unterminated IRI inside RDF Surface', at);
|
|
16911
|
+
}
|
|
16912
|
+
|
|
16913
|
+
function skipWsAndComments(s, at) {
|
|
16914
|
+
let i = at;
|
|
16915
|
+
while (i < s.length) {
|
|
16916
|
+
if (isWs(s[i])) {
|
|
16917
|
+
i += 1;
|
|
16918
|
+
continue;
|
|
16919
|
+
}
|
|
16920
|
+
if (s[i] === '#') {
|
|
16921
|
+
while (i < s.length && s[i] !== '\n' && s[i] !== '\r') i += 1;
|
|
16922
|
+
continue;
|
|
16923
|
+
}
|
|
16924
|
+
break;
|
|
16925
|
+
}
|
|
16926
|
+
return i;
|
|
16927
|
+
}
|
|
16928
|
+
|
|
16929
|
+
function readBareTokenAt(s, at) {
|
|
16930
|
+
const i0 = skipWsAndComments(s, at);
|
|
16931
|
+
if (i0 >= s.length) return null;
|
|
16932
|
+
if (s[i0] === '<') return readIriAt(s, i0);
|
|
16933
|
+
if (s[i0] === '"' || s[i0] === "'") return readStringAt(s, i0);
|
|
16934
|
+
let i = i0;
|
|
16935
|
+
while (i < s.length && !isWs(s[i]) && !'{}[](),;.'.includes(s[i])) i += 1;
|
|
16936
|
+
if (i === i0) return null;
|
|
16937
|
+
return { text: s.slice(i0, i), start: i0, end: i };
|
|
16938
|
+
}
|
|
16939
|
+
|
|
16940
|
+
function readStatementSegment(s) {
|
|
16941
|
+
let i = 0;
|
|
16942
|
+
let depthBrace = 0;
|
|
16943
|
+
let depthBracket = 0;
|
|
16944
|
+
let depthParen = 0;
|
|
16945
|
+
while (i < s.length) {
|
|
16946
|
+
if (s.startsWith('%not[', i) && depthBrace === 0 && depthBracket === 0 && depthParen === 0) {
|
|
16947
|
+
return s.slice(0, i);
|
|
16948
|
+
}
|
|
16949
|
+
const ch = s[i];
|
|
16950
|
+
if (ch === '"' || ch === "'") {
|
|
16951
|
+
i = readStringAt(s, i).end;
|
|
16952
|
+
continue;
|
|
16953
|
+
}
|
|
16954
|
+
if (ch === '<') {
|
|
16955
|
+
i = readIriAt(s, i).end;
|
|
16956
|
+
continue;
|
|
16957
|
+
}
|
|
16958
|
+
if (ch === '#') {
|
|
16959
|
+
while (i < s.length && s[i] !== '\n' && s[i] !== '\r') i += 1;
|
|
16960
|
+
continue;
|
|
16961
|
+
}
|
|
16962
|
+
if (ch === '{') depthBrace += 1;
|
|
16963
|
+
else if (ch === '}' && depthBrace > 0) depthBrace -= 1;
|
|
16964
|
+
else if (ch === '[') depthBracket += 1;
|
|
16965
|
+
else if (ch === ']' && depthBracket > 0) depthBracket -= 1;
|
|
16966
|
+
else if (ch === '(') depthParen += 1;
|
|
16967
|
+
else if (ch === ')' && depthParen > 0) depthParen -= 1;
|
|
16968
|
+
else if (ch === '.' && depthBrace === 0 && depthBracket === 0 && depthParen === 0) return s.slice(0, i);
|
|
16969
|
+
i += 1;
|
|
16970
|
+
}
|
|
16971
|
+
return s;
|
|
16972
|
+
}
|
|
16973
|
+
|
|
16974
|
+
function tokenizeLeadingSegment(segment) {
|
|
16975
|
+
const toks = [];
|
|
16976
|
+
let pos = 0;
|
|
16977
|
+
while (pos < segment.length) {
|
|
16978
|
+
const tok = readBareTokenAt(segment, pos);
|
|
16979
|
+
if (!tok) break;
|
|
16980
|
+
toks.push(tok);
|
|
16981
|
+
pos = tok.end;
|
|
16982
|
+
}
|
|
16983
|
+
return toks;
|
|
16984
|
+
}
|
|
16985
|
+
|
|
16986
|
+
function extractLeadingBinders(raw) {
|
|
16987
|
+
const text = String(raw || '');
|
|
16988
|
+
const contentStart = skipWsAndComments(text, 0);
|
|
16989
|
+
if (contentStart >= text.length) return { binders: [], text };
|
|
16990
|
+
|
|
16991
|
+
const segment = readStatementSegment(text.slice(contentStart));
|
|
16992
|
+
const toks = tokenizeLeadingSegment(segment);
|
|
16993
|
+
let leadingBlankCount = 0;
|
|
16994
|
+
while (leadingBlankCount < toks.length && /^_:[A-Za-z_][A-Za-z0-9._-]*$/.test(toks[leadingBlankCount].text)) {
|
|
16995
|
+
leadingBlankCount += 1;
|
|
16996
|
+
}
|
|
16997
|
+
|
|
16998
|
+
if (leadingBlankCount === 0) return { binders: [], text };
|
|
16999
|
+
|
|
17000
|
+
let binderCount = 0;
|
|
17001
|
+
if (toks.length >= 3) {
|
|
17002
|
+
// Prefer the longest explicit binder prefix that still leaves at least a
|
|
17003
|
+
// subject, predicate, and object for the first statement. This matches the
|
|
17004
|
+
// BLOGIC slide convention, e.g. `%not[ _:x _:x a :C . ... %]`.
|
|
17005
|
+
binderCount = Math.min(leadingBlankCount, Math.max(0, toks.length - 3));
|
|
17006
|
+
} else {
|
|
17007
|
+
// No own triple before a nested surface: treat the leading marks as binders.
|
|
17008
|
+
binderCount = leadingBlankCount;
|
|
17009
|
+
}
|
|
17010
|
+
|
|
17011
|
+
if (binderCount <= 0) return { binders: [], text };
|
|
17012
|
+
|
|
17013
|
+
const binders = toks.slice(0, binderCount).map((t) => t.text.slice(2));
|
|
17014
|
+
const cut = toks[binderCount - 1].end;
|
|
17015
|
+
return { binders, text: text.slice(0, contentStart) + text.slice(contentStart + cut) };
|
|
17016
|
+
}
|
|
17017
|
+
|
|
17018
|
+
function splitTopLevelStatements(raw, surfaceOffset = null) {
|
|
17019
|
+
const text = String(raw || '');
|
|
17020
|
+
const out = [];
|
|
17021
|
+
let start = 0;
|
|
17022
|
+
let i = 0;
|
|
17023
|
+
let depthBrace = 0;
|
|
17024
|
+
let depthBracket = 0;
|
|
17025
|
+
let depthParen = 0;
|
|
17026
|
+
|
|
17027
|
+
while (i < text.length) {
|
|
17028
|
+
const ch = text[i];
|
|
17029
|
+
if (ch === '"' || ch === "'") {
|
|
17030
|
+
i = readStringAt(text, i).end;
|
|
17031
|
+
continue;
|
|
17032
|
+
}
|
|
17033
|
+
if (ch === '<') {
|
|
17034
|
+
i = readIriAt(text, i).end;
|
|
17035
|
+
continue;
|
|
17036
|
+
}
|
|
17037
|
+
if (ch === '#') {
|
|
17038
|
+
while (i < text.length && text[i] !== '\n' && text[i] !== '\r') i += 1;
|
|
17039
|
+
continue;
|
|
17040
|
+
}
|
|
17041
|
+
if (ch === '{') depthBrace += 1;
|
|
17042
|
+
else if (ch === '}' && depthBrace > 0) depthBrace -= 1;
|
|
17043
|
+
else if (ch === '[') depthBracket += 1;
|
|
17044
|
+
else if (ch === ']' && depthBracket > 0) depthBracket -= 1;
|
|
17045
|
+
else if (ch === '(') depthParen += 1;
|
|
17046
|
+
else if (ch === ')' && depthParen > 0) depthParen -= 1;
|
|
17047
|
+
else if (ch === '.' && depthBrace === 0 && depthBracket === 0 && depthParen === 0) {
|
|
17048
|
+
const stmt = text.slice(start, i).trim();
|
|
17049
|
+
if (stmt) out.push(stmt);
|
|
17050
|
+
start = i + 1;
|
|
17051
|
+
}
|
|
17052
|
+
i += 1;
|
|
17053
|
+
}
|
|
17054
|
+
|
|
17055
|
+
const tail = text.slice(start).trim();
|
|
17056
|
+
if (tail) {
|
|
17057
|
+
// A raw binder-only segment is OK; any other dangling text is most likely a
|
|
17058
|
+
// missing dot in the surface body.
|
|
17059
|
+
if (!/^_:[A-Za-z_][A-Za-z0-9._-]*(?:\s+_:[A-Za-z_][A-Za-z0-9._-]*)*$/.test(tail)) {
|
|
17060
|
+
throw syntaxError('RDF Surface statement is missing a terminating dot', surfaceOffset);
|
|
17061
|
+
}
|
|
17062
|
+
}
|
|
17063
|
+
|
|
17064
|
+
return out;
|
|
17065
|
+
}
|
|
17066
|
+
|
|
17067
|
+
function readSurfaceAt(s, at) {
|
|
17068
|
+
if (!s.startsWith('%not[', at)) return null;
|
|
17069
|
+
let i = at + '%not['.length;
|
|
17070
|
+
let current = '';
|
|
17071
|
+
const segments = [];
|
|
17072
|
+
const children = [];
|
|
17073
|
+
|
|
17074
|
+
while (i < s.length) {
|
|
17075
|
+
if (s.startsWith('%]', i)) {
|
|
17076
|
+
segments.push(current);
|
|
17077
|
+
i += 2;
|
|
17078
|
+
const raw = segments.join('\n');
|
|
17079
|
+
const stripped = extractLeadingBinders(raw);
|
|
17080
|
+
return {
|
|
17081
|
+
type: 'not',
|
|
17082
|
+
start: at,
|
|
17083
|
+
end: i,
|
|
17084
|
+
binders: stripped.binders,
|
|
17085
|
+
statements: splitTopLevelStatements(stripped.text, at),
|
|
17086
|
+
children,
|
|
17087
|
+
};
|
|
17088
|
+
}
|
|
17089
|
+
|
|
17090
|
+
if (s.startsWith('%not[', i)) {
|
|
17091
|
+
segments.push(current);
|
|
17092
|
+
current = '';
|
|
17093
|
+
const child = readSurfaceAt(s, i);
|
|
17094
|
+
children.push(child);
|
|
17095
|
+
i = child.end;
|
|
17096
|
+
continue;
|
|
17097
|
+
}
|
|
17098
|
+
|
|
17099
|
+
const ch = s[i];
|
|
17100
|
+
if (ch === '"' || ch === "'") {
|
|
17101
|
+
const str = readStringAt(s, i);
|
|
17102
|
+
current += str.text;
|
|
17103
|
+
i = str.end;
|
|
17104
|
+
continue;
|
|
17105
|
+
}
|
|
17106
|
+
if (ch === '<') {
|
|
17107
|
+
const iri = readIriAt(s, i);
|
|
17108
|
+
current += iri.text;
|
|
17109
|
+
i = iri.end;
|
|
17110
|
+
continue;
|
|
17111
|
+
}
|
|
17112
|
+
if (ch === '#') {
|
|
17113
|
+
while (i < s.length) {
|
|
17114
|
+
const c = s[i++];
|
|
17115
|
+
current += c;
|
|
17116
|
+
if (c === '\n' || c === '\r') break;
|
|
17117
|
+
}
|
|
17118
|
+
continue;
|
|
17119
|
+
}
|
|
17120
|
+
|
|
17121
|
+
current += ch;
|
|
17122
|
+
i += 1;
|
|
17123
|
+
}
|
|
17124
|
+
|
|
17125
|
+
throw syntaxError('Unterminated RDF Surface, expected %]', at);
|
|
17126
|
+
}
|
|
17127
|
+
|
|
17128
|
+
const LOG_FOR_ALL_IN_IRI = '<http://www.w3.org/2000/10/swap/log#forAllIn>';
|
|
17129
|
+
|
|
17130
|
+
function rewriteBlankMarksWithMap(statement, labelToVarName) {
|
|
17131
|
+
const map = labelToVarName instanceof Map ? labelToVarName : new Map();
|
|
17132
|
+
let out = '';
|
|
17133
|
+
let i = 0;
|
|
17134
|
+
while (i < statement.length) {
|
|
17135
|
+
const ch = statement[i];
|
|
17136
|
+
if (ch === '"' || ch === "'") {
|
|
17137
|
+
const str = readStringAt(statement, i);
|
|
17138
|
+
out += str.text;
|
|
17139
|
+
i = str.end;
|
|
17140
|
+
continue;
|
|
17141
|
+
}
|
|
17142
|
+
if (ch === '<') {
|
|
17143
|
+
const iri = readIriAt(statement, i);
|
|
17144
|
+
out += iri.text;
|
|
17145
|
+
i = iri.end;
|
|
17146
|
+
continue;
|
|
17147
|
+
}
|
|
17148
|
+
if (ch === '#') {
|
|
17149
|
+
while (i < statement.length) {
|
|
17150
|
+
const c = statement[i++];
|
|
17151
|
+
out += c;
|
|
17152
|
+
if (c === '\n' || c === '\r') break;
|
|
17153
|
+
}
|
|
17154
|
+
continue;
|
|
17155
|
+
}
|
|
17156
|
+
if (statement.startsWith('_:', i)) {
|
|
17157
|
+
let j = i + 2;
|
|
17158
|
+
while (j < statement.length && !isWs(statement[j]) && !'{}[](),;.'.includes(statement[j])) j += 1;
|
|
17159
|
+
const label = statement.slice(i + 2, j);
|
|
17160
|
+
const mapped = label ? map.get(label) : null;
|
|
17161
|
+
if (mapped) {
|
|
17162
|
+
out += `?${mapped}`;
|
|
17163
|
+
i = j;
|
|
17164
|
+
continue;
|
|
17165
|
+
}
|
|
17166
|
+
}
|
|
17167
|
+
out += ch;
|
|
17168
|
+
i += 1;
|
|
17169
|
+
}
|
|
17170
|
+
return out.trim();
|
|
17171
|
+
}
|
|
17172
|
+
|
|
17173
|
+
function formatGraphWithMap(statements, labelMap) {
|
|
17174
|
+
const body = (statements || [])
|
|
17175
|
+
.map((st) => rewriteBlankMarksWithMap(st, labelMap))
|
|
17176
|
+
.filter(Boolean)
|
|
17177
|
+
.map((st) => ` ${st} .`)
|
|
17178
|
+
.join('\n');
|
|
17179
|
+
return body ? `{
|
|
17180
|
+
${body}\n}` : '{ }';
|
|
17181
|
+
}
|
|
17182
|
+
|
|
17183
|
+
function formatGraphFromRewritten(statements) {
|
|
17184
|
+
const body = (statements || [])
|
|
17185
|
+
.map((st) => String(st || '').trim())
|
|
17186
|
+
.filter(Boolean)
|
|
17187
|
+
.map((st) => ` ${st} .`)
|
|
17188
|
+
.join('\n');
|
|
17189
|
+
return body ? `{
|
|
17190
|
+
${body}\n}` : '{ }';
|
|
17191
|
+
}
|
|
17192
|
+
|
|
17193
|
+
function makeVarMap(labels, prefix = '') {
|
|
17194
|
+
const map = new Map();
|
|
17195
|
+
for (const label of labels || []) map.set(label, `${prefix}${label}`);
|
|
17196
|
+
return map;
|
|
17197
|
+
}
|
|
17198
|
+
|
|
17199
|
+
function mergeVarMaps(...maps) {
|
|
17200
|
+
const out = new Map();
|
|
17201
|
+
for (const m of maps) {
|
|
17202
|
+
for (const [k, v] of m.entries()) out.set(k, v);
|
|
17203
|
+
}
|
|
17204
|
+
return out;
|
|
17205
|
+
}
|
|
17206
|
+
|
|
17207
|
+
function slide33ReverseAllValuesFromRule(node, inheritedMap = new Map(), extraPremises = []) {
|
|
17208
|
+
const outerBinders = node.binders || [];
|
|
17209
|
+
const own = node.statements || [];
|
|
17210
|
+
const children = node.children || [];
|
|
17211
|
+
|
|
17212
|
+
if (own.length !== 0 || outerBinders.length === 0 || children.length !== 2) return null;
|
|
17213
|
+
|
|
17214
|
+
let bodyChild = null;
|
|
17215
|
+
let headChild = null;
|
|
17216
|
+
for (const child of children) {
|
|
17217
|
+
const childChildren = child && child.children ? child.children : [];
|
|
17218
|
+
if (childChildren.length === 1) bodyChild = child;
|
|
17219
|
+
else if (childChildren.length === 0) headChild = child;
|
|
17220
|
+
else return null;
|
|
17221
|
+
}
|
|
17222
|
+
|
|
17223
|
+
if (!bodyChild || !headChild) return null;
|
|
17224
|
+
if (!bodyChild.statements || bodyChild.statements.length === 0) return null;
|
|
17225
|
+
if (!headChild.statements || headChild.statements.length === 0) return null;
|
|
17226
|
+
|
|
17227
|
+
const thenChild = bodyChild.children[0];
|
|
17228
|
+
if (!thenChild || (thenChild.children && thenChild.children.length)) return null;
|
|
17229
|
+
if (!thenChild.statements || thenChild.statements.length === 0) return null;
|
|
17230
|
+
|
|
17231
|
+
const outerMap = mergeVarMaps(inheritedMap, makeVarMap(outerBinders));
|
|
17232
|
+
const witnessMap = makeVarMap(bodyChild.binders || [], '__rs_witness_');
|
|
17233
|
+
const localMap = makeVarMap(bodyChild.binders || [], '__rs_');
|
|
17234
|
+
|
|
17235
|
+
const mappedExtra = (extraPremises || [])
|
|
17236
|
+
.map((st) => rewriteBlankMarksWithMap(st, outerMap))
|
|
17237
|
+
.filter(Boolean);
|
|
17238
|
+
const premiseStmts = bodyChild.statements
|
|
17239
|
+
.map((st) => rewriteBlankMarksWithMap(st, mergeVarMaps(outerMap, witnessMap)))
|
|
17240
|
+
.filter(Boolean);
|
|
17241
|
+
|
|
17242
|
+
const whereGraph = formatGraphWithMap(bodyChild.statements, mergeVarMaps(outerMap, localMap));
|
|
17243
|
+
const thenGraph = formatGraphWithMap(thenChild.statements, mergeVarMaps(outerMap, localMap));
|
|
17244
|
+
const forAllLine = `( ${whereGraph} ${thenGraph} ) ${LOG_FOR_ALL_IN_IRI} 1`;
|
|
17245
|
+
|
|
17246
|
+
const premise = formatGraphFromRewritten([...mappedExtra, ...premiseStmts, forAllLine]);
|
|
17247
|
+
const conclusion = formatGraphWithMap(headChild.statements, outerMap);
|
|
17248
|
+
return `${premise} => ${conclusion} .`;
|
|
17249
|
+
}
|
|
17250
|
+
|
|
17251
|
+
|
|
17252
|
+
function translateHeadSurface(node, extraPremises, inheritedMap = new Map()) {
|
|
17253
|
+
const rules = [];
|
|
17254
|
+
const map = inheritedMap instanceof Map ? inheritedMap : new Map();
|
|
17255
|
+
const own = node.statements || [];
|
|
17256
|
+
if (own.length) {
|
|
17257
|
+
rules.push(`${formatGraphWithMap(extraPremises, map)} => ${formatGraphWithMap(own, map)} .`);
|
|
17258
|
+
}
|
|
17259
|
+
for (const child of node.children || []) {
|
|
17260
|
+
rules.push(...translateRuleSurface(child, extraPremises, map));
|
|
17261
|
+
}
|
|
17262
|
+
return rules;
|
|
17263
|
+
}
|
|
17264
|
+
|
|
17265
|
+
function translateRuleSurface(node, extraPremises = [], inheritedMap = new Map()) {
|
|
17266
|
+
const slide33Reverse = slide33ReverseAllValuesFromRule(node, inheritedMap, extraPremises);
|
|
17267
|
+
if (slide33Reverse) return [slide33Reverse];
|
|
17268
|
+
|
|
17269
|
+
const map = mergeVarMaps(inheritedMap, makeVarMap(node.binders || []));
|
|
17270
|
+
const own = node.statements || [];
|
|
17271
|
+
const premise = [...(extraPremises || []), ...own];
|
|
17272
|
+
const children = node.children || [];
|
|
17273
|
+
|
|
17274
|
+
if (children.length === 0) {
|
|
17275
|
+
return own.length ? [`${formatGraphWithMap(premise, map)} => false .`] : [];
|
|
17276
|
+
}
|
|
17277
|
+
|
|
17278
|
+
return children.flatMap((child) => translateHeadSurface(child, premise, map));
|
|
17279
|
+
}
|
|
17280
|
+
|
|
17281
|
+
function translateTopLevelSurface(node) {
|
|
17282
|
+
const map = makeVarMap(node.binders || []);
|
|
17283
|
+
const own = node.statements || [];
|
|
17284
|
+
|
|
17285
|
+
if (!node.children || node.children.length === 0) {
|
|
17286
|
+
return own.length ? [`${formatGraphWithMap(own, map)} => false .`] : [];
|
|
17287
|
+
}
|
|
17288
|
+
|
|
17289
|
+
const slide33Reverse = slide33ReverseAllValuesFromRule(node);
|
|
17290
|
+
if (slide33Reverse) return [slide33Reverse];
|
|
17291
|
+
|
|
17292
|
+
return node.children.flatMap((child) => translateHeadSurface(child, own, map));
|
|
17293
|
+
}
|
|
17294
|
+
|
|
17295
|
+
function normalizeRdfSurfaces(inputText) {
|
|
17296
|
+
const s = String(inputText ?? '');
|
|
17297
|
+
if (!s.includes('%not[')) return s;
|
|
17298
|
+
|
|
17299
|
+
let out = '';
|
|
17300
|
+
const generated = [];
|
|
17301
|
+
let i = 0;
|
|
17302
|
+
let braceDepth = 0;
|
|
17303
|
+
let bracketDepth = 0;
|
|
17304
|
+
let parenDepth = 0;
|
|
17305
|
+
|
|
17306
|
+
while (i < s.length) {
|
|
17307
|
+
if (s.startsWith('%not[', i) && braceDepth === 0 && bracketDepth === 0 && parenDepth === 0) {
|
|
17308
|
+
const surface = readSurfaceAt(s, i);
|
|
17309
|
+
generated.push(...translateTopLevelSurface(surface));
|
|
17310
|
+
i = surface.end;
|
|
17311
|
+
continue;
|
|
17312
|
+
}
|
|
17313
|
+
|
|
17314
|
+
const ch = s[i];
|
|
17315
|
+
if (ch === '"' || ch === "'") {
|
|
17316
|
+
const str = readStringAt(s, i);
|
|
17317
|
+
out += str.text;
|
|
17318
|
+
i = str.end;
|
|
17319
|
+
continue;
|
|
17320
|
+
}
|
|
17321
|
+
if (ch === '<') {
|
|
17322
|
+
const iri = readIriAt(s, i);
|
|
17323
|
+
out += iri.text;
|
|
17324
|
+
i = iri.end;
|
|
17325
|
+
continue;
|
|
17326
|
+
}
|
|
17327
|
+
if (ch === '#') {
|
|
17328
|
+
while (i < s.length) {
|
|
17329
|
+
const c = s[i++];
|
|
17330
|
+
out += c;
|
|
17331
|
+
if (c === '\n' || c === '\r') break;
|
|
17332
|
+
}
|
|
17333
|
+
continue;
|
|
17334
|
+
}
|
|
17335
|
+
|
|
17336
|
+
if (ch === '{') braceDepth += 1;
|
|
17337
|
+
else if (ch === '}' && braceDepth > 0) braceDepth -= 1;
|
|
17338
|
+
else if (ch === '[') bracketDepth += 1;
|
|
17339
|
+
else if (ch === ']' && bracketDepth > 0) bracketDepth -= 1;
|
|
17340
|
+
else if (ch === '(') parenDepth += 1;
|
|
17341
|
+
else if (ch === ')' && parenDepth > 0) parenDepth -= 1;
|
|
17342
|
+
|
|
17343
|
+
out += ch;
|
|
17344
|
+
i += 1;
|
|
17345
|
+
}
|
|
17346
|
+
|
|
17347
|
+
if (generated.length === 0) return out;
|
|
17348
|
+
const sep = out.trim() ? (out.endsWith('\n') ? '\n' : '\n\n') : '';
|
|
17349
|
+
return out + sep + generated.join('\n\n') + '\n';
|
|
17350
|
+
}
|
|
17351
|
+
|
|
17352
|
+
module.exports = {
|
|
17353
|
+
normalizeRdfSurfaces,
|
|
17354
|
+
};
|
|
17355
|
+
|
|
16665
17356
|
};
|
|
16666
17357
|
__modules["lib/rdfjs.js"] = function(require, module, exports){
|
|
16667
17358
|
/**
|
|
@@ -17645,6 +18336,7 @@ const {
|
|
|
17645
18336
|
GraphTerm,
|
|
17646
18337
|
Triple,
|
|
17647
18338
|
copyQuotedGraphMetadata,
|
|
18339
|
+
INTERNAL_BLANK_VAR_PREFIX,
|
|
17648
18340
|
} = require('./prelude');
|
|
17649
18341
|
|
|
17650
18342
|
function liftBlankRuleVars(premise, conclusion) {
|
|
@@ -17660,10 +18352,8 @@ function liftBlankRuleVars(premise, conclusion) {
|
|
|
17660
18352
|
// These variables are implementation details used to correlate one blank
|
|
17661
18353
|
// node across the lifted rule body. Their names must not be spellable by
|
|
17662
18354
|
// user input; otherwise a user variable such as ?_b1 can capture the
|
|
17663
|
-
// lifted blank node and leak it into the rule head.
|
|
17664
|
-
//
|
|
17665
|
-
const INTERNAL_BLANK_VAR_PREFIX = '\uE000eyeling_b';
|
|
17666
|
-
|
|
18355
|
+
// lifted blank node and leak it into the rule head. The public custom
|
|
18356
|
+
// builtin API maps these names back to ordinary-looking ?_bN variables.
|
|
17667
18357
|
function blankToVar(label) {
|
|
17668
18358
|
let name = mapping[label];
|
|
17669
18359
|
if (name === undefined) {
|