@manta-eu/datalog-parser 0.1.0 → 0.1.2

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 CHANGED
@@ -1,10 +1,10 @@
1
1
  # @manta-eu/datalog-parser
2
2
 
3
- RDFox Datalog parser and AST builder with inference verification.
3
+ Datalog parser and AST builder with inference verification.
4
4
 
5
5
  ## Features
6
6
 
7
- - **Complete Datalog Parser**: Parses RDFox Datalog rules into type-safe ASTs
7
+ - **Complete Datalog Parser**: Parses Datalog rules into type-safe ASTs
8
8
  - **Syntax Validation**: Comprehensive rule validation with error reporting
9
9
  - **Built-in Function Support**: CONCAT, STR, IF, IRI, SKOLEM, ROUND, REGEX functions
10
10
  - **Advanced Constructs**: Support for FILTER, BIND, AGGREGATE, NOT EXIST patterns
@@ -31,13 +31,13 @@ const equivalent = areRulesEquivalent(rule1, rule2);
31
31
  ### Advanced Features
32
32
 
33
33
  ```typescript
34
- import { verifyRuleInference, transactionManager } from "@manta-eu/datalog-parser";
34
+ import { verifyRuleInference, withTransaction } from "@manta-eu/datalog-parser";
35
35
 
36
- // Verify rule produces expected inferences
37
- await verifyRuleInference(rule, expectedFacts, rdfoxConfig);
36
+ // Verify rule produces expected inferences against a running datastore
37
+ await verifyRuleInference(rule, endpointUrl, datastoreId, authorization);
38
38
 
39
39
  // Manage transactions
40
- await transactionManager.withTransaction(async () => {
40
+ await withTransaction({ endpointUrl, datastoreName, authorization }, async (connectionId) => {
41
41
  // Rule operations here
42
42
  });
43
43
  ```
@@ -53,5 +53,5 @@ import type { DatalogRule, DatalogAtom, DatalogBodyFormula } from "@manta-eu/dat
53
53
  - **Head Atoms**: Property atoms, class atoms, general atoms
54
54
  - **Body Formulas**: All atom types plus FILTER, BIND, AGGREGATE, SKOLEM, negation
55
55
  - **Expressions**: Binary operators, function calls, literals
56
- - **Built-in Functions**: Full RDFox function library
56
+ - **Built-in Functions**: The full built-in function library
57
57
  - **Complex Patterns**: NOT EXIST clauses with mixed formulas
package/dist/index.d.ts CHANGED
@@ -39,7 +39,7 @@ export declare type AggregateBinding = AggregateFunctionBinding | ExpressionAggr
39
39
  export declare type AggregateBindingTarget = {
40
40
  /** Target variable name without its `?`, or the value's text when `groundedTarget` is set. */
41
41
  variable: string;
42
- /** Set only when the expanded grammar read a value in `AS` position, as RDFox's grounded rules do. */
42
+ /** Set only when the expanded grammar read a value in `AS` position, as the engine's grounded rules do. */
43
43
  groundedTarget?: DatalogTerm;
44
44
  };
45
45
 
@@ -172,7 +172,7 @@ export declare const BaseDatalogVisitor: new (...args: any[]) => ICstVisitor<any
172
172
  /**
173
173
  * Begin a read-write transaction on a connection
174
174
  */
175
- export declare function beginTransaction(params: RDFoxTransactionParams): Promise<void>;
175
+ export declare function beginTransaction(params: DatastoreTransactionParams): Promise<void>;
176
176
 
