eyeling 1.24.1 → 1.24.3

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.
Files changed (77) hide show
  1. package/HANDBOOK.md +134 -0
  2. package/dist/browser/eyeling.browser.js +454 -22
  3. package/eyeling.js +454 -22
  4. package/index.js +2 -0
  5. package/lib/cli.js +27 -10
  6. package/lib/engine.js +17 -7
  7. package/lib/lexer.js +295 -2
  8. package/lib/multisource.js +9 -2
  9. package/lib/printing.js +106 -1
  10. package/package.json +1 -1
  11. package/see/README.md +4 -0
  12. package/see/examples/_see.js +33 -2
  13. package/see/examples/age.js +27 -1
  14. package/see/examples/annotation.js +27 -1
  15. package/see/examples/backward.js +27 -1
  16. package/see/examples/backward_recursion.js +27 -1
  17. package/see/examples/bayes_diagnosis.js +27 -1
  18. package/see/examples/bayes_therapy.js +27 -1
  19. package/see/examples/bmi.js +27 -1
  20. package/see/examples/builtin_coverage.js +27 -1
  21. package/see/examples/collection.js +27 -1
  22. package/see/examples/complex.js +27 -1
  23. package/see/examples/complex_matrix_stability.js +27 -1
  24. package/see/examples/composition_of_injective_functions_is_injective.js +27 -1
  25. package/see/examples/control_system.js +27 -1
  26. package/see/examples/crypto_builtins_tests.js +27 -1
  27. package/see/examples/delfour.js +27 -1
  28. package/see/examples/digital_product_passport.js +27 -1
  29. package/see/examples/dijkstra.js +27 -1
  30. package/see/examples/dijkstra_risk_path.js +27 -1
  31. package/see/examples/doc/rdf_dataset.md +26 -0
  32. package/see/examples/doc/triple_terms.md +26 -0
  33. package/see/examples/dog.js +27 -1
  34. package/see/examples/eco_route_insight.js +27 -1
  35. package/see/examples/equals.js +27 -1
  36. package/see/examples/equivalence_classes_overlap_implies_same_class.js +27 -1
  37. package/see/examples/euler_identity.js +27 -1
  38. package/see/examples/ev_roundtrip_planner.js +27 -1
  39. package/see/examples/existential_rule.js +27 -1
  40. package/see/examples/expression_eval.js +27 -1
  41. package/see/examples/family_cousins.js +27 -1
  42. package/see/examples/fastpow.js +27 -1
  43. package/see/examples/fibonacci.js +27 -1
  44. package/see/examples/french_cities.js +27 -1
  45. package/see/examples/fundamental_theorem_arithmetic.js +27 -1
  46. package/see/examples/genetic_knapsack_selection.js +27 -1
  47. package/see/examples/goldbach_1000.js +27 -1
  48. package/see/examples/good_cobbler.js +27 -1
  49. package/see/examples/gps.js +27 -1
  50. package/see/examples/gray_code_counter.js +27 -1
  51. package/see/examples/greatest_lower_bound_uniqueness.js +27 -1
  52. package/see/examples/group_inverse_uniqueness.js +27 -1
  53. package/see/examples/hadamard_approx.js +27 -1
  54. package/see/examples/hanoi.js +27 -1
  55. package/see/examples/input/rdf_dataset.trig +34 -0
  56. package/see/examples/input/triple_terms.trig +28 -0
  57. package/see/examples/n3/rdf_dataset.n3 +34 -0
  58. package/see/examples/n3/triple_terms.n3 +23 -0
  59. package/see/examples/odrl_dpv_risk_ranked.js +27 -1
  60. package/see/examples/output/rdf_dataset.md +54 -0
  61. package/see/examples/output/triple_terms.md +53 -0
  62. package/see/examples/path_discovery.js +27 -1
  63. package/see/examples/rc_discharge_envelope.js +27 -1
  64. package/see/examples/rdf_dataset.js +1512 -0
  65. package/see/examples/rdf_message_flow.js +27 -1
  66. package/see/examples/rdf_messages.js +27 -1
  67. package/see/examples/school_placement_audit.js +27 -1
  68. package/see/examples/smoke_arithmetic.js +27 -1
  69. package/see/examples/socrates.js +27 -1
  70. package/see/examples/triple_terms.js +1442 -0
  71. package/see/examples/wind_turbine.js +27 -1
  72. package/see/examples/witch.js +27 -1
  73. package/see/see.js +101 -4
  74. package/test/api.test.js +86 -0
  75. package/test/see.test.js +0 -0
  76. package/tools/bundle.js +0 -0
  77. package/tools/n3gen.js +0 -0
