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 +21 -2
- package/package.json +1 -1
- package/test/api.test.js +14 -0
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(
|
|
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)
|
|
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
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;
|