n3 1.25.2 → 2.0.0-beta.1
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 +0 -7
- package/browser/n3.min.js +1 -1
- package/lib/IRIs.js +4 -3
- package/lib/N3DataFactory.js +34 -6
- package/lib/N3Lexer.js +35 -17
- package/lib/N3Parser.js +189 -43
- package/lib/N3Store.js +21 -23
- package/lib/N3Writer.js +9 -8
- package/lib/index.js +0 -8
- package/package.json +24 -12
- package/src/IRIs.js +7 -6
- package/src/N3DataFactory.js +38 -9
- package/src/N3Lexer.js +37 -17
- package/src/N3Parser.js +206 -52
- package/src/N3Store.js +21 -22
- package/src/N3Writer.js +11 -7
- package/src/index.js +0 -3
- package/lib/BaseIRI.js +0 -93
- package/lib/Util.js +0 -9
- package/src/BaseIRI.js +0 -101
- package/src/Util.js +0 -3
package/src/N3Parser.js
CHANGED
|
@@ -27,16 +27,12 @@ export default class N3Parser {
|
|
|
27
27
|
this._readPredicateOrNamedGraph = this._readPredicate;
|
|
28
28
|
// Support triples in other graphs
|
|
29
29
|
this._supportsQuads = !(isTurtle || isTriG || isNTriples || isN3);
|
|
30
|
-
// Whether the log:isImpliedBy predicate is supported
|
|
31
|
-
this._isImpliedBy = options.isImpliedBy;
|
|
32
|
-
// Support nesting of triples
|
|
33
|
-
this._supportsRDFStar = format === '' || /star|\*$/.test(format);
|
|
34
30
|
// Disable relative IRIs in N-Triples or N-Quads mode
|
|
35
31
|
if (isLineMode)
|
|
36
32
|
this._resolveRelativeIRI = iri => { return null; };
|
|
37
33
|
this._blankNodePrefix = typeof options.blankNodePrefix !== 'string' ? '' :
|
|
38
34
|
options.blankNodePrefix.replace(/^(?!_:)/, '_:');
|
|
39
|
-
this._lexer = options.lexer || new N3Lexer({ lineMode: isLineMode, n3: isN3
|
|
35
|
+
this._lexer = options.lexer || new N3Lexer({ lineMode: isLineMode, n3: isN3 });
|
|
40
36
|
// Disable explicit quantifiers by default
|
|
41
37
|
this._explicitQuantifiers = !!options.explicitQuantifiers;
|
|
42
38
|
}
|
|
@@ -135,6 +131,11 @@ export default class N3Parser {
|
|
|
135
131
|
this._sparqlStyle = true;
|
|
136
132
|
case '@base':
|
|
137
133
|
return this._readBaseIRI;
|
|
134
|
+
// It could be a version declaration
|
|
135
|
+
case 'VERSION':
|
|
136
|
+
this._sparqlStyle = true;
|
|
137
|
+
case '@version':
|
|
138
|
+
return this._readVersion;
|
|
138
139
|
// It could be a graph
|
|
139
140
|
case '{':
|
|
140
141
|
if (this._supportsNamedGraphs) {
|
|
@@ -199,6 +200,10 @@ export default class N3Parser {
|
|
|
199
200
|
this._subject = this._factory.blankNode(), null, null);
|
|
200
201
|
return this._readBlankNodeHead;
|
|
201
202
|
case '(':
|
|
203
|
+
const stack = this._contextStack, parent = stack.length && stack[stack.length - 1];
|
|
204
|
+
if (parent.type === '<<') {
|
|
205
|
+
return this._error('Unexpected list in reified triple', token);
|
|
206
|
+
}
|
|
202
207
|
// Start a new list
|
|
203
208
|
this._saveContext('list', this._graph, this.RDF_NIL, null, null);
|
|
204
209
|
this._subject = null;
|
|
@@ -239,9 +244,13 @@ export default class N3Parser {
|
|
|
239
244
|
this._subject = this._factory.literal(token.value, this._factory.namedNode(token.prefix));
|
|
240
245
|
|
|
241
246
|
break;
|
|
247
|
+
case '<<(':
|
|
248
|
+
if (!this._n3Mode)
|
|
249
|
+
return this._error('Disallowed triple term as subject', token);
|
|
250
|
+
this._saveContext('<<(', this._graph, null, null, null);
|
|
251
|
+
this._graph = null;
|
|
252
|
+
return this._readSubject;
|
|
242
253
|
case '<<':
|
|
243
|
-
if (!this._supportsRDFStar)
|
|
244
|
-
return this._error('Unexpected RDF-star syntax', token);
|
|
245
254
|
this._saveContext('<<', this._graph, null, null, null);
|
|
246
255
|
this._graph = null;
|
|
247
256
|
return this._readSubject;
|
|
@@ -271,6 +280,7 @@ export default class N3Parser {
|
|
|
271
280
|
case '.':
|
|
272
281
|
case ']':
|
|
273
282
|
case '}':
|
|
283
|
+
case '|}':
|
|
274
284
|
// Expected predicate didn't come, must have been trailing semicolon
|
|
275
285
|
if (this._predicate === null)
|
|
276
286
|
return this._error(`Unexpected ${type}`, token);
|
|
@@ -317,6 +327,10 @@ export default class N3Parser {
|
|
|
317
327
|
this._subject = this._factory.blankNode());
|
|
318
328
|
return this._readBlankNodeHead;
|
|
319
329
|
case '(':
|
|
330
|
+
const stack = this._contextStack, parent = stack.length && stack[stack.length - 1];
|
|
331
|
+
if (parent.type === '<<') {
|
|
332
|
+
return this._error('Unexpected list in reified triple', token);
|
|
333
|
+
}
|
|
320
334
|
// Start a new list
|
|
321
335
|
this._saveContext('list', this._graph, this._subject, this._predicate, this.RDF_NIL);
|
|
322
336
|
this._subject = null;
|
|
@@ -328,9 +342,11 @@ export default class N3Parser {
|
|
|
328
342
|
this._saveContext('formula', this._graph, this._subject, this._predicate,
|
|
329
343
|
this._graph = this._factory.blankNode());
|
|
330
344
|
return this._readSubject;
|
|
345
|
+
case '<<(':
|
|
346
|
+
this._saveContext('<<(', this._graph, this._subject, this._predicate, null);
|
|
347
|
+
this._graph = null;
|
|
348
|
+
return this._readSubject;
|
|
331
349
|
case '<<':
|
|
332
|
-
if (!this._supportsRDFStar)
|
|
333
|
-
return this._error('Unexpected RDF-star syntax', token);
|
|
334
350
|
this._saveContext('<<', this._graph, this._subject, this._predicate, null);
|
|
335
351
|
this._graph = null;
|
|
336
352
|
return this._readSubject;
|
|
@@ -366,6 +382,10 @@ export default class N3Parser {
|
|
|
366
382
|
return this._readBlankNodeTail(token);
|
|
367
383
|
}
|
|
368
384
|
else {
|
|
385
|
+
const stack = this._contextStack, parentParent = stack.length > 1 && stack[stack.length - 2];
|
|
386
|
+
if (parentParent.type === '<<') {
|
|
387
|
+
return this._error('Unexpected compound blank node expression in reified triple', token);
|
|
388
|
+
}
|
|
369
389
|
this._predicate = null;
|
|
370
390
|
return this._readPredicate(token);
|
|
371
391
|
}
|
|
@@ -475,6 +495,11 @@ export default class N3Parser {
|
|
|
475
495
|
this._saveContext('formula', this._graph, this._subject, this._predicate,
|
|
476
496
|
this._graph = this._factory.blankNode());
|
|
477
497
|
return this._readSubject;
|
|
498
|
+
case '<<':
|
|
499
|
+
this._saveContext('<<', this._graph, null, null, null);
|
|
500
|
+
this._graph = null;
|
|
501
|
+
next = this._readSubject;
|
|
502
|
+
break;
|
|
478
503
|
default:
|
|
479
504
|
if ((item = this._readEntity(token)) === undefined)
|
|
480
505
|
return;
|
|
@@ -484,6 +509,10 @@ export default class N3Parser {
|
|
|
484
509
|
if (list === null)
|
|
485
510
|
this._subject = list = this._factory.blankNode();
|
|
486
511
|
|
|
512
|
+
// When reading a reified triple, store the list as subject in the stack, as this will be overridden when reading the triple.
|
|
513
|
+
if (token.type === '<<')
|
|
514
|
+
stack[stack.length - 1].subject = this._subject;
|
|
515
|
+
|
|
487
516
|
// Is this the first element of the list?
|
|
488
517
|
if (previousList === null) {
|
|
489
518
|
// This list is either the subject or the object of its parent
|
|
@@ -524,9 +553,10 @@ export default class N3Parser {
|
|
|
524
553
|
}
|
|
525
554
|
|
|
526
555
|
// ### `_completeLiteral` completes a literal with an optional datatype or language
|
|
527
|
-
_completeLiteral(token) {
|
|
556
|
+
_completeLiteral(token, component) {
|
|
528
557
|
// Create a simple string literal by default
|
|
529
558
|
let literal = this._factory.literal(this._literalValue);
|
|
559
|
+
let readCb;
|
|
530
560
|
|
|
531
561
|
switch (token.type) {
|
|
532
562
|
// Create a datatyped literal
|
|
@@ -534,43 +564,82 @@ export default class N3Parser {
|
|
|
534
564
|
case 'typeIRI':
|
|
535
565
|
const datatype = this._readEntity(token);
|
|
536
566
|
if (datatype === undefined) return; // No datatype means an error occurred
|
|
567
|
+
if (datatype.value === namespaces.rdf.langString || datatype.value === namespaces.rdf.dirLangString) {
|
|
568
|
+
return this._error('Detected illegal (directional) languaged-tagged string with explicit datatype', token);
|
|
569
|
+
}
|
|
537
570
|
literal = this._factory.literal(this._literalValue, datatype);
|
|
538
571
|
token = null;
|
|
539
572
|
break;
|
|
540
573
|
// Create a language-tagged string
|
|
541
574
|
case 'langcode':
|
|
575
|
+
if (token.value.length > 8)
|
|
576
|
+
return this._error('Detected language tag of length larger than 8', token);
|
|
542
577
|
literal = this._factory.literal(this._literalValue, token.value);
|
|
578
|
+
this._literalLanguage = token.value;
|
|
543
579
|
token = null;
|
|
580
|
+
readCb = this._readDirCode.bind(this, component);
|
|
544
581
|
break;
|
|
545
582
|
}
|
|
546
583
|
|
|
547
|
-
return { token, literal };
|
|
584
|
+
return { token, literal, readCb };
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
_readDirCode(component, listItem, token) {
|
|
588
|
+
// Attempt to read a dircode
|
|
589
|
+
if (token.type === 'dircode') {
|
|
590
|
+
const term = this._factory.literal(this._literalValue, { language: this._literalLanguage, direction: token.value });
|
|
591
|
+
if (component === 'subject')
|
|
592
|
+
this._subject = term;
|
|
593
|
+
else
|
|
594
|
+
this._object = term;
|
|
595
|
+
this._literalLanguage = undefined;
|
|
596
|
+
token = null;
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
if (component === 'subject')
|
|
600
|
+
return token === null ? this._readPredicateOrNamedGraph : this._readPredicateOrNamedGraph(token);
|
|
601
|
+
return this._completeObjectLiteralPost(token, listItem);
|
|
548
602
|
}
|
|
549
603
|
|
|
550
604
|
// Completes a literal in subject position
|
|
551
605
|
_completeSubjectLiteral(token) {
|
|
552
|
-
|
|
606
|
+
const completed = this._completeLiteral(token, 'subject');
|
|
607
|
+
this._subject = completed.literal;
|
|
608
|
+
|
|
609
|
+
// Postpone completion if the literal is only partially completed (such as lang+dir).
|
|
610
|
+
if (completed.readCb)
|
|
611
|
+
return completed.readCb.bind(this, false);
|
|
612
|
+
|
|
553
613
|
return this._readPredicateOrNamedGraph;
|
|
554
614
|
}
|
|
555
615
|
|
|
556
616
|
// Completes a literal in object position
|
|
557
617
|
_completeObjectLiteral(token, listItem) {
|
|
558
|
-
const completed = this._completeLiteral(token);
|
|
618
|
+
const completed = this._completeLiteral(token, 'object');
|
|
559
619
|
if (!completed)
|
|
560
620
|
return;
|
|
621
|
+
|
|
561
622
|
this._object = completed.literal;
|
|
562
623
|
|
|
624
|
+
// Postpone completion if the literal is only partially completed (such as lang+dir).
|
|
625
|
+
if (completed.readCb)
|
|
626
|
+
return completed.readCb.bind(this, listItem);
|
|
627
|
+
|
|
628
|
+
return this._completeObjectLiteralPost(completed.token, listItem);
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
_completeObjectLiteralPost(token, listItem) {
|
|
563
632
|
// If this literal was part of a list, write the item
|
|
564
633
|
// (we could also check the context stack, but passing in a flag is faster)
|
|
565
634
|
if (listItem)
|
|
566
635
|
this._emit(this._subject, this.RDF_FIRST, this._object, this._graph);
|
|
567
636
|
// If the token was consumed, continue with the rest of the input
|
|
568
|
-
if (
|
|
637
|
+
if (token === null)
|
|
569
638
|
return this._getContextEndReader();
|
|
570
639
|
// Otherwise, consume the token now
|
|
571
640
|
else {
|
|
572
641
|
this._readCallback = this._getContextEndReader();
|
|
573
|
-
return this._readCallback(
|
|
642
|
+
return this._readCallback(token);
|
|
574
643
|
}
|
|
575
644
|
}
|
|
576
645
|
|
|
@@ -592,7 +661,7 @@ export default class N3Parser {
|
|
|
592
661
|
|
|
593
662
|
// ### `_readPunctuation` reads punctuation between quads or quad parts
|
|
594
663
|
_readPunctuation(token) {
|
|
595
|
-
let next, graph = this._graph;
|
|
664
|
+
let next, graph = this._graph, startingAnnotation = false;
|
|
596
665
|
const subject = this._subject, inversePredicate = this._inversePredicate;
|
|
597
666
|
switch (token.type) {
|
|
598
667
|
// A closing brace ends a graph
|
|
@@ -605,6 +674,7 @@ export default class N3Parser {
|
|
|
605
674
|
// A dot just ends the statement, without sharing anything with the next
|
|
606
675
|
case '.':
|
|
607
676
|
this._subject = null;
|
|
677
|
+
this._tripleTerm = null;
|
|
608
678
|
next = this._contextStack.length ? this._readSubject : this._readInTopContext;
|
|
609
679
|
if (inversePredicate) this._inversePredicate = false;
|
|
610
680
|
break;
|
|
@@ -616,20 +686,24 @@ export default class N3Parser {
|
|
|
616
686
|
case ',':
|
|
617
687
|
next = this._readObject;
|
|
618
688
|
break;
|
|
689
|
+
// ~ is allowed in the annotation syntax
|
|
690
|
+
case '~':
|
|
691
|
+
next = this._readReifierInAnnotation;
|
|
692
|
+
startingAnnotation = true;
|
|
693
|
+
break;
|
|
619
694
|
// {| means that the current triple is annotated with predicate-object pairs.
|
|
620
695
|
case '{|':
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
const predicate = this._predicate, object = this._object;
|
|
625
|
-
this._subject = this._factory.quad(subject, predicate, object, this.DEFAULTGRAPH);
|
|
696
|
+
// Continue using the last triple as reified triple subject for the predicate-object pairs.
|
|
697
|
+
this._subject = this._readTripleTerm();
|
|
698
|
+
startingAnnotation = true;
|
|
626
699
|
next = this._readPredicate;
|
|
627
700
|
break;
|
|
628
|
-
// |} means that the current
|
|
701
|
+
// |} means that the current reified triple in annotation syntax is finalized.
|
|
629
702
|
case '|}':
|
|
630
|
-
if (this.
|
|
631
|
-
return this._error('Unexpected
|
|
703
|
+
if (!this._annotation)
|
|
704
|
+
return this._error('Unexpected annotation syntax closing', token);
|
|
632
705
|
this._subject = null;
|
|
706
|
+
this._annotation = false;
|
|
633
707
|
next = this._readPunctuation;
|
|
634
708
|
break;
|
|
635
709
|
default:
|
|
@@ -641,13 +715,16 @@ export default class N3Parser {
|
|
|
641
715
|
return this._error(`Expected punctuation to follow "${this._object.id}"`, token);
|
|
642
716
|
}
|
|
643
717
|
// A quad has been completed now, so return it
|
|
644
|
-
if (subject !== null) {
|
|
718
|
+
if (subject !== null && (!startingAnnotation || (startingAnnotation && !this._annotation))) {
|
|
645
719
|
const predicate = this._predicate, object = this._object;
|
|
646
720
|
if (!inversePredicate)
|
|
647
721
|
this._emit(subject, predicate, object, graph);
|
|
648
722
|
else
|
|
649
723
|
this._emit(object, predicate, subject, graph);
|
|
650
724
|
}
|
|
725
|
+
if (startingAnnotation) {
|
|
726
|
+
this._annotation = true;
|
|
727
|
+
}
|
|
651
728
|
return next;
|
|
652
729
|
}
|
|
653
730
|
|
|
@@ -705,6 +782,16 @@ export default class N3Parser {
|
|
|
705
782
|
return this._readDeclarationPunctuation;
|
|
706
783
|
}
|
|
707
784
|
|
|
785
|
+
// ### `_readVersion` reads version string declaration
|
|
786
|
+
_readVersion(token) {
|
|
787
|
+
if (token.type !== 'literal')
|
|
788
|
+
return this._error('Expected literal to follow version declaration', token);
|
|
789
|
+
if ((token.end - token.start) !== token.value.length + 2)
|
|
790
|
+
return this._error('Version declarations must use single quotes', token);
|
|
791
|
+
this._prefixCallback(token.value);
|
|
792
|
+
return this._readDeclarationPunctuation;
|
|
793
|
+
}
|
|
794
|
+
|
|
708
795
|
// ### `_readNamedGraphLabel` reads the label of a named graph
|
|
709
796
|
_readNamedGraphLabel(token) {
|
|
710
797
|
switch (token.type) {
|
|
@@ -853,25 +940,15 @@ export default class N3Parser {
|
|
|
853
940
|
return this._readPath;
|
|
854
941
|
}
|
|
855
942
|
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
if (token.type !== '>>')
|
|
859
|
-
|
|
860
|
-
if (this._supportsQuads && this._graph === null && (this._graph = this._readEntity(token)) !== undefined)
|
|
861
|
-
return this._readRDFStarTail;
|
|
862
|
-
return this._error(`Expected >> to follow "${this._object.id}"`, token);
|
|
863
|
-
}
|
|
864
|
-
return this._readRDFStarTail(token);
|
|
865
|
-
}
|
|
866
|
-
|
|
867
|
-
// ### `_readRDFStarTail` reads the end of a nested RDF-star triple
|
|
868
|
-
_readRDFStarTail(token) {
|
|
869
|
-
if (token.type !== '>>')
|
|
870
|
-
return this._error(`Expected >> but got ${token.type}`, token);
|
|
943
|
+
// ### `_readTripleTermTail` reads the end of a triple term
|
|
944
|
+
_readTripleTermTail(token) {
|
|
945
|
+
if (token.type !== ')>>')
|
|
946
|
+
return this._error(`Expected )>> but got ${token.type}`, token);
|
|
871
947
|
// Read the quad and restore the previous context
|
|
872
948
|
const quad = this._factory.quad(this._subject, this._predicate, this._object,
|
|
873
|
-
|
|
874
|
-
this._restoreContext('<<', token);
|
|
949
|
+
this._graph || this.DEFAULTGRAPH);
|
|
950
|
+
this._restoreContext('<<(', token);
|
|
951
|
+
|
|
875
952
|
// If the triple was the subject, continue by reading the predicate.
|
|
876
953
|
if (this._subject === null) {
|
|
877
954
|
this._subject = quad;
|
|
@@ -884,6 +961,78 @@ export default class N3Parser {
|
|
|
884
961
|
}
|
|
885
962
|
}
|
|
886
963
|
|
|
964
|
+
// ### `_readReifiedTripleTailOrReifier` reads a reifier or the end of a nested reified triple
|
|
965
|
+
_readReifiedTripleTailOrReifier(token) {
|
|
966
|
+
if (token.type === '~') {
|
|
967
|
+
return this._readReifier;
|
|
968
|
+
}
|
|
969
|
+
return this._readReifiedTripleTail(token);
|
|
970
|
+
}
|
|
971
|
+
|
|
972
|
+
// ### `_readReifiedTripleTail` reads the end of a nested reified triple
|
|
973
|
+
_readReifiedTripleTail(token) {
|
|
974
|
+
if (token.type !== '>>')
|
|
975
|
+
return this._error(`Expected >> but got ${token.type}`, token);
|
|
976
|
+
// Read the triple term and restore the previous context
|
|
977
|
+
this._tripleTerm = null;
|
|
978
|
+
const reifier = this._readTripleTerm();
|
|
979
|
+
this._restoreContext('<<', token);
|
|
980
|
+
|
|
981
|
+
// // If we're in a list, continue processing that list
|
|
982
|
+
const stack = this._contextStack, parent = stack.length && stack[stack.length - 1];
|
|
983
|
+
if (parent && parent.type === 'list') {
|
|
984
|
+
this._emit(this._subject, this.RDF_FIRST, reifier, this._graph);
|
|
985
|
+
return this._getContextEndReader();
|
|
986
|
+
}
|
|
987
|
+
// If the triple was the subject, continue by reading the predicate.
|
|
988
|
+
else if (this._subject === null) {
|
|
989
|
+
this._subject = reifier;
|
|
990
|
+
return this._readPredicateOrReifierTripleEnd;
|
|
991
|
+
}
|
|
992
|
+
// If the triple was the object, read context end.
|
|
993
|
+
else {
|
|
994
|
+
this._object = reifier;
|
|
995
|
+
return this._getContextEndReader();
|
|
996
|
+
}
|
|
997
|
+
}
|
|
998
|
+
|
|
999
|
+
_readPredicateOrReifierTripleEnd(token) {
|
|
1000
|
+
if (token.type === '.') {
|
|
1001
|
+
this._subject = null;
|
|
1002
|
+
return this._readPunctuation(token);
|
|
1003
|
+
}
|
|
1004
|
+
return this._readPredicate(token);
|
|
1005
|
+
}
|
|
1006
|
+
|
|
1007
|
+
// ### `_readReifier` reads the triple term identifier after a tilde when in a reifying triple.
|
|
1008
|
+
_readReifier(token) {
|
|
1009
|
+
this._reifier = this._readEntity(token);
|
|
1010
|
+
return this._readReifiedTripleTail;
|
|
1011
|
+
}
|
|
1012
|
+
|
|
1013
|
+
// ### `_readReifier` reads the optional triple term identifier after a tilde when in annotation syntax.
|
|
1014
|
+
_readReifierInAnnotation(token) {
|
|
1015
|
+
// If next token is a reifier, read it as such.
|
|
1016
|
+
if (token.type === 'IRI' || token.type === 'typeIRI' || token.type === 'type' || token.type === 'prefixed' || token.type === 'blank' || token.type === 'var') {
|
|
1017
|
+
this._reifier = this._readEntity(token);
|
|
1018
|
+
return this._readPunctuation;
|
|
1019
|
+
}
|
|
1020
|
+
// Otherwise, emit and assert triple term.
|
|
1021
|
+
this._readTripleTerm();
|
|
1022
|
+
this._subject = null;
|
|
1023
|
+
return this._readPunctuation(token);
|
|
1024
|
+
}
|
|
1025
|
+
|
|
1026
|
+
_readTripleTerm() {
|
|
1027
|
+
const stack = this._contextStack, parent = stack.length && stack[stack.length - 1];
|
|
1028
|
+
const parentGraph = parent ? parent.graph : undefined;
|
|
1029
|
+
const reifier = this._reifier || this._factory.blankNode();
|
|
1030
|
+
this._reifier = null;
|
|
1031
|
+
this._tripleTerm = this._tripleTerm || this._factory.quad(this._subject, this._predicate, this._object);
|
|
1032
|
+
this._emit(reifier, this.RDF_REIFIES, this._tripleTerm, parentGraph || this.DEFAULTGRAPH);
|
|
1033
|
+
return reifier;
|
|
1034
|
+
}
|
|
1035
|
+
|
|
887
1036
|
// ### `_getContextEndReader` gets the next reader function at the end of a context
|
|
888
1037
|
_getContextEndReader() {
|
|
889
1038
|
const contextStack = this._contextStack;
|
|
@@ -897,8 +1046,10 @@ export default class N3Parser {
|
|
|
897
1046
|
return this._readListItem;
|
|
898
1047
|
case 'formula':
|
|
899
1048
|
return this._readFormulaTail;
|
|
1049
|
+
case '<<(':
|
|
1050
|
+
return this._readTripleTermTail;
|
|
900
1051
|
case '<<':
|
|
901
|
-
return this.
|
|
1052
|
+
return this._readReifiedTripleTailOrReifier;
|
|
902
1053
|
}
|
|
903
1054
|
}
|
|
904
1055
|
|
|
@@ -1013,18 +1164,20 @@ export default class N3Parser {
|
|
|
1013
1164
|
// ## Public methods
|
|
1014
1165
|
|
|
1015
1166
|
// ### `parse` parses the N3 input and emits each parsed quad through the onQuad callback.
|
|
1016
|
-
parse(input, quadCallback, prefixCallback) {
|
|
1167
|
+
parse(input, quadCallback, prefixCallback, versionCallback) {
|
|
1017
1168
|
// The second parameter accepts an object { onQuad: ..., onPrefix: ..., onComment: ...}
|
|
1018
1169
|
// As a second and third parameter it still accepts a separate quadCallback and prefixCallback for backward compatibility as well
|
|
1019
|
-
let onQuad, onPrefix, onComment;
|
|
1020
|
-
if (quadCallback && (quadCallback.onQuad || quadCallback.onPrefix || quadCallback.onComment)) {
|
|
1170
|
+
let onQuad, onPrefix, onComment, onVersion;
|
|
1171
|
+
if (quadCallback && (quadCallback.onQuad || quadCallback.onPrefix || quadCallback.onComment || quadCallback.onVersion)) {
|
|
1021
1172
|
onQuad = quadCallback.onQuad;
|
|
1022
1173
|
onPrefix = quadCallback.onPrefix;
|
|
1023
1174
|
onComment = quadCallback.onComment;
|
|
1175
|
+
onVersion = quadCallback.onVersion;
|
|
1024
1176
|
}
|
|
1025
1177
|
else {
|
|
1026
1178
|
onQuad = quadCallback;
|
|
1027
1179
|
onPrefix = prefixCallback;
|
|
1180
|
+
onVersion = versionCallback;
|
|
1028
1181
|
}
|
|
1029
1182
|
// The read callback is the next function to be executed when a token arrives.
|
|
1030
1183
|
// We start reading in the top context.
|
|
@@ -1034,6 +1187,7 @@ export default class N3Parser {
|
|
|
1034
1187
|
this._prefixes._ = this._blankNodePrefix ? this._blankNodePrefix.substr(2)
|
|
1035
1188
|
: `b${blankNodePrefix++}_`;
|
|
1036
1189
|
this._prefixCallback = onPrefix || noop;
|
|
1190
|
+
this._versionCallback = onVersion || noop;
|
|
1037
1191
|
this._inversePredicate = false;
|
|
1038
1192
|
this._quantified = Object.create(null);
|
|
1039
1193
|
|
|
@@ -1089,16 +1243,16 @@ function initDataFactory(parser, factory) {
|
|
|
1089
1243
|
parser.DEFAULTGRAPH = factory.defaultGraph();
|
|
1090
1244
|
|
|
1091
1245
|
// Set common named nodes
|
|
1092
|
-
parser.RDF_FIRST
|
|
1093
|
-
parser.RDF_REST
|
|
1094
|
-
parser.RDF_NIL
|
|
1095
|
-
parser.
|
|
1096
|
-
parser.
|
|
1246
|
+
parser.RDF_FIRST = factory.namedNode(namespaces.rdf.first);
|
|
1247
|
+
parser.RDF_REST = factory.namedNode(namespaces.rdf.rest);
|
|
1248
|
+
parser.RDF_NIL = factory.namedNode(namespaces.rdf.nil);
|
|
1249
|
+
parser.RDF_REIFIES = factory.namedNode(namespaces.rdf.reifies);
|
|
1250
|
+
parser.N3_FORALL = factory.namedNode(namespaces.r.forAll);
|
|
1251
|
+
parser.N3_FORSOME = factory.namedNode(namespaces.r.forSome);
|
|
1097
1252
|
parser.ABBREVIATIONS = {
|
|
1098
1253
|
'a': factory.namedNode(namespaces.rdf.type),
|
|
1099
1254
|
'=': factory.namedNode(namespaces.owl.sameAs),
|
|
1100
1255
|
'>': factory.namedNode(namespaces.log.implies),
|
|
1101
|
-
'<': factory.namedNode(namespaces.log.isImpliedBy),
|
|
1102
1256
|
};
|
|
1103
1257
|
parser.QUANTIFIERS_GRAPH = factory.namedNode('urn:n3:quantifiers');
|
|
1104
1258
|
}
|
package/src/N3Store.js
CHANGED
|
@@ -163,7 +163,7 @@ export default class N3Store {
|
|
|
163
163
|
this._graphs = Object.create(null);
|
|
164
164
|
|
|
165
165
|
// Shift parameters if `quads` is not given
|
|
166
|
-
if (!options && quads && !quads[0]
|
|
166
|
+
if (!options && quads && !quads[0])
|
|
167
167
|
options = quads, quads = null;
|
|
168
168
|
options = options || {};
|
|
169
169
|
this._factory = options.factory || N3DataFactory;
|
|
@@ -175,7 +175,7 @@ export default class N3Store {
|
|
|
175
175
|
|
|
176
176
|
// Add quads if passed
|
|
177
177
|
if (quads)
|
|
178
|
-
this.
|
|
178
|
+
this.addQuads(quads);
|
|
179
179
|
}
|
|
180
180
|
|
|
181
181
|
// ## Public properties
|
|
@@ -601,7 +601,7 @@ export default class N3Store {
|
|
|
601
601
|
// Setting any field to `undefined` or `null` indicates a wildcard.
|
|
602
602
|
some(callback, subject, predicate, object, graph) {
|
|
603
603
|
for (const quad of this.readQuads(subject, predicate, object, graph))
|
|
604
|
-
if (callback(quad
|
|
604
|
+
if (callback(quad))
|
|
605
605
|
return true;
|
|
606
606
|
return false;
|
|
607
607
|
}
|
|
@@ -1134,28 +1134,27 @@ class DatasetCoreAndReadableStream extends Readable {
|
|
|
1134
1134
|
|
|
1135
1135
|
const graphs = n3Store._getGraphs(graph);
|
|
1136
1136
|
for (const graphKey in graphs) {
|
|
1137
|
-
let subjects, predicates, objects
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
}
|
|
1144
|
-
}
|
|
1145
|
-
else if (objectId) {
|
|
1146
|
-
if (objects = indexMatch(content.objects, [objectId, subjectId, predicateId])) {
|
|
1147
|
-
subjects = indexMatch(content.subjects, [subjectId, predicateId, objectId]);
|
|
1148
|
-
predicates = indexMatch(content.predicates, [predicateId, objectId, subjectId]);
|
|
1149
|
-
}
|
|
1137
|
+
let subjects, predicates, objects;
|
|
1138
|
+
|
|
1139
|
+
if (!subjectId && predicateId) {
|
|
1140
|
+
if (predicates = indexMatch(graphs[graphKey].predicates, [predicateId, objectId, subjectId])) {
|
|
1141
|
+
subjects = indexMatch(graphs[graphKey].subjects, [subjectId, predicateId, objectId]);
|
|
1142
|
+
objects = indexMatch(graphs[graphKey].objects, [objectId, subjectId, predicateId]);
|
|
1150
1143
|
}
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1144
|
+
}
|
|
1145
|
+
else if (objectId) {
|
|
1146
|
+
if (objects = indexMatch(graphs[graphKey].objects, [objectId, subjectId, predicateId])) {
|
|
1147
|
+
subjects = indexMatch(graphs[graphKey].subjects, [subjectId, predicateId, objectId]);
|
|
1148
|
+
predicates = indexMatch(graphs[graphKey].predicates, [predicateId, objectId, subjectId]);
|
|
1154
1149
|
}
|
|
1155
|
-
|
|
1156
|
-
if (subjects)
|
|
1157
|
-
newStore._graphs[graphKey] = { subjects, predicates, objects };
|
|
1158
1150
|
}
|
|
1151
|
+
else if (subjects = indexMatch(graphs[graphKey].subjects, [subjectId, predicateId, objectId])) {
|
|
1152
|
+
predicates = indexMatch(graphs[graphKey].predicates, [predicateId, objectId, subjectId]);
|
|
1153
|
+
objects = indexMatch(graphs[graphKey].objects, [objectId, subjectId, predicateId]);
|
|
1154
|
+
}
|
|
1155
|
+
|
|
1156
|
+
if (subjects)
|
|
1157
|
+
newStore._graphs[graphKey] = { subjects, predicates, objects };
|
|
1159
1158
|
}
|
|
1160
1159
|
newStore._size = null;
|
|
1161
1160
|
}
|
package/src/N3Writer.js
CHANGED
|
@@ -2,8 +2,6 @@
|
|
|
2
2
|
import namespaces from './IRIs';
|
|
3
3
|
import { default as N3DataFactory, Term } from './N3DataFactory';
|
|
4
4
|
import { isDefaultGraph } from './N3Util';
|
|
5
|
-
import BaseIRI from './BaseIRI';
|
|
6
|
-
import { escapeRegex } from './Util';
|
|
7
5
|
|
|
8
6
|
const DEFAULTGRAPH = N3DataFactory.defaultGraph();
|
|
9
7
|
|
|
@@ -60,7 +58,9 @@ export default class N3Writer {
|
|
|
60
58
|
this._prefixIRIs = Object.create(null);
|
|
61
59
|
options.prefixes && this.addPrefixes(options.prefixes);
|
|
62
60
|
if (options.baseIRI) {
|
|
63
|
-
this.
|
|
61
|
+
this._baseMatcher = new RegExp(`^${escapeRegex(options.baseIRI)
|
|
62
|
+
}${options.baseIRI.endsWith('/') ? '' : '[#?]'}`);
|
|
63
|
+
this._baseLength = options.baseIRI.length;
|
|
64
64
|
}
|
|
65
65
|
}
|
|
66
66
|
else {
|
|
@@ -153,9 +153,8 @@ export default class N3Writer {
|
|
|
153
153
|
}
|
|
154
154
|
let iri = entity.value;
|
|
155
155
|
// Use relative IRIs if requested and possible
|
|
156
|
-
if (this.
|
|
157
|
-
iri = this.
|
|
158
|
-
}
|
|
156
|
+
if (this._baseMatcher && this._baseMatcher.test(iri))
|
|
157
|
+
iri = iri.substr(this._baseLength);
|
|
159
158
|
// Escape special characters
|
|
160
159
|
if (escape.test(iri))
|
|
161
160
|
iri = iri.replace(escapeAll, characterReplacer);
|
|
@@ -173,8 +172,9 @@ export default class N3Writer {
|
|
|
173
172
|
value = value.replace(escapeAll, characterReplacer);
|
|
174
173
|
|
|
175
174
|
// Write a language-tagged literal
|
|
175
|
+
const direction = literal.direction ? `--${literal.direction}` : '';
|
|
176
176
|
if (literal.language)
|
|
177
|
-
return `"${value}"@${literal.language}`;
|
|
177
|
+
return `"${value}"@${literal.language}${direction}`;
|
|
178
178
|
|
|
179
179
|
// Write dedicated literals per data type
|
|
180
180
|
if (this._lineMode) {
|
|
@@ -395,3 +395,7 @@ function characterReplacer(character) {
|
|
|
395
395
|
}
|
|
396
396
|
return result;
|
|
397
397
|
}
|
|
398
|
+
|
|
399
|
+
function escapeRegex(regex) {
|
|
400
|
+
return regex.replace(/[\]\/\(\)\*\+\?\.\\\$]/g, '\\$&');
|
|
401
|
+
}
|
package/src/index.js
CHANGED
|
@@ -7,7 +7,6 @@ import Reasoner, { getRulesFromDataset } from './N3Reasoner';
|
|
|
7
7
|
import StreamParser from './N3StreamParser';
|
|
8
8
|
import StreamWriter from './N3StreamWriter';
|
|
9
9
|
import * as Util from './N3Util';
|
|
10
|
-
import BaseIRI from './BaseIRI';
|
|
11
10
|
|
|
12
11
|
import {
|
|
13
12
|
default as DataFactory,
|
|
@@ -37,7 +36,6 @@ export {
|
|
|
37
36
|
StreamWriter,
|
|
38
37
|
Util,
|
|
39
38
|
Reasoner,
|
|
40
|
-
BaseIRI,
|
|
41
39
|
|
|
42
40
|
DataFactory,
|
|
43
41
|
|
|
@@ -67,7 +65,6 @@ export default {
|
|
|
67
65
|
StreamWriter,
|
|
68
66
|
Util,
|
|
69
67
|
Reasoner,
|
|
70
|
-
BaseIRI,
|
|
71
68
|
|
|
72
69
|
DataFactory,
|
|
73
70
|
|