eyeling 1.5.27 → 1.5.28

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/eyeling.js CHANGED
@@ -235,6 +235,12 @@ function lex(inputText) {
235
235
  i += 2;
236
236
  continue;
237
237
  }
238
+ // N3 predicate inversion: "<-" (swap subject/object for this predicate)
239
+ if (peek(1) === "-") {
240
+ tokens.push(new Token("OpPredInvert"));
241
+ i += 2;
242
+ continue;
243
+ }
238
244
  // Otherwise IRIREF <...>
239
245
  i++; // skip '<'
240
246
  const iriChars = [];
@@ -823,9 +829,14 @@ class Parser {
823
829
  while (true) {
824
830
  // Verb (can also be 'a')
825
831
  let pred;
832
+ let invert = false;
826
833
  if (this.peek().typ === "Ident" && (this.peek().value || "") === "a") {
827
834
  this.next();
828
835
  pred = new Iri(RDF_NS + "type");
836
+ } else if (this.peek().typ === "OpPredInvert") {
837
+ this.next(); // consume "<-"
838
+ pred = this.parseTerm();
839
+ invert = true;
829
840
  } else {
830
841
  pred = this.parseTerm();
831
842
  }
@@ -838,7 +849,8 @@ class Parser {
838
849
  }
839
850
 
840
851
  for (const o of objs) {
841
- this.pendingTriples.push(new Triple(subj, pred, o));
852
+ this.pendingTriples.push(invert ? new Triple(o, pred, subj)
853
+ : new Triple(subj, pred, o));
842
854
  }
843
855
 
844
856
  if (this.peek().typ === "Semicolon") {
@@ -906,14 +918,21 @@ class Parser {
906
918
  const out = [];
907
919
  while (true) {
908
920
  let verb;
921
+ let invert = false;
909
922
  if (this.peek().typ === "Ident" && (this.peek().value || "") === "a") {
910
923
  this.next();
911
924
  verb = new Iri(RDF_NS + "type");
925
+ } else if (this.peek().typ === "OpPredInvert") {
926
+ this.next(); // consume "<-"
927
+ verb = this.parseTerm(); // predicate expression
928
+ invert = true;
912
929
  } else {
913
930
  verb = this.parseTerm();
914
931
  }
915
932
  const objects = this.parseObjectList();
916
- for (const o of objects) out.push(new Triple(subject, verb, o));
933
+ for (const o of objects) {
934
+ out.push(new Triple(invert ? o : subject, verb, invert ? subject : o));
935
+ }
917
936
 
918
937
  if (this.peek().typ === "Semicolon") {
919
938
  this.next();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eyeling",
3
- "version": "1.5.27",
3
+ "version": "1.5.28",
4
4
  "description": "A minimal Notation3 (N3) reasoner in JavaScript.",
5
5
  "main": "./index.js",
6
6
  "keywords": [
package/test/api.test.js CHANGED
@@ -636,6 +636,20 @@ ${U('s')} ${U('p')} ${U('o')}. # another trailing comment
636
636
  world"""@en.`,
637
637
  expect: [new RegExp(`${EX}s>\\s+<${EX}q>\\s+(?:"""Hello[\\s\\S]*?world"""@en|"Hello\\\\nworld"@en)\\s*\\.`)],
638
638
  },
639
+
640
+ { name: '44 syntax: "<-" in predicate position swaps subject and object',
641
+ opt: { proofComments: false },
642
+ input: ` { ?s ${U('p')} ?o } => { ?s ${U('q')} ?o }.
643
+ ${U('a')} <-${U('p')} ${U('b')}.`,
644
+ expect: [new RegExp(`${EX}b>\\s+<${EX}q>\\s+<${EX}a>\\s*\\.`)],
645
+ },
646
+
647
+ { name: '45 syntax: "<-" works inside blank node property lists ([ ... ])',
648
+ opt: { proofComments: false },
649
+ input: ` ${U('s')} ${U('p')} [ <-${U('r')} ${U('o')} ].
650
+ { ${U('o')} ${U('r')} ?x } => { ?x ${U('q')} ${U('k')} }.`,
651
+ expect: [new RegExp(`_:b1\\s+<${EX}q>\\s+<${EX}k>\\s*\\.`)],
652
+ },
639
653
  ];
640
654
 
641
655
  let passed = 0;