177
177
  export declare type BinaryAggregateBinding = AggregateBindingTarget & {
178
178
  function: BinaryAggregateFunction;
@@ -254,6 +254,8 @@ export declare const booleanLiteralTokenTypes: Set<TokenType>;
254
254
 
255
255
  export declare const builtinFunctionTokenTypes: Set<TokenType>;
256
256
 
257
+ export declare function canonicalRuleText(rule: string): string;
258
+
257
259
  export declare type ClassAssertion = {
258
260
  className: string;
259
261
  instance: DatalogTerm;
@@ -280,7 +282,7 @@ export declare const COMMENT: TokenType;
280
282
  /**
281
283
  * Commit a transaction on a connection
282
284
  */
283
- export declare function commitTransaction(params: RDFoxTransactionParams): Promise<void>;
285
+ export declare function commitTransaction(params: DatastoreTransactionParams): Promise<void>;
284
286
 
285
287
  export declare type ComparisonOperator = Extract<BinaryExpression["operator"], "=" | "!=" | "<" | ">" | "<=" | ">=">;
286
288
 
@@ -327,7 +329,7 @@ export declare const COUNT_MIN: TokenType;
327
329
  /**
328
330
  * Create a connection to a datastore
329
331
  */
330
- export declare function createConnection(params: RDFoxConnectionParams): Promise<string>;
332
+ export declare function createConnection(params: DatastoreConnectionParams): Promise<string>;
331
333
 
332
334
  export declare type DatalogAggregate = {
333
335
  type: "aggregate";
@@ -340,7 +342,7 @@ export declare type DatalogAggregate = {
340
342
  * variable name (`datalog-to-sparql-select`, `ast-utils`) — use authored/strict ASTs there.
341
343
  */
342
344
  onVars?: string[];
343
- /** Set only when the expanded grammar read values in `ON` position, as RDFox's grounded rules do. */
345
+ /** Set only when the expanded grammar read values in `ON` position, as the engine's grounded rules do. */
344
346
  groundedOnTargets?: DatalogTerm[];
345
347
  bindings?: AggregateBinding[];
346
348
  };
@@ -417,7 +419,7 @@ export declare type DatalogBind = {
417
419
  expression: DatalogExpression;
418
420
  /** Target variable name without its `?`, or the value's text when `groundedTarget` is set. */
419
421
  variable: string;
420
- /** Set only when the expanded grammar read a value in `AS` position, as RDFox's grounded rules do. */
422
+ /** Set only when the expanded grammar read a value in `AS` position, as the engine's grounded rules do. */
421
423
  groundedTarget?: DatalogTerm;
422
424
  };
423
425
 
@@ -544,6 +546,25 @@ export declare type DatalogToken = IToken;
544
546
 
545
547
  export declare type DataManipulationSubType = "insertdata" | "deletedata" | "modify";
546
548
 
549
+ /**
550
+ * Transaction Management Library
551
+ *
552
+ * This module provides side-effecty functions for managing datastore connections and transactions
553
+ * via the RESTful API. It follows the engine's connection-based transaction model where transactions
554
+ * are associated with data store connections.
555
+ *
556
+ * @see https://docs.oxfordsemantic.tech/apis.html#transactions-in-the-restful-api
557
+ */
558
+ export declare type DatastoreConnectionParams = {
559
+ endpointUrl: string;
560
+ datastoreName: string;
561
+ authorization: string;
562
+ };
563
+
564
+ export declare type DatastoreTransactionParams = DatastoreConnectionParams & {
565
+ connectionId: string;
566
+ };
567
+
547
568
  export declare function datatypeToTermText(datatype: string): string;
548
569
 
549
570
  export declare const DECIMAL: TokenType;
@@ -570,7 +591,7 @@ export declare interface DefaultGraphAtomCstNode extends CstNode {
570
591
  /**
571
592
  * Delete a connection
572
593
  */
573
- export declare function deleteConnection(params: RDFoxTransactionParams): Promise<void>;
594
+ export declare function deleteConnection(params: DatastoreTransactionParams): Promise<void>;
574
595
 
575
596
  export declare const delimiterTokenTypes: Set<TokenType>;
576
597
 
@@ -599,7 +620,7 @@ export declare interface ExistsClauseCstNode extends CstNode {
599
620
  }
600
621
 
601
622
  /**
602
- * Grammar variant for the grounded rules RDFox returns.
623
+ * Grammar variant for the grounded rules the engine returns.
603
624
  *
604
625
  * Grounding substitutes an `AS` target with the value it computed, so
605
626
  * `BIND(?spend > 500 AS ?highSpend)` comes back as `BIND(901.22 > 500 AS true)`.
@@ -1113,7 +1134,7 @@ export declare function parseDatalogRuleWithIssues(ruleText: string): DatalogPar
1113
1134
  export declare function parseDatalogTermText(termText: string): DatalogTerm | undefined;
1114
1135
 
1115
1136
  /**
1116
- * Parse a grounded rule returned by RDFox, where `AS` targets have been
1137
+ * Parse a grounded rule returned by the engine, where `AS` targets have been
1117
1138
  * substituted with the values they evaluated to. Authored rules must go through
1118
1139
  * `parseDatalogRule` so that those substitutions stay invalid.
1119
1140
  */
@@ -1184,25 +1205,6 @@ export declare type PropertyAtom = {
1184
1205
 
1185
1206
  export declare const RBRACKET: TokenType;
1186
1207
 
1187
- /**
1188
- * RDFox Transaction Management Library
1189
- *
1190
- * This module provides side-effecty functions for managing RDFox connections and transactions
1191
- * via the RESTful API. It follows RDFox's connection-based transaction model where transactions
1192
- * are associated with data store connections.
1193
- *
1194
- * @see https://docs.oxfordsemantic.tech/apis.html#transactions-in-the-restful-api
1195
- */
1196
- export declare type RDFoxConnectionParams = {
1197
- rdfoxUrl: string;
1198
- datastoreName: string;
1199
- authorization: string;
1200
- };
1201
-
1202
- export declare type RDFoxTransactionParams = RDFoxConnectionParams & {
1203
- connectionId: string;
1204
- };
1205
-
1206
1208
  export declare const REGEX: TokenType;
1207
1209
 
1208
1210
  export declare type RegexFunctionCstChildren = {
@@ -1250,7 +1252,7 @@ export declare function resolveVariableTypes(evidence: VariableTypeEvidence[], l
1250
1252
  /**
1251
1253
  * Rollback a transaction on a connection
1252
1254
  */
1253
- export declare function rollbackTransaction(params: RDFoxTransactionParams): Promise<void>;
1255
+ export declare function rollbackTransaction(params: DatastoreTransactionParams): Promise<void>;
1254
1256
 
1255
1257
  export declare const ROUND: TokenType;
1256
1258
 
@@ -1571,7 +1573,7 @@ export declare type VariableTypeSource = "class" | PredicatePosition;
1571
1573
  /**
1572
1574
  * Verify that a rule produces the expected inference
1573
1575
  */
1574
- export declare function verifyRuleInference(rule: DatalogRule, rdfoxUrl: string, datastoreId: string, authorization: string, testTriple?: {
1576
+ export declare function verifyRuleInference(rule: DatalogRule, endpointUrl: string, datastoreId: string, authorization: string, testTriple?: {
1575
1577
  subject: string;
1576
1578
  predicate: string;
1577
1579
  object: string;
@@ -1582,7 +1584,7 @@ export declare const WHITESPACE: TokenType;
1582
1584
  /**
1583
1585
  * Execute a function within a transaction context, automatically handling commit/rollback
1584
1586
  */
1585
- export declare function withTransaction<T>(params: RDFoxConnectionParams, fn: (connectionId: string) => Promise<T>): Promise<T>;
1587
+ export declare function withTransaction<T>(params: DatastoreConnectionParams, fn: (connectionId: string) => Promise<T>): Promise<T>;
1586
1588
 
1587
1589
  export declare type XsdDatatypeLocalName = keyof typeof xsdDatatypes;
1588
1590
 
package/dist/index.js CHANGED
@@ -8,17 +8,17 @@ import { sparql11GeneratorBuilder as Mt } from "@traqula/generator-sparql-1-1";
8
8
  import { AstFactory as vr, lex as ze, completeGeneratorContext as Cr, gram as n, MinimalSparqlParser as Ir, sparqlCodepointEscape as Mr } from "@traqula/rules-sparql-1-1";
9
9
  import { createToken as c, Lexer as Bt, CstParser as Br, EOF as Fr } from "chevrotain";
10
10
  import { z as q } from "zod";
11
- const Mn = (e) => p(e).with({ type: "triple" }, () => !0).otherwise(() => !1), Bn = (e) => p(e).with({ type: "property" }, () => !0).otherwise(() => !1), Fn = (e) => p(e).with({ type: "class" }, () => !0).otherwise(() => !1), Pn = (e) => p(e).with({ type: "general" }, () => !0).otherwise(() => !1), I = (e) => p(e).with({ type: "variable" }, () => !0).otherwise(() => !1), kn = (e) => p(e).with({ type: "iri" }, () => !0).otherwise(() => !1), tt = (e) => p(e).with({ type: "literal" }, () => !0).otherwise(() => !1), Dn = (e) => p(e).with({ type: "blank" }, () => !0).otherwise(() => !1), $n = (e) => p(e).with({ type: "negation" }, () => !0).otherwise(() => !1), Gn = (e) => p(e).with({ type: "filter" }, () => !0).otherwise(() => !1), _n = (e) => p(e).with({ type: "bind" }, () => !0).otherwise(() => !1), Vn = (e) => p(e).with({ type: "aggregate" }, () => !0).otherwise(() => !1), jn = (e) => p(e).with({ type: "skolem" }, () => !0).otherwise(() => !1), qn = (e) => p(e).with({ type: "binary" }, () => !0).otherwise(() => !1), Xn = (e) => p(e).with({ type: "unary" }, () => !0).otherwise(() => !1), Hn = (e) => p(e).with({ type: "term" }, () => !0).otherwise(() => !1), Qn = (e) => p(e).with({ type: "function" }, () => !0).otherwise(() => !1), zn = (e) => p(e).with({ type: "triple" }, () => "triple").with({ type: "property" }, () => "property").with({ type: "class" }, () => "class").with({ type: "general" }, () => "general").exhaustive(), Kn = (e) => p(e).with({ type: "variable" }, () => "variable").with({ type: "iri" }, () => "iri").with({ type: "literal" }, () => "literal").with({ type: "blank" }, () => "blank").exhaustive(), Wn = (e) => p(e).with({ type: "binary" }, () => "binary").with({ type: "unary" }, () => "unary").with({ type: "term" }, () => "term").with({ type: "function" }, () => "function").with({ type: "in" }, () => "in").exhaustive(), Pr = (e) => p(e).with({ type: "triple" }, (t) => [t.subject, t.predicate, t.object].filter(I)).with({ type: "property" }, (t) => [t.subject, t.object].filter(I)).with({ type: "class" }, (t) => [t.instance].filter(I)).with({ type: "general" }, (t) => t.terms.filter(I)).exhaustive(), kr = (e) => {
11
+ const Mn = (e) => p(e).with({ type: "triple" }, () => !0).otherwise(() => !1), Bn = (e) => p(e).with({ type: "property" }, () => !0).otherwise(() => !1), Fn = (e) => p(e).with({ type: "class" }, () => !0).otherwise(() => !1), Pn = (e) => p(e).with({ type: "general" }, () => !0).otherwise(() => !1), I = (e) => p(e).with({ type: "variable" }, () => !0).otherwise(() => !1), kn = (e) => p(e).with({ type: "iri" }, () => !0).otherwise(() => !1), tt = (e) => p(e).with({ type: "literal" }, () => !0).otherwise(() => !1), $n = (e) => p(e).with({ type: "blank" }, () => !0).otherwise(() => !1), Dn = (e) => p(e).with({ type: "negation" }, () => !0).otherwise(() => !1), Gn = (e) => p(e).with({ type: "filter" }, () => !0).otherwise(() => !1), _n = (e) => p(e).with({ type: "bind" }, () => !0).otherwise(() => !1), Vn = (e) => p(e).with({ type: "aggregate" }, () => !0).otherwise(() => !1), jn = (e) => p(e).with({ type: "skolem" }, () => !0).otherwise(() => !1), qn = (e) => p(e).with({ type: "binary" }, () => !0).otherwise(() => !1), Xn = (e) => p(e).with({ type: "unary" }, () => !0).otherwise(() => !1), Hn = (e) => p(e).with({ type: "term" }, () => !0).otherwise(() => !1), Qn = (e) => p(e).with({ type: "function" }, () => !0).otherwise(() => !1), zn = (e) => p(e).with({ type: "triple" }, () => "triple").with({ type: "property" }, () => "property").with({ type: "class" }, () => "class").with({ type: "general" }, () => "general").exhaustive(), Kn = (e) => p(e).with({ type: "variable" }, () => "variable").with({ type: "iri" }, () => "iri").with({ type: "literal" }, () => "literal").with({ type: "blank" }, () => "blank").exhaustive(), Wn = (e) => p(e).with({ type: "binary" }, () => "binary").with({ type: "unary" }, () => "unary").with({ type: "term" }, () => "term").with({ type: "function" }, () => "function").with({ type: "in" }, () => "in").exhaustive(), Pr = (e) => p(e).with({ type: "triple" }, (t) => [t.subject, t.predicate, t.object].filter(I)).with({ type: "property" }, (t) => [t.subject, t.object].filter(I)).with({ type: "class" }, (t) => [t.instance].filter(I)).with({ type: "general" }, (t) => t.terms.filter(I)).exhaustive(), kr = (e) => {
12
12
  const t = Pr(e), r = "graph" in e ? e.graph : void 0;
13
13
  return r && I(r) ? [...t, r] : t;
14
- }, Yn = (e) => e.function, Zn = (e) => p(e).with(u.union("+", "-", "*", "/", "<", ">", "<=", ">="), () => !0).with(u.union("=", "!=", "||", "&&"), () => !1).exhaustive(), Jn = (e) => p(e).with(u.union("||", "&&", "=", "!=", "<", ">", "<=", ">="), () => !0).with(u.union("+", "-", "*", "/"), () => !1).exhaustive(), Ke = '[^\\s<>"{}|^`\\\\]', Dr = new RegExp(`^[a-z][a-z0-9+.-]*:${Ke}*$`, "i");
14
+ }, Yn = (e) => e.function, Zn = (e) => p(e).with(u.union("+", "-", "*", "/", "<", ">", "<=", ">="), () => !0).with(u.union("=", "!=", "||", "&&"), () => !1).exhaustive(), Jn = (e) => p(e).with(u.union("||", "&&", "=", "!=", "<", ">", "<=", ">="), () => !0).with(u.union("+", "-", "*", "/"), () => !1).exhaustive(), Ke = '[^\\s<>"{}|^`\\\\]', $r = new RegExp(`^[a-z][a-z0-9+.-]*:${Ke}*$`, "i");
15
15
  function ts(e) {
16
- return Dr.test(e);
16
+ return $r.test(e);
17
17
  }
18
18
  function We(e) {
19
19
  return e.includes("://");
20
20
  }
21
- const $r = /^(true|false)$/i, Gr = /^"(true|false)"\^\^<?\S*boolean>?$/i, St = "[eE][+-]?\\d+", _r = new RegExp(
21
+ const Dr = /^(true|false)$/i, Gr = /^"(true|false)"\^\^<?\S*boolean>?$/i, St = "[eE][+-]?\\d+", _r = new RegExp(
22
22
  `^[+-]?(?:\\d+\\.\\d*(?:${St})|\\d+\\.\\d+|\\.\\d+(?:${St})?|\\d+(?:${St})?)$`
23
23
  );
24
24
  function Rt(e) {
@@ -37,7 +37,7 @@ function Xr(e) {
37
37
  return h === "0" || r === "+" ? h : `${r}${h}`;
38
38
  }
39
39
  function es(e) {
40
- if ($r.test(e)) return e.toLowerCase() === "true";
40
+ if (Dr.test(e)) return e.toLowerCase() === "true";
41
41
  const t = e.match(Gr);
42
42
  if (t != null && t[1]) return t[1].toLowerCase() === "true";
43
43
  }
@@ -338,7 +338,7 @@ function H(e, t = {}) {
338
338
  ...ke(r.right, r.operator, "right", t)
339
339
  ]).with({ type: "unary" }, (r) => [C(r.operator), ...ii(r.operand, t)]).with({ type: "term" }, (r) => ni(r.term, t)).with({ type: "function" }, (r) => [
340
340
  C(`${r.name}(`),
341
- ...De(
341
+ ...$e(
342
342
  r.args.map((i) => H(i, t)),
343
343
  ", "
344
344
  ),
@@ -346,7 +346,7 @@ function H(e, t = {}) {
346
346
  ]).with({ type: "in" }, (r) => [
347
347
  ...H(r.expression, t),
348
348
  C(` ${r.negated ? "NOT IN" : "IN"} (`),
349
- ...De(
349
+ ...$e(
350
350
  r.list.map((i) => H(i, t)),
351
351
  ", "
352
352
  ),
@@ -375,7 +375,7 @@ function ni(e, t) {
375
375
  function ir(e) {
376
376
  return [C("("), ...e, C(")")];
377
377
  }
378
- function De(e, t) {
378
+ function $e(e, t) {
379
379
  return e.flatMap((r, i) => i === 0 ? r : [C(t), ...r]);
380
380
  }
381
381
  function si(e) {
@@ -403,17 +403,15 @@ function Ct(e) {
403
403
  ({ groundedOnTargets: t, bindings: r, atoms: i }) => t !== void 0 || ((r == null ? void 0 : r.some((s) => s.groundedTarget !== void 0)) ?? !1) || i.some(Ct)
404
404
  ).with({ type: "negation" }, ({ formulas: t }) => t.some(Ct)).with({ type: u.union("triple", "property", "class", "general", "filter", "skolem") }, () => !1).exhaustive();
405
405
  }
406
- const g = new vr(), m = g.gen(), $e = Mt.getRule("aggregate"), Ge = Mt.getRule("expression"), ui = {
407
- ...$e,
406
+ const g = new vr(), m = g.gen(), De = Mt.getRule("aggregate"), Ge = Mt.getRule("expression"), ui = {
407
+ ...De,
408
408
  gImpl: (e) => (t, r) => {
409
409
  const i = t.secondExpression;
410
410
  if (!i)
411
- return $e.gImpl(e)(t, r);
411
+ return De.gImpl(e)(t, r);
412
412
  const { PRINT_WORD: s, SUBRULE: a } = e, o = t.expression[0], l = r.astFactory;
413
413
  if (l.isWildcard(o))
414
- throw new Error(
415
- `RDFox aggregate ${t.aggregation.toUpperCase()} cannot combine * with a second expression.`
416
- );
414
+ throw new Error(`Aggregate ${t.aggregation.toUpperCase()} cannot combine * with a second expression.`);
417
415
  l.printFilter(t, () => {
418
416
  s(t.aggregation.toUpperCase(), "("), t.distinct && s("DISTINCT");
419
417
  }), a(Ge, o), l.printFilter(t, () => s(",")), a(Ge, i), l.printFilter(t, () => s(")"));
@@ -424,7 +422,7 @@ const g = new vr(), m = g.gen(), $e = Mt.getRule("aggregate"), Ge = Mt.getRule("
424
422
  return [t.LABEL.toLowerCase(), t.LABEL];
425
423
  })
426
424
  );
427
- function $(e) {
425
+ function D(e) {
428
426
  if (e.includes("://") || e.startsWith("urn:") || e.startsWith("mailto:") || e.startsWith("tel:") || e.startsWith("data:"))
429
427
  return g.termNamed(m, e);
430
428
  const r = e.indexOf(":");
@@ -436,11 +434,11 @@ function ot(e, t) {
436
434
  function di(e, t) {
437
435
  const { function: r, expression: i, secondExpression: s } = e, a = pi.has(r), o = s !== void 0;
438
436
  if (a && s == null)
439
- throw new Error(`RDFox aggregate ${r} requires two expressions.`);
437
+ throw new Error(`Aggregate ${r} requires two expressions.`);
440
438
  if (a && i === "*")
441
- throw new Error(`RDFox aggregate ${r} cannot use * as an expression.`);
439
+ throw new Error(`Aggregate ${r} cannot use * as an expression.`);
442
440
  if (!a && o)
443
- throw new Error(`RDFox aggregate ${r} accepts only one expression.`);
441
+ throw new Error(`Aggregate ${r} accepts only one expression.`);
444
442
  const l = i === "*" ? g.wildcard(m) : O(i, t), E = g.aggregate(
445
443
  r.toLowerCase(),
446
444
  e.distinct || !1,
@@ -453,7 +451,7 @@ function di(e, t) {
453
451
  secondExpression: O(s, t)
454
452
  } : E;
455
453
  }
456
- function D(e, t, r = void 0) {
454
+ function $(e, t, r = void 0) {
457
455
  return p(r).with("predicate", () => {
458
456
  if (e.type !== "variable" && e.type !== "iri")
459
457
  throw new Error(`Invalid predicate term: ${e.type}. RDF predicates cannot be ${e.type} nodes.`);
@@ -464,11 +462,11 @@ function D(e, t, r = void 0) {
464
462
  if (e.type !== "variable" && e.type !== "iri")
465
463
  throw new Error(`Invalid graph name term: ${e.type}. Graph names can only be variables or IRIs.`);
466
464
  }).with(u.nullish, () => {
467
- }).exhaustive(), r === "predicate" && e.type === "iri" && e.value === "a" ? $("rdf:type") : p(e).with({ type: "variable" }, (i) => (t.add(i.name), g.termVariable(i.name, m))).with({ type: "iri", prefixed: !0 }, (i) => $(i.value)).with({ type: "iri", prefixed: !1 }, (i) => g.termNamed(m, i.value)).with(
465
+ }).exhaustive(), r === "predicate" && e.type === "iri" && e.value === "a" ? D("rdf:type") : p(e).with({ type: "variable" }, (i) => (t.add(i.name), g.termVariable(i.name, m))).with({ type: "iri", prefixed: !0 }, (i) => D(i.value)).with({ type: "iri", prefixed: !1 }, (i) => g.termNamed(m, i.value)).with(
468
466
  { type: "literal", language: u.string },
469
467
  (i) => g.termLiteral(m, i.value, i.language)
470
468
  ).with({ type: "literal", datatype: u.string }, (i) => {
471
- const s = $(i.datatype);
469
+ const s = D(i.datatype);
472
470
  return g.termLiteral(m, i.value, s);
473
471
  }).with({ type: "literal" }, (i) => g.termLiteral(m, i.value)).with({ type: "blank" }, (i) => g.termBlank(i.label, m)).exhaustive();
474
472
  }
@@ -476,7 +474,7 @@ function Ei(e, t) {
476
474
  const r = e.args.map((a) => O(a, t)), i = hi.get(e.name.toLowerCase());
477
475
  if (i)
478
476
  return ot(i.toLowerCase(), r);
479
- const s = $(e.name);
477
+ const s = D(e.name);
480
478
  return g.expressionFunctionCall(s, r, !1, m);
481
479
  }
482
480
  function O(e, t) {
@@ -489,7 +487,7 @@ function O(e, t) {
489
487
  ).with(
490
488
  { type: "unary" },
491
489
  (r) => ot(r.operator, [O(r.operand, t)])
492
- ).with({ type: "term" }, (r) => D(r.term, t, "expression")).with({ type: "function" }, (r) => Ei(r, t)).with(
490
+ ).with({ type: "term" }, (r) => $(r.term, t, "expression")).with({ type: "function" }, (r) => Ei(r, t)).with(
493
491
  { type: "in" },
494
492
  (r) => ot(r.negated ? "notin" : "in", [
495
493
  O(r.expression, t),
@@ -501,16 +499,16 @@ function Pt(e, t) {
501
499
  const r = p(e).with(
502
500
  { type: "triple" },
503
501
  (i) => g.triple(
504
- D(i.subject, t),
505
- D(i.predicate, t, "predicate"),
506
- D(i.object, t)
502
+ $(i.subject, t),
503
+ $(i.predicate, t, "predicate"),
504
+ $(i.object, t)
507
505
  )
508
506
  ).with({ type: "property" }, (i) => {
509
- const s = $(i.predicate);
510
- return g.triple(D(i.subject, t), s, D(i.object, t));
507
+ const s = D(i.predicate);
508
+ return g.triple($(i.subject, t), s, $(i.object, t));
511
509
  }).with({ type: "class" }, (i) => {
512
- const s = $("rdf:type"), a = $(i.className);
513
- return g.triple(D(i.instance, t), s, a);
510
+ const s = D("rdf:type"), a = D(i.className);
511
+ return g.triple($(i.instance, t), s, a);
514
512
  }).with({ type: "general" }, () => {
515
513
  throw new Error("General formulas are not supported as triple patterns.");
516
514
  }).exhaustive();
@@ -518,7 +516,7 @@ function Pt(e, t) {
518
516
  if ("graph" in e && e.graph) {
519
517
  const i = g.patternBgp([r], m);
520
518
  return { graph: g.patternGraph(
521
- D(e.graph, t, "graph"),
519
+ $(e.graph, t, "graph"),
522
520
  [i],
523
521
  m
524
522
  ) };
@@ -555,7 +553,7 @@ function mi(e, t) {
555
553
  const { triples: r, filters: i, binds: s, graphPatterns: a } = gi(e.atoms, t), o = e.onVars || [], l = o.map((h) => (t.add(h), g.termVariable(h, m))), E = [], y = [];
556
554
  return (S = e.bindings) == null || S.forEach((h) => {
557
555
  if (t.add(h.variable), h.expression === void 0) {
558
- const W = h.function !== void 0 ? `RDFox aggregate ${h.function}` : "Expression-only aggregate binding";
556
+ const W = h.function !== void 0 ? `Aggregate ${h.function}` : "Expression-only aggregate binding";
559
557
  throw new Error(`${W} requires an expression.`);
560
558
  }
561
559
  if (h.function === void 0 && h.secondExpression !== void 0)
@@ -643,7 +641,7 @@ function yi(e, t) {
643
641
  variables: S
644
642
  };
645
643
  }
646
- const kt = c({ name: "RULE_ARROW", pattern: /:-/ }), lt = c({ name: "NOT", pattern: /NOT/ }), Dt = c({ name: "EXISTS", pattern: /EXISTS?/ }), Z = c({ name: "IN", pattern: /IN/ }), $t = c({ name: "FILTER", pattern: /FILTER/ }), z = c({ name: "BIND", pattern: /BIND/ }), K = c({ name: "AS", pattern: /AS/ }), wt = c({ name: "AGGREGATE", pattern: /AGGREGATE/ }), At = c({ name: "ON", pattern: /ON/ }), Gt = c({ name: "COUNT", pattern: /COUNT/ }), _t = c({ name: "MIN", pattern: /MIN/ }), Vt = c({ name: "MAX", pattern: /MAX/ }), jt = c({ name: "SUM", pattern: /SUM/ }), qt = c({ name: "MUL", pattern: /MUL/ }), Xt = c({ name: "AVG", pattern: /AVG/ }), Ht = c({ name: "COUNT_MIN", pattern: /COUNT_MIN/ }), Qt = c({ name: "COUNT_MAX", pattern: /COUNT_MAX/ }), zt = c({ name: "MIN_ARGMIN", pattern: /MIN_ARGMIN/ }), Kt = c({ name: "MAX_ARGMIN", pattern: /MAX_ARGMIN/ }), Wt = c({ name: "MIN_ARGMAX", pattern: /MIN_ARGMAX/ }), Yt = c({ name: "MAX_ARGMAX", pattern: /MAX_ARGMAX/ }), ut = c({ name: "DISTINCT", pattern: /DISTINCT/ }), Zt = c({ name: "CONCAT", pattern: /CONCAT/ }), Jt = c({ name: "STR", pattern: /STR/ }), te = c({ name: "IF", pattern: /IF/ }), ee = c({ name: "IRI", pattern: /IRI/ }), ct = c({ name: "SKOLEM", pattern: /SKOLEM/ }), re = c({ name: "ROUND", pattern: /ROUND/ }), ie = c({ name: "REGEX", pattern: /REGEX/ }), ne = c({ name: "TRUE", pattern: /true/ }), se = c({ name: "FALSE", pattern: /false/ }), ae = c({ name: "EQUALS", pattern: /=/ }), oe = c({ name: "NOT_EQUALS", pattern: /!=/ }), le = c({ name: "LESS_THAN", pattern: /</ }), ue = c({ name: "LESS_THAN_OR_EQUAL", pattern: /<=/ }), ce = c({ name: "GREATER_THAN", pattern: />/ }), pe = c({ name: "GREATER_THAN_OR_EQUAL", pattern: />=/ }), he = c({ name: "AND", pattern: /&&/ }), de = c({ name: "OR", pattern: /\|\|/ }), pt = c({ name: "PLUS", pattern: /\+/ }), ht = c({ name: "MINUS", pattern: /-/ }), dt = c({ name: "STAR", pattern: /\*/ }), Ee = c({ name: "SLASH", pattern: /\// }), fe = c({ name: "EXCLAMATION", pattern: /!/ }), ge = c({ name: "DOT", pattern: /\./ }), N = c({ name: "COMMA", pattern: /,/ }), U = c({ name: "LPAREN", pattern: /\(/ }), w = c({ name: "RPAREN", pattern: /\)/ }), Et = c({ name: "LBRACKET", pattern: /\[/ }), ft = c({ name: "RBRACKET", pattern: /\]/ }), sr = c({ name: "AT", pattern: /@/ }), gt = c({ name: "HAT", pattern: /\^/ }), ar = c({ name: "COLON", pattern: /:/ }), b = c({ name: "VARIABLE", pattern: /\?[a-zA-Z_][a-zA-Z0-9_]*/ }), me = c({ name: "IRI_REF", pattern: new RegExp(`<${Ke}*>`) }), ye = c({ name: "INTERNAL_FUNCTION", pattern: /<internal:[^>]+>/ }), et = c({ name: "BLANK_NODE", pattern: /_:[\w](?:[\w.-]*[\w-])?/ }), Le = "%[0-9a-fA-F]{2}|\\\\[-_~.!$&'()*+,;=/?#@%]", Li = `(?:[\\w:]|${Le})`, Ui = `(?:[\\w:.-]|${Le})`, wi = `(?:[\\w:-]|${Le})`, or = `${Li}(?:${Ui}*${wi})?`, st = c({
644
+ const kt = c({ name: "RULE_ARROW", pattern: /:-/ }), lt = c({ name: "NOT", pattern: /NOT/ }), $t = c({ name: "EXISTS", pattern: /EXISTS?/ }), Z = c({ name: "IN", pattern: /IN/ }), Dt = c({ name: "FILTER", pattern: /FILTER/ }), z = c({ name: "BIND", pattern: /BIND/ }), K = c({ name: "AS", pattern: /AS/ }), wt = c({ name: "AGGREGATE", pattern: /AGGREGATE/ }), At = c({ name: "ON", pattern: /ON/ }), Gt = c({ name: "COUNT", pattern: /COUNT/ }), _t = c({ name: "MIN", pattern: /MIN/ }), Vt = c({ name: "MAX", pattern: /MAX/ }), jt = c({ name: "SUM", pattern: /SUM/ }), qt = c({ name: "MUL", pattern: /MUL/ }), Xt = c({ name: "AVG", pattern: /AVG/ }), Ht = c({ name: "COUNT_MIN", pattern: /COUNT_MIN/ }), Qt = c({ name: "COUNT_MAX", pattern: /COUNT_MAX/ }), zt = c({ name: "MIN_ARGMIN", pattern: /MIN_ARGMIN/ }), Kt = c({ name: "MAX_ARGMIN", pattern: /MAX_ARGMIN/ }), Wt = c({ name: "MIN_ARGMAX", pattern: /MIN_ARGMAX/ }), Yt = c({ name: "MAX_ARGMAX", pattern: /MAX_ARGMAX/ }), ut = c({ name: "DISTINCT", pattern: /DISTINCT/ }), Zt = c({ name: "CONCAT", pattern: /CONCAT/ }), Jt = c({ name: "STR", pattern: /STR/ }), te = c({ name: "IF", pattern: /IF/ }), ee = c({ name: "IRI", pattern: /IRI/ }), ct = c({ name: "SKOLEM", pattern: /SKOLEM/ }), re = c({ name: "ROUND", pattern: /ROUND/ }), ie = c({ name: "REGEX", pattern: /REGEX/ }), ne = c({ name: "TRUE", pattern: /true/ }), se = c({ name: "FALSE", pattern: /false/ }), ae = c({ name: "EQUALS", pattern: /=/ }), oe = c({ name: "NOT_EQUALS", pattern: /!=/ }), le = c({ name: "LESS_THAN", pattern: /</ }), ue = c({ name: "LESS_THAN_OR_EQUAL", pattern: /<=/ }), ce = c({ name: "GREATER_THAN", pattern: />/ }), pe = c({ name: "GREATER_THAN_OR_EQUAL", pattern: />=/ }), he = c({ name: "AND", pattern: /&&/ }), de = c({ name: "OR", pattern: /\|\|/ }), pt = c({ name: "PLUS", pattern: /\+/ }), ht = c({ name: "MINUS", pattern: /-/ }), dt = c({ name: "STAR", pattern: /\*/ }), Ee = c({ name: "SLASH", pattern: /\// }), fe = c({ name: "EXCLAMATION", pattern: /!/ }), ge = c({ name: "DOT", pattern: /\./ }), N = c({ name: "COMMA", pattern: /,/ }), U = c({ name: "LPAREN", pattern: /\(/ }), w = c({ name: "RPAREN", pattern: /\)/ }), Et = c({ name: "LBRACKET", pattern: /\[/ }), ft = c({ name: "RBRACKET", pattern: /\]/ }), sr = c({ name: "AT", pattern: /@/ }), gt = c({ name: "HAT", pattern: /\^/ }), ar = c({ name: "COLON", pattern: /:/ }), b = c({ name: "VARIABLE", pattern: /\?[a-zA-Z_][a-zA-Z0-9_]*/ }), me = c({ name: "IRI_REF", pattern: new RegExp(`<${Ke}*>`) }), ye = c({ name: "INTERNAL_FUNCTION", pattern: /<internal:[^>]+>/ }), et = c({ name: "BLANK_NODE", pattern: /_:[\w](?:[\w.-]*[\w-])?/ }), Le = "%[0-9a-fA-F]{2}|\\\\[-_~.!$&'()*+,;=/?#@%]", Li = `(?:[\\w:]|${Le})`, Ui = `(?:[\\w:.-]|${Le})`, wi = `(?:[\\w:-]|${Le})`, or = `${Li}(?:${Ui}*${wi})?`, st = c({
647
645
  name: "PREFIXED_NAME",
648
646
  pattern: new RegExp(`[a-zA-Z_][\\w]*:${or}`)
649
647
  }), Tt = c({ name: "PREFIX_ONLY", pattern: /[a-zA-Z_][\w]*:/ }), Ue = c({
@@ -684,9 +682,9 @@ const kt = c({ name: "RULE_ARROW", pattern: /:-/ }), lt = c({ name: "NOT", patte
684
682
  gt,
685
683
  // Keywords (before identifiers)
686
684
  lt,
687
- Dt,
688
- Z,
689
685
  $t,
686
+ Z,
687
+ Dt,
690
688
  z,
691
689
  K,
692
690
  wt,
@@ -746,7 +744,7 @@ const kt = c({ name: "RULE_ARROW", pattern: /:-/ }), lt = c({ name: "NOT", patte
746
744
  ft,
747
745
  sr,
748
746
  ar
749
- ], Si = /* @__PURE__ */ new Set([lt, Dt, Z, $t, z, K, wt, At, ut]), Ni = /* @__PURE__ */ new Set([
747
+ ], Si = /* @__PURE__ */ new Set([lt, $t, Z, Dt, z, K, wt, At, ut]), Ni = /* @__PURE__ */ new Set([
750
748
  Gt,
751
749
  _t,
752
750
  Vt,
@@ -977,7 +975,7 @@ class xe extends Br {
977
975
  }));
978
976
  // ExistsClause := 'EXISTS' variable (',' variable)* 'IN'
979
977
  d(this, "existsClause", this.RULE("existsClause", () => {
980
- this.CONSUME(Dt), this.CONSUME(b), this.MANY(() => {
978
+ this.CONSUME($t), this.CONSUME(b), this.MANY(() => {
981
979
  this.CONSUME(N), this.CONSUME2(b);
982
980
  }), this.CONSUME(Z);
983
981
  }));
@@ -1003,7 +1001,7 @@ class xe extends Br {
1003
1001
  }));
1004
1002
  // FilterAtom := 'FILTER' '(' Expression ')'
1005
1003
  d(this, "filterAtom", this.RULE("filterAtom", () => {
1006
- this.CONSUME($t), this.CONSUME(U), this.SUBRULE(this.expression), this.CONSUME(w);
1004
+ this.CONSUME(Dt), this.CONSUME(U), this.SUBRULE(this.expression), this.CONSUME(w);
1007
1005
  }));
1008
1006
  // BindAtom := 'BIND' '(' Expression 'AS' variable ')'
1009
1007
  d(this, "bindAtom", this.RULE("bindAtom", () => {
@@ -1266,7 +1264,7 @@ class vi extends xe {
1266
1264
  this.CONSUME(z), this.CONSUME(U), this.SUBRULE(this.expression), this.CONSUME(K), this.variableOrGroundedTarget(), this.CONSUME(w);
1267
1265
  }));
1268
1266
  // Aggregate := 'AGGREGATE' '(' AtomList? OnClause? AggregateBind* ')'
1269
- // atomList is optional so RDFox-emitted atom-free forms parse; empty
1267
+ // atomList is optional so engine-emitted atom-free forms parse; empty
1270
1268
  // `AGGREGATE()` / `AGGREGATE(ON ?x)` are rejected after parse (visitor).
1271
1269
  d(this, "expandedAggregate", this.OVERRIDE_RULE("aggregate", () => {
1272
1270
  this.CONSUME(wt), this.CONSUME(U), this.OPTION(() => {
@@ -1363,7 +1361,7 @@ async function Us(e, t, r, i, s) {
1363
1361
  verified: !1,
1364
1362
  error: "Could not generate test triple from rule head"
1365
1363
  };
1366
- const l = Bi(e), E = await Di(l, t, r, i);
1364
+ const l = Bi(e), E = await $i(l, t, r, i);
1367
1365
  if (E)
1368
1366
  return {
1369
1367
  verified: !1,
@@ -1371,7 +1369,7 @@ async function Us(e, t, r, i, s) {
1371
1369
  candidateQuery: l,
1372
1370
  error: E
1373
1371
  };
1374
- const y = $i(o), S = new URL(`datastores/${r}/sparql`, t), h = await fetch(S.toString(), {
1372
+ const y = Di(o), S = new URL(`datastores/${r}/sparql`, t), h = await fetch(S.toString(), {
1375
1373
  method: "POST",
1376
1374
  headers: {
1377
1375
  Authorization: i,
@@ -1396,7 +1394,7 @@ async function Us(e, t, r, i, s) {
1396
1394
  };
1397
1395
  }
1398
1396
  }
1399
- async function Di(e, t, r, i) {
1397
+ async function $i(e, t, r, i) {
1400
1398
  try {
1401
1399
  const s = new URL(`datastores/${r}/sparql`, t), a = await fetch(s.toString(), {
1402
1400
  method: "POST",
@@ -1421,7 +1419,7 @@ async function Di(e, t, r, i) {
1421
1419
  return `Candidate query failed: ${s instanceof Error ? s.message : "Unknown error"}`;
1422
1420
  }
1423
1421
  }
1424
- function $i(e) {
1422
+ function Di(e) {
1425
1423
  return `
1426
1424
  ASK WHERE {
1427
1425
  ${e.subject} ${e.predicate} ${e.object} .
@@ -1825,7 +1823,7 @@ function Ts(e) {
1825
1823
  } : { allowed: !0, operationTypes: r.map((o) => o.subType).filter(_e) };
1826
1824
  }
1827
1825
  async function pn(e) {
1828
- const { rdfoxUrl: t, datastoreName: r, authorization: i } = e, s = new URL(`datastores/${r}/connections`, t), a = await fetch(s.toString(), {
1826
+ const { endpointUrl: t, datastoreName: r, authorization: i } = e, s = new URL(`datastores/${r}/connections`, t), a = await fetch(s.toString(), {
1829
1827
  method: "POST",
1830
1828
  headers: {
1831
1829
  Authorization: i
@@ -1841,7 +1839,7 @@ async function pn(e) {
1841
1839
  return o.split("/").pop();
1842
1840
  }
1843
1841
  async function hn(e) {
1844
- const { rdfoxUrl: t, datastoreName: r, connectionId: i, authorization: s } = e, a = new URL(`datastores/${r}/connections/${i}/transaction`, t);
1842
+ const { endpointUrl: t, datastoreName: r, connectionId: i, authorization: s } = e, a = new URL(`datastores/${r}/connections/${i}/transaction`, t);
1845
1843
  a.searchParams.set("operation", "begin-read-write-transaction");
1846
1844
  const o = await fetch(a.toString(), {
1847
1845
  method: "PATCH",
@@ -1855,7 +1853,7 @@ async function hn(e) {
1855
1853
  }
1856
1854
  }
1857
1855
  async function dn(e) {
1858
- const { rdfoxUrl: t, datastoreName: r, connectionId: i, authorization: s } = e, a = new URL(`datastores/${r}/connections/${i}/transaction`, t);
1856
+ const { endpointUrl: t, datastoreName: r, connectionId: i, authorization: s } = e, a = new URL(`datastores/${r}/connections/${i}/transaction`, t);
1859
1857
  a.searchParams.set("operation", "commit-transaction");
1860
1858
  const o = await fetch(a.toString(), {
1861
1859
  method: "PATCH",
@@ -1869,7 +1867,7 @@ async function dn(e) {
1869
1867
  }
1870
1868
  }
1871
1869
  async function En(e) {
1872
- const { rdfoxUrl: t, datastoreName: r, connectionId: i, authorization: s } = e, a = new URL(`datastores/${r}/connections/${i}/transaction`, t);
1870
+ const { endpointUrl: t, datastoreName: r, connectionId: i, authorization: s } = e, a = new URL(`datastores/${r}/connections/${i}/transaction`, t);
1873
1871
  a.searchParams.set("operation", "rollback-transaction");
1874
1872
  const o = await fetch(a.toString(), {
1875
1873
  method: "PATCH",
@@ -1883,7 +1881,7 @@ async function En(e) {
1883
1881
  }
1884
1882
  }
1885
1883
  async function fn(e) {
1886
- const { rdfoxUrl: t, datastoreName: r, connectionId: i, authorization: s } = e, a = new URL(`datastores/${r}/connections/${i}`, t), o = await fetch(a.toString(), {
1884
+ const { endpointUrl: t, datastoreName: r, connectionId: i, authorization: s } = e, a = new URL(`datastores/${r}/connections/${i}`, t), o = await fetch(a.toString(), {
1887
1885
  method: "DELETE",
1888
1886
  headers: {
1889
1887
  Authorization: s
@@ -2179,7 +2177,7 @@ class Ln extends mn {
2179
2177
  ...this.asTarget(t, "Bind missing variable")
2180
2178
  };
2181
2179
  }
2182
- // The expanded grammar accepts a value where a variable belongs, because RDFox
2180
+ // The expanded grammar accepts a value where a variable belongs, because the engine
2183
2181
  // substitutes the `AS` target when it grounds a rule.
2184
2182
  asTarget(t, r) {
2185
2183
  var a;
@@ -2211,7 +2209,7 @@ class Ln extends mn {
2211
2209
  bindings: s
2212
2210
  };
2213
2211
  }
2214
- // RDFox grounds every grouping variable or none of them, so listing the
2212
+ // The engine grounds every grouping variable or none of them, so listing the
2215
2213
  // variables ahead of any substituted values preserves source order in practice.
2216
2214
  onClause(t) {
2217
2215
  var a, o;
@@ -2710,10 +2708,10 @@ export {
2710
2708
  xe as DatalogParser,
2711
2709
  ae as EQUALS,
2712
2710
  fe as EXCLAMATION,
2713
- Dt as EXISTS,
2711
+ $t as EXISTS,
2714
2712
  vi as ExpandedDatalogParser,
2715
2713
  se as FALSE,
2716
- $t as FILTER,
2714
+ Dt as FILTER,
2717
2715
  ce as GREATER_THAN,
2718
2716
  pe as GREATER_THAN_OR_EQUAL,
2719
2717
  gt as HAT,
@@ -2768,6 +2766,7 @@ export {
2768
2766
  ei as binaryOperandNeedsParentheses,
2769
2767
  Ri as booleanLiteralTokenTypes,
2770
2768
  Ni as builtinFunctionTokenTypes,
2769
+ Qe as canonicalRuleText,
2771
2770
  Ze as classAssertionFromAtom,
2772
2771
  Ns as collectVariableTypeEvidence,
2773
2772
  dn as commitTransaction,
@@ -2799,7 +2798,7 @@ export {
2799
2798
  ns as isBareNumericLiteral,
2800
2799
  qn as isBinaryExpression,
2801
2800
  _n as isBindFormula,
2802
- Dn as isBlankNodeTerm,
2801
+ $n as isBlankNodeTerm,
2803
2802
  er as isBooleanLiteral,
2804
2803
  Fn as isClassAtom,
2805
2804
  rs as isComparisonOperator,
@@ -2813,7 +2812,7 @@ export {
2813
2812
  kn as isIriTerm,
2814
2813
  tt as isLiteralTerm,
2815
2814
  Jn as isLogicalOperator,
2816
- $n as isNegationFormula,
2815
+ Dn as isNegationFormula,
2817
2816
  Q as isNumericLiteral,
2818
2817
  ss as isNumericLiteralTerm,
2819
2818
  Zn as isNumericOperator,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@manta-eu/datalog-parser",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "RDFox Datalog parser and AST builder with inference verification",
5
5
  "license": "MIT",
6
6
  "type": "module",