package/eyeling.js CHANGED
@@ -4547,6 +4547,7 @@ function main() {
4547
4547
  ` -e, --enforce-https Rewrite http:// IRIs to https:// for log dereferencing builtins.\n` +
4548
4548
  ` -h, --help Show this help and exit.\n` +
4549
4549
  ` -p, --proof-comments Enable proof explanations.\n` +
4550
+ ` -r, --rdf Enable RDF/TriG input/output compatibility.\n` +
4550
4551
  ` -s, --super-restricted Disable all builtins except => and <=.\n` +
4551
4552
  ` -t, --stream Stream derived triples as soon as they are derived.\n` +
4552
4553
  ` -v, --version Print version and exit.\n`;
@@ -4588,6 +4589,7 @@ function main() {
4588
4589
 
4589
4590
  const showAst = argv.includes('--ast') || argv.includes('-a');
4590
4591
  const streamMode = argv.includes('--stream') || argv.includes('-t');
4592
+ const rdfMode = argv.includes('--rdf') || argv.includes('-r');
4591
4593
 
4592
4594
  // --enforce-https: rewrite http:// -> https:// for log dereferencing builtins
4593
4595
  if (argv.includes('--enforce-https') || argv.includes('-e')) {
@@ -4650,6 +4652,7 @@ function main() {
4650
4652
  label: sourceLabel,
4651
4653
  collectUsedPrefixes: true,
4652
4654
  keepSourceArtifacts: false,
4655
+ rdf: rdfMode,
4653
4656
  }),
4654
4657
  );
4655
4658
  } catch (e) {
@@ -4762,10 +4765,10 @@ function main() {
4762
4765
  (df) => {
4763
4766
  if (engine.getProofCommentsEnabled()) {
4764
4767
  engine.printExplanation(df, outPrefixes);
4765
- console.log(engine.tripleToN3(df.fact, outPrefixes));
4768
+ console.log(rdfMode ? engine.tripleToRdfCompatible(df.fact, outPrefixes) : engine.tripleToN3(df.fact, outPrefixes));
4766
4769
  console.log();
4767
4770
  } else {
4768
- console.log(engine.tripleToN3(df.fact, outPrefixes));
4771
+ console.log(rdfMode ? engine.tripleToRdfCompatible(df.fact, outPrefixes) : engine.tripleToN3(df.fact, outPrefixes));
4769
4772
  }
4770
4773
  },
4771
4774
  { captureExplanations: engine.getProofCommentsEnabled(), prefixes: outPrefixes },
@@ -4801,7 +4804,24 @@ function main() {
4801
4804
  return;
4802
4805
  }
4803
4806
 
4804
- const usedPrefixes = prefixes.prefixesUsedForOutput(outTriples);
4807
+ let bodyText = '';
4808
+ if (rdfMode && !engine.getProofCommentsEnabled()) {
4809
+ bodyText = outTriples.map((tr) => engine.tripleToRdfCompatible(tr, prefixes)).join('\n');
4810
+ } else if (hasQueries && !engine.getProofCommentsEnabled()) {
4811
+ // In log:query mode, when proof comments are disabled, pretty-print blank-node
4812
+ // shaped outputs as Turtle property lists ("[ ... ] .") for readability.
4813
+ bodyText = engine.prettyPrintQueryTriples(outTriples, prefixes);
4814
+ }
4815
+
4816
+ let usedPrefixes = prefixes.prefixesUsedForOutput(outTriples);
4817
+ if (rdfMode && bodyText) {
4818
+ usedPrefixes = usedPrefixes.filter(([pfx]) => pfx === '' || bodyText.includes(pfx + ':'));
4819
+ }
4820
+
4821
+ if (rdfMode && bodyText.includes('<<(')) {
4822
+ console.log('VERSION "1.2"');
4823
+ console.log();
4824
+ }
4805
4825
 
4806
4826
  for (const [pfx, base] of usedPrefixes) {
4807
4827
  if (pfx === '') console.log(`@prefix : <${base}> .`);
@@ -4809,21 +4829,18 @@ function main() {
4809
4829
  }
4810
4830
  if (outTriples.length && usedPrefixes.length) console.log();
4811
4831
 
4812
- // In log:query mode, when proof comments are disabled, pretty-print blank-node
4813
- // shaped outputs as Turtle property lists ("[ ... ] .") for readability.
4814
- if (hasQueries && !engine.getProofCommentsEnabled()) {
4815
- const s = engine.prettyPrintQueryTriples(outTriples, prefixes);
4816
- if (s) process.stdout.write(String(s).replace(/\s*$/g, '') + '\n');
4832
+ if (bodyText) {
4833
+ process.stdout.write(String(bodyText).replace(/\s*$/g, '') + '\n');
4817
4834
  return;
4818
4835
  }
4819
4836
 
4820
4837
  for (const df of outDerived) {
4821
4838
  if (engine.getProofCommentsEnabled()) {
4822
4839
  engine.printExplanation(df, prefixes);
4823
- console.log(engine.tripleToN3(df.fact, prefixes));
4840
+ console.log(rdfMode ? engine.tripleToRdfCompatible(df.fact, prefixes) : engine.tripleToN3(df.fact, prefixes));
4824
4841
  console.log();
4825
4842
  } else {
4826
- console.log(engine.tripleToN3(df.fact, prefixes));
4843
+ console.log(rdfMode ? engine.tripleToRdfCompatible(df.fact, prefixes) : engine.tripleToN3(df.fact, prefixes));
4827
4844
  }
4828
4845
  }
4829
4846
  }
@@ -5356,7 +5373,12 @@ const {
5356
5373
 
5357
5374
  const { makeExplain } = require('./explain');
5358
5375
 
5359
- const { termToN3, tripleToN3, prettyPrintQueryTriples } = require('./printing');
5376
+ const {
5377
+ termToN3,
5378
+ tripleToN3,
5379
+ prettyPrintQueryTriples,
5380
+ tripleToRdfCompatible,
5381
+ } = require('./printing');
5360
5382
  const {
5361
5383
  getDataFactory,
5362
5384
  internalTripleToRdfJsQuad,
@@ -8669,9 +8691,12 @@ function reasonStream(input, opts = {}) {
8669
8691
  dataFactory = null,
8670
8692
  skipUnsupportedRdfJs = false,
8671
8693
  builtinModules = null,
8694
+ rdf = false,
8672
8695
  } = opts;
8673
8696
 
8674
- const parsedSourceList = parseN3SourceList(input, { baseIri });
8697
+ const useRdfCompatibility = !!rdf;
8698
+
8699
+ const parsedSourceList = parseN3SourceList(input, { baseIri, rdf: useRdfCompatibility });
8675
8700
  const parsedInput = parsedSourceList || normalizeParsedReasonerInputSync(input);
8676
8701
  const rdfFactory = rdfjs ? getDataFactory(dataFactory) : null;
8677
8702
 
@@ -8707,7 +8732,7 @@ function reasonStream(input, opts = {}) {
8707
8732
  if (baseIri) prefixes.setBase(baseIri);
8708
8733
  } else {
8709
8734
  const n3Text = normalizeReasonerInputSync(input);
8710
- const toks = lex(n3Text);
8735
+ const toks = lex(n3Text, { rdf: useRdfCompatibility });
8711
8736
  const parser = new Parser(toks);
8712
8737
  if (baseIri) parser.prefixes.setBase(baseIri);
8713
8738
 
@@ -8741,7 +8766,7 @@ function reasonStream(input, opts = {}) {
8741
8766
  // query-selected triples (not all derived facts).
8742
8767
  if (typeof onDerived === 'function') {
8743
8768
  for (const qdf of queryDerived) {
8744
- const payload = { triple: tripleToN3(qdf.fact, prefixes), df: qdf };
8769
+ const payload = { triple: useRdfCompatibility ? tripleToRdfCompatible(qdf.fact, prefixes) : tripleToN3(qdf.fact, prefixes), df: qdf };
8745
8770
  if (rdfFactory) {
8746
8771
  const quad = maybeTripleToRdfJsQuad(qdf.fact, rdfFactory, skipUnsupportedRdfJs);
8747
8772
  if (quad) payload.quad = quad;
@@ -8758,7 +8783,7 @@ function reasonStream(input, opts = {}) {
8758
8783
  (df) => {
8759
8784
  if (typeof onDerived === 'function') {
8760
8785
  const payload = {
8761
- triple: tripleToN3(df.fact, prefixes),
8786
+ triple: useRdfCompatibility ? tripleToRdfCompatible(df.fact, prefixes) : tripleToN3(df.fact, prefixes),
8762
8787
  df,
8763
8788
  };
8764
8789
  if (rdfFactory) {
@@ -8779,8 +8804,9 @@ function reasonStream(input, opts = {}) {
8779
8804
  ? facts
8780
8805
  : derived.map((d) => d.fact);
8781
8806
 
8782
- const closureN3 =
8783
- Array.isArray(logQueryRules) && logQueryRules.length && !proof
8807
+ const closureN3 = useRdfCompatibility
8808
+ ? closureTriples.map((t) => tripleToRdfCompatible(t, prefixes)).join('\n')
8809
+ : Array.isArray(logQueryRules) && logQueryRules.length && !proof
8784
8810
  ? prettyPrintQueryTriples(closureTriples, prefixes)
8785
8811
  : closureTriples.map((t) => tripleToN3(t, prefixes)).join('\n');
8786
8812
 
@@ -8921,6 +8947,7 @@ module.exports = {
8921
8947
  printExplanation,
8922
8948
  // used by demo worker to stringify derived triples with prefixes
8923
8949
  tripleToN3,
8950
+ tripleToRdfCompatible,
8924
8951
  // pretty log:query output (when proof comments are disabled)
8925
8952
  prettyPrintQueryTriples,
8926
8953
  getEnforceHttpsEnabled,
@@ -9555,7 +9582,300 @@ function stripQuotes(lex) {
9555
9582
  return lex;
9556
9583
  }
9557
9584
 
9558
- function lex(inputText) {
9585
+
9586
+ // RDF/TriG compatibility is an opt-in syntax-normalization layer, not a new
9587
+ // reasoning model. Eyeling remains strict N3 by default and N3 internally:
9588
+ // - RDF 1.2 triple terms <<( s p o )>> become singleton graph terms { s p o }.
9589
+ // - TriG named graph blocks g { ... } become g log:nameOf { ... } .
9590
+ // - A top-level default graph block { ... } is unwrapped into ordinary triples.
9591
+ // This mirrors tools/n3gen.js and keeps all downstream parsing/reasoning N3-only.
9592
+ const LOG_NAME_OF_IRI = '<http://www.w3.org/2000/10/swap/log#nameOf>';
9593
+
9594
+ function normalizeRdfCompatibility(inputText) {
9595
+ let text = String(inputText ?? '');
9596
+
9597
+ // Fast path: most Eyeling inputs are ordinary N3 and do not need RDF/TriG
9598
+ // surface-syntax normalization. Avoid scanning large files character-by-character
9599
+ // unless they actually contain RDF 1.2 triple terms, VERSION directives, or a
9600
+ // plausible top-level TriG named graph block.
9601
+ const hasTripleTerms = text.includes('<<(');
9602
+ const hasVersionDirective = /^\s*(?:@version|VERSION)\s+(["'])1\.2\1\s*\.?\s*(?:#.*)?$/im.test(text);
9603
+ const hasNamedGraphCandidate = /(?:^|[.\r\n])\s*(?:GRAPH\s+)?(?:<[^>\r\n]*>|_:[A-Za-z][A-Za-z0-9_-]*|[A-Za-z][A-Za-z0-9_-]*:[^\s{};,.()[\]]*)\s*\{/m.test(text);
9604
+
9605
+ if (!hasTripleTerms && !hasVersionDirective && !hasNamedGraphCandidate) return text;
9606
+
9607
+ function isWordChar(ch) {
9608
+ return ch != null && /[A-Za-z0-9_:-]/.test(ch);
9609
+ }
9610
+
9611
+ function startsWordAt(s, word, at) {
9612
+ return s.startsWith(word, at) && !isWordChar(s[at - 1]) && !isWordChar(s[at + word.length]);
9613
+ }
9614
+
9615
+ function readStringAt(s, at) {
9616
+ const quote = s[at];
9617
+ let i = at;
9618
+ let out = quote;
9619
+ const long = s.startsWith(quote.repeat(3), i);
9620
+ if (long) {
9621
+ out = quote.repeat(3);
9622
+ i += 3;
9623
+ while (i < s.length) {
9624
+ if (s.startsWith(quote.repeat(3), i)) {
9625
+ out += quote.repeat(3);
9626
+ i += 3;
9627
+ return { text: out, end: i };
9628
+ }
9629
+ if (s[i] === '\\' && i + 1 < s.length) {
9630
+ out += s.slice(i, i + 2);
9631
+ i += 2;
9632
+ } else {
9633
+ out += s[i++];
9634
+ }
9635
+ }
9636
+ return { text: out, end: i };
9637
+ }
9638
+ i += 1;
9639
+ let escaped = false;
9640
+ while (i < s.length) {
9641
+ const ch = s[i++];
9642
+ out += ch;
9643
+ if (escaped) {
9644
+ escaped = false;
9645
+ } else if (ch === '\\') {
9646
+ escaped = true;
9647
+ } else if (ch === quote) {
9648
+ break;
9649
+ }
9650
+ }
9651
+ return { text: out, end: i };
9652
+ }
9653
+
9654
+ function readIriAt(s, at) {
9655
+ let i = at + 1;
9656
+ let out = '<';
9657
+ while (i < s.length) {
9658
+ const ch = s[i++];
9659
+ out += ch;
9660
+ if (ch === '>') break;
9661
+ }
9662
+ return { text: out, end: i };
9663
+ }
9664
+
9665
+ function convertTripleTerms(s) {
9666
+ let i = 0;
9667
+
9668
+ function startsAt(needle, at = i) {
9669
+ return s.startsWith(needle, at);
9670
+ }
9671
+
9672
+ function convertUntil(stopToken) {
9673
+ let out = '';
9674
+ while (i < s.length) {
9675
+ if (stopToken && startsAt(stopToken)) {
9676
+ i += stopToken.length;
9677
+ return out;
9678
+ }
9679
+ if (startsAt('<<(')) {
9680
+ i += 3;
9681
+ out += '{ ' + convertUntil(')>>').trim() + ' }';
9682
+ continue;
9683
+ }
9684
+ const ch = s[i];
9685
+ if (ch === '"' || ch === "'") {
9686
+ const str = readStringAt(s, i);
9687
+ out += str.text;
9688
+ i = str.end;
9689
+ continue;
9690
+ }
9691
+ if (ch === '<') {
9692
+ const iri = readIriAt(s, i);
9693
+ out += iri.text;
9694
+ i = iri.end;
9695
+ continue;
9696
+ }
9697
+ if (ch === '#') {
9698
+ while (i < s.length) {
9699
+ const c = s[i++];
9700
+ out += c;
9701
+ if (c === '\n' || c === '\r') break;
9702
+ }
9703
+ continue;
9704
+ }
9705
+ out += ch;
9706
+ i += 1;
9707
+ }
9708
+ if (stopToken) throw new N3SyntaxError(`Unterminated RDF 1.2 triple term, expected ${stopToken}`);
9709
+ return out;
9710
+ }
9711
+
9712
+ return convertUntil(null);
9713
+ }
9714
+
9715
+ function stripVersionDirectives(s) {
9716
+ return s.replace(/^\s*(?:@version|VERSION)\s+(["'])1\.2\1\s*\.?\s*(?:#.*)?$/gim, '');
9717
+ }
9718
+
9719
+ function skipWsAndComments(s, at) {
9720
+ let i = at;
9721
+ while (i < s.length) {
9722
+ if (/\s/.test(s[i])) {
9723
+ i += 1;
9724
+ continue;
9725
+ }
9726
+ if (s[i] === '#') {
9727
+ while (i < s.length && s[i] !== '\n' && s[i] !== '\r') i += 1;
9728
+ continue;
9729
+ }
9730
+ break;
9731
+ }
9732
+ return i;
9733
+ }
9734
+
9735
+ function readTermAt(s, at) {
9736
+ if (s[at] === '<') return readIriAt(s, at);
9737
+ let i = at;
9738
+ while (i < s.length && !/\s/.test(s[i]) && !'{}[](),;.'.includes(s[i])) i += 1;
9739
+ if (i === at) return null;
9740
+ const value = s.slice(at, i);
9741
+ if (!value || value.startsWith('@')) return null;
9742
+ return { text: value, end: i };
9743
+ }
9744
+
9745
+ function readBalancedBlock(s, at) {
9746
+ if (s[at] !== '{') return null;
9747
+ let i = at;
9748
+ let depth = 0;
9749
+ while (i < s.length) {
9750
+ const ch = s[i];
9751
+ if (ch === '"' || ch === "'") {
9752
+ i = readStringAt(s, i).end;
9753
+ continue;
9754
+ }
9755
+ if (ch === '<') {
9756
+ i = readIriAt(s, i).end;
9757
+ continue;
9758
+ }
9759
+ if (ch === '#') {
9760
+ while (i < s.length && s[i] !== '\n' && s[i] !== '\r') i += 1;
9761
+ continue;
9762
+ }
9763
+ if (ch === '{') depth += 1;
9764
+ if (ch === '}') {
9765
+ depth -= 1;
9766
+ i += 1;
9767
+ if (depth === 0) return { text: s.slice(at, i), inner: s.slice(at + 1, i - 1), end: i };
9768
+ continue;
9769
+ }
9770
+ i += 1;
9771
+ }
9772
+ throw new N3SyntaxError('Unterminated RDF/TriG graph block, expected }');
9773
+ }
9774
+
9775
+ function normalizeNamedGraphs(s) {
9776
+ let out = '';
9777
+ let i = 0;
9778
+ let statementStart = true;
9779
+ let braceDepth = 0;
9780
+
9781
+ while (i < s.length) {
9782
+ if (statementStart && braceDepth === 0) {
9783
+ const termStart = skipWsAndComments(s, i);
9784
+ out += s.slice(i, termStart);
9785
+ i = termStart;
9786
+
9787
+ // Top-level TriG default graph block: { ... } .
9788
+ if (s[i] === '{') {
9789
+ const block = readBalancedBlock(s, i);
9790
+ const after = skipWsAndComments(s, block.end);
9791
+ if (after >= s.length || s[after] === '.') {
9792
+ out += block.inner.trim();
9793
+ if (block.inner.trim() && !/\n$/.test(block.inner)) out += '\n';
9794
+ i = after < s.length && s[after] === '.' ? after + 1 : after;
9795
+ statementStart = true;
9796
+ continue;
9797
+ }
9798
+ // It is an ordinary N3 formula subject, not a TriG default graph.
9799
+ out += block.text;
9800
+ i = block.end;
9801
+ statementStart = false;
9802
+ continue;
9803
+ }
9804
+
9805
+ let graphKeyword = false;
9806
+ if (startsWordAt(s, 'GRAPH', i)) {
9807
+ graphKeyword = true;
9808
+ i += 'GRAPH'.length;
9809
+ i = skipWsAndComments(s, i);
9810
+ }
9811
+
9812
+ const term = readTermAt(s, i);
9813
+ if (term && !['@prefix', '@base', 'PREFIX', 'BASE', 'VERSION'].includes(term.text)) {
9814
+ const afterTerm = skipWsAndComments(s, term.end);
9815
+ if (s[afterTerm] === '{') {
9816
+ const block = readBalancedBlock(s, afterTerm);
9817
+ const afterBlock = skipWsAndComments(s, block.end);
9818
+ out += `${term.text} ${LOG_NAME_OF_IRI} ${block.text} .`;
9819
+ i = afterBlock < s.length && s[afterBlock] === '.' ? afterBlock + 1 : block.end;
9820
+ statementStart = true;
9821
+ continue;
9822
+ }
9823
+ }
9824
+
9825
+ // Not TriG named-graph syntax after all; copy the first character and
9826
+ // continue as ordinary N3.
9827
+ if (graphKeyword) {
9828
+ out += 'GRAPH ';
9829
+ statementStart = false;
9830
+ } else if (i < s.length) {
9831
+ const copied = s[i++];
9832
+ out += copied;
9833
+ if (!/\s/.test(copied)) statementStart = false;
9834
+ }
9835
+ } else {
9836
+ const ch = s[i];
9837
+ out += ch;
9838
+ if (ch === '"' || ch === "'") {
9839
+ const str = readStringAt(s, i);
9840
+ out = out.slice(0, -1) + str.text;
9841
+ i = str.end;
9842
+ continue;
9843
+ }
9844
+ if (ch === '<') {
9845
+ const iri = readIriAt(s, i);
9846
+ out = out.slice(0, -1) + iri.text;
9847
+ i = iri.end;
9848
+ continue;
9849
+ }
9850
+ if (ch === '#') {
9851
+ i += 1;
9852
+ while (i < s.length) {
9853
+ const c = s[i++];
9854
+ out += c;
9855
+ if (c === '\n' || c === '\r') break;
9856
+ }
9857
+ continue;
9858
+ }
9859
+ if (ch === '{') braceDepth += 1;
9860
+ else if (ch === '}' && braceDepth > 0) braceDepth -= 1;
9861
+ else if (ch === '.' && braceDepth === 0) statementStart = true;
9862
+ else if (!/\s/.test(ch)) statementStart = false;
9863
+ i += 1;
9864
+ }
9865
+ }
9866
+
9867
+ return out;
9868
+ }
9869
+
9870
+ if (hasTripleTerms) text = convertTripleTerms(text);
9871
+ if (hasVersionDirective) text = stripVersionDirectives(text);
9872
+ if (hasVersionDirective || hasNamedGraphCandidate) text = normalizeNamedGraphs(text);
9873
+ return text;
9874
+ }
9875
+
9876
+ function lex(inputText, opts = {}) {
9877
+ const rdf = !!(opts && opts.rdf);
9878
+ if (rdf) inputText = normalizeRdfCompatibility(inputText);
9559
9879
  const chars = Array.from(inputText);
9560
9880
  const n = chars.length;
9561
9881
  let i = 0;
@@ -10016,7 +10336,7 @@ function lex(inputText) {
10016
10336
  return tokens;
10017
10337
  }
10018
10338
 
10019
- module.exports = { Token, N3SyntaxError, lex, decodeN3StringEscapes };
10339
+ module.exports = { Token, N3SyntaxError, lex, normalizeRdfCompatibility, decodeN3StringEscapes };
10020
10340
 
10021
10341
  };
10022
10342
  __modules["lib/multisource.js"] = function(require, module, exports){
@@ -10125,8 +10445,14 @@ function prefixesUsedInTokens(tokens, prefEnv) {
10125
10445
  }
10126
10446
 
10127
10447
  function parseN3Text(text, opts = {}) {
10128
- const { baseIri = '', label = '<input>', keepSourceArtifacts = true, collectUsedPrefixes = false } = opts || {};
10129
- const tokens = lex(text);
10448
+ const {
10449
+ baseIri = '',
10450
+ label = '<input>',
10451
+ keepSourceArtifacts = true,
10452
+ collectUsedPrefixes = false,
10453
+ rdf = false,
10454
+ } = opts || {};
10455
+ const tokens = lex(text, { rdf });
10130
10456
  const parser = new Parser(tokens);
10131
10457
  if (baseIri) parser.prefixes.setBase(baseIri);
10132
10458
  const [prefixes, triples, frules, brules, logQueryRules] = parser.parseDocument();
@@ -10320,6 +10646,7 @@ function parseN3SourceList(input, opts = {}) {
10320
10646
  baseIri: source.baseIri || (sources.length === 1 ? defaultBaseIri : ''),
10321
10647
  collectUsedPrefixes: true,
10322
10648
  keepSourceArtifacts: !!opts.keepSourceArtifacts,
10649
+ rdf: !!opts.rdf,
10323
10650
  }),
10324
10651
  );
10325
10652
  return mergeParsedDocuments(parsed, {
@@ -11710,6 +12037,7 @@ const {
11710
12037
  isOwlSameAsPred,
11711
12038
  isLogImplies,
11712
12039
  isLogImpliedBy,
12040
+ LOG_NS,
11713
12041
  } = require('./prelude');
11714
12042
 
11715
12043
  function stripQuotes(lex) {
@@ -12039,7 +12367,111 @@ function prettyPrintQueryTriples(triples, prefixes) {
12039
12367
  return blocks.join('\n');
12040
12368
  }
12041
12369
 
12042
- module.exports = { termToN3, tripleToN3, prettyPrintQueryTriples };
12370
+
12371
+ // ---------------------------------------------------------------------------
12372
+ // RDF compatibility output
12373
+ // ---------------------------------------------------------------------------
12374
+
12375
+ function isRdfTripleTermSubject(t) {
12376
+ return t instanceof Iri || t instanceof Blank;
12377
+ }
12378
+
12379
+ function isRdfTripleTermPredicate(t) {
12380
+ return t instanceof Iri;
12381
+ }
12382
+
12383
+ function isRdfTripleTermObject(t) {
12384
+ return t instanceof Iri || t instanceof Blank || t instanceof Literal;
12385
+ }
12386
+
12387
+ function isRdfTripleTermGraph(t) {
12388
+ if (!(t instanceof GraphTerm)) return false;
12389
+ if (!Array.isArray(t.triples) || t.triples.length !== 1) return false;
12390
+ const tr = t.triples[0];
12391
+ return isRdfTripleTermSubject(tr.s) && isRdfTripleTermPredicate(tr.p) && isRdfTripleTermObject(tr.o);
12392
+ }
12393
+
12394
+
12395
+ function isLogNameOfPred(p) {
12396
+ return p instanceof Iri && p.value === LOG_NS + 'nameOf';
12397
+ }
12398
+
12399
+ function isRdfNamedGraphLabel(t) {
12400
+ return t instanceof Iri || t instanceof Blank;
12401
+ }
12402
+
12403
+ function rdfCompatibleGraphBlock(graph, prefixes) {
12404
+ const indent = ' ';
12405
+ const indentBlock = (str) =>
12406
+ str
12407
+ .split(/\r?\n/)
12408
+ .map((ln) => (ln.length ? indent + ln : ln))
12409
+ .join('\n');
12410
+
12411
+ let s = '{\n';
12412
+ for (const inner of graph.triples || []) {
12413
+ const block = tripleToRdfCompatible(inner, prefixes).trimEnd();
12414
+ if (block) s += indentBlock(block) + '\n';
12415
+ }
12416
+ s += '}';
12417
+ return s;
12418
+ }
12419
+
12420
+ function rdfPredicateToText(p, prefixes) {
12421
+ return isRdfTypePred(p) ? 'a' : termToN3(p, prefixes);
12422
+ }
12423
+
12424
+ function termToRdfCompatible(t, pref) {
12425
+ if (isRdfTripleTermGraph(t)) {
12426
+ const tr = t.triples[0];
12427
+ const s = termToN3(tr.s, pref);
12428
+ const p = rdfPredicateToText(tr.p, pref);
12429
+ const o = termToN3(tr.o, pref);
12430
+ return `<<( ${s} ${p} ${o} )>>`;
12431
+ }
12432
+ return termToN3(t, pref);
12433
+ }
12434
+
12435
+ function tripleToRdfCompatible(tr, prefixes) {
12436
+ if (isLogNameOfPred(tr.p) && isRdfNamedGraphLabel(tr.s) && tr.o instanceof GraphTerm) {
12437
+ return `${termToN3(tr.s, prefixes)} ${rdfCompatibleGraphBlock(tr.o, prefixes)}`;
12438
+ }
12439
+
12440
+ if (isLogImplies(tr.p)) {
12441
+ const s = termToRdfCompatible(tr.s, prefixes);
12442
+ const o = termToRdfCompatible(tr.o, prefixes);
12443
+ return `${s} => ${o} .`;
12444
+ }
12445
+
12446
+ if (isLogImpliedBy(tr.p)) {
12447
+ const s = termToRdfCompatible(tr.s, prefixes);
12448
+ const o = termToRdfCompatible(tr.o, prefixes);
12449
+ return `${s} <= ${o} .`;
12450
+ }
12451
+
12452
+ const s = termToRdfCompatible(tr.s, prefixes);
12453
+ const p = isRdfTypePred(tr.p) ? 'a' : isOwlSameAsPred(tr.p) ? '=' : termToN3(tr.p, prefixes);
12454
+ const o = termToRdfCompatible(tr.o, prefixes);
12455
+ return `${s} ${p} ${o} .`;
12456
+ }
12457
+
12458
+ function prettyPrintQueryTriplesRdfCompatible(triples, prefixes) {
12459
+ return triples.map((tr) => tripleToRdfCompatible(tr, prefixes)).join('\n');
12460
+ }
12461
+
12462
+ function needsRdf12Version(text) {
12463
+ return typeof text === 'string' && text.includes('<<(');
12464
+ }
12465
+
12466
+ module.exports = {
12467
+ termToN3,
12468
+ tripleToN3,
12469
+ prettyPrintQueryTriples,
12470
+ termToRdfCompatible,
12471
+ tripleToRdfCompatible,
12472
+ prettyPrintQueryTriplesRdfCompatible,
12473
+ needsRdf12Version,
12474
+ };
12043
12475
 
12044
12476
  };
12045
12477
  __modules["lib/rdfjs.js"] = function(require, module, exports){
package/index.js CHANGED
@@ -37,6 +37,8 @@ function reason(opt = {}, input = '') {
37
37
  else args.push('--no-proof-comments');
38
38
  }
39
39
 
40
+ if (opt.rdf) args.push('--rdf');
41
+
40
42
  if (Array.isArray(opt.args)) args.push(...opt.args);
41
43
 
42
44
  const builtinModules = Array.isArray(opt.builtinModules)