n3 1.26.0 → 2.0.0-beta.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 +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 +206 -44
- package/lib/N3Store.js +23 -24
- package/lib/N3Util.js +0 -6
- package/lib/N3Writer.js +11 -9
- package/lib/index.js +2 -9
- 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 +229 -53
- package/src/N3Store.js +21 -22
- package/src/N3Util.js +0 -5
- 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,18 +27,17 @@ 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;
|
|
38
|
+
// Disable parsing of unsupported versions by default
|
|
39
|
+
this._parseUnsupportedVersions = !!options.parseUnsupportedVersions;
|
|
40
|
+
this._version = options.version;
|
|
42
41
|
}
|
|
43
42
|
|
|
44
43
|
// ## Static class methods
|
|
@@ -116,6 +115,13 @@ export default class N3Parser {
|
|
|
116
115
|
}
|
|
117
116
|
}
|
|
118
117
|
|
|
118
|
+
// ### `_readBeforeTopContext` is called once only at the start of parsing.
|
|
119
|
+
_readBeforeTopContext(token) {
|
|
120
|
+
if (this._version && !this._isValidVersion(this._version))
|
|
121
|
+
return this._error(`Detected unsupported version as media type parameter: "${this._version}"`, token);
|
|
122
|
+
return this._readInTopContext(token);
|
|
123
|
+
}
|
|
124
|
+
|
|
119
125
|
// ### `_readInTopContext` reads a token when in the top context
|
|
120
126
|
_readInTopContext(token) {
|
|
121
127
|
switch (token.type) {
|
|
@@ -135,6 +141,11 @@ export default class N3Parser {
|
|
|
135
141
|
this._sparqlStyle = true;
|
|
136
142
|
case '@base':
|
|
137
143
|
return this._readBaseIRI;
|
|
144
|
+
// It could be a version declaration
|
|
145
|
+
case 'VERSION':
|
|
146
|
+
this._sparqlStyle = true;
|
|
147
|
+
case '@version':
|
|
148
|
+
return this._readVersion;
|
|
138
149
|
// It could be a graph
|
|
139
150
|
case '{':
|
|
140
151
|
if (this._supportsNamedGraphs) {
|
|
@@ -199,6 +210,10 @@ export default class N3Parser {
|
|
|
199
210
|
this._subject = this._factory.blankNode(), null, null);
|
|
200
211
|
return this._readBlankNodeHead;
|
|
201
212
|
case '(':
|
|
213
|
+
const stack = this._contextStack, parent = stack.length && stack[stack.length - 1];
|
|
214
|
+
if (parent.type === '<<') {
|
|
215
|
+
return this._error('Unexpected list in reified triple', token);
|
|
216
|
+
}
|
|
202
217
|
// Start a new list
|
|
203
218
|
this._saveContext('list', this._graph, this.RDF_NIL, null, null);
|
|
204
219
|
this._subject = null;
|
|
@@ -239,9 +254,13 @@ export default class N3Parser {
|
|
|
239
254
|
this._subject = this._factory.literal(token.value, this._factory.namedNode(token.prefix));
|
|
240
255
|
|
|
241
256
|
break;
|
|
257
|
+
case '<<(':
|
|
258
|
+
if (!this._n3Mode)
|
|
259
|
+
return this._error('Disallowed triple term as subject', token);
|
|
260
|
+
this._saveContext('<<(', this._graph, null, null, null);
|
|
261
|
+
this._graph = null;
|
|
262
|
+
return this._readSubject;
|
|
242
263
|
case '<<':
|
|
243
|
-
if (!this._supportsRDFStar)
|
|
244
|
-
return this._error('Unexpected RDF-star syntax', token);
|
|
245
264
|
this._saveContext('<<', this._graph, null, null, null);
|
|
246
265
|
this._graph = null;
|
|
247
266
|
return this._readSubject;
|
|
@@ -271,6 +290,7 @@ export default class N3Parser {
|
|
|
271
290
|
case '.':
|
|
272
291
|
case ']':
|
|
273
292
|
case '}':
|
|
293
|
+
case '|}':
|
|
274
294
|
// Expected predicate didn't come, must have been trailing semicolon
|
|
275
295
|
if (this._predicate === null)
|
|
276
296
|
return this._error(`Unexpected ${type}`, token);
|
|
@@ -317,6 +337,10 @@ export default class N3Parser {
|
|
|
317
337
|
this._subject = this._factory.blankNode());
|
|
318
338
|
return this._readBlankNodeHead;
|
|
319
339
|
case '(':
|
|
340
|
+
const stack = this._contextStack, parent = stack.length && stack[stack.length - 1];
|
|
341
|
+
if (parent.type === '<<') {
|
|
342
|
+
return this._error('Unexpected list in reified triple', token);
|
|
343
|
+
}
|
|
320
344
|
// Start a new list
|
|
321
345
|
this._saveContext('list', this._graph, this._subject, this._predicate, this.RDF_NIL);
|
|
322
346
|
this._subject = null;
|
|
@@ -328,9 +352,11 @@ export default class N3Parser {
|
|
|
328
352
|
this._saveContext('formula', this._graph, this._subject, this._predicate,
|
|
329
353
|
this._graph = this._factory.blankNode());
|
|
330
354
|
return this._readSubject;
|
|
355
|
+
case '<<(':
|
|
356
|
+
this._saveContext('<<(', this._graph, this._subject, this._predicate, null);
|
|
357
|
+
this._graph = null;
|
|
358
|
+
return this._readSubject;
|
|
331
359
|
case '<<':
|
|
332
|
-
if (!this._supportsRDFStar)
|
|
333
|
-
return this._error('Unexpected RDF-star syntax', token);
|
|
334
360
|
this._saveContext('<<', this._graph, this._subject, this._predicate, null);
|
|
335
361
|
this._graph = null;
|
|
336
362
|
return this._readSubject;
|
|
@@ -366,6 +392,10 @@ export default class N3Parser {
|
|
|
366
392
|
return this._readBlankNodeTail(token);
|
|
367
393
|
}
|
|
368
394
|
else {
|
|
395
|
+
const stack = this._contextStack, parentParent = stack.length > 1 && stack[stack.length - 2];
|
|
396
|
+
if (parentParent.type === '<<') {
|
|
397
|
+
return this._error('Unexpected compound blank node expression in reified triple', token);
|
|
398
|
+
}
|
|
369
399
|
this._predicate = null;
|
|
370
400
|
return this._readPredicate(token);
|
|
371
401
|
}
|
|
@@ -475,6 +505,11 @@ export default class N3Parser {
|
|
|
475
505
|
this._saveContext('formula', this._graph, this._subject, this._predicate,
|
|
476
506
|
this._graph = this._factory.blankNode());
|
|
477
507
|
return this._readSubject;
|
|
508
|
+
case '<<':
|
|
509
|
+
this._saveContext('<<', this._graph, null, null, null);
|
|
510
|
+
this._graph = null;
|
|
511
|
+
next = this._readSubject;
|
|
512
|
+
break;
|
|
478
513
|
default:
|
|
479
514
|
if ((item = this._readEntity(token)) === undefined)
|
|
480
515
|
return;
|
|
@@ -484,6 +519,10 @@ export default class N3Parser {
|
|
|
484
519
|
if (list === null)
|
|
485
520
|
this._subject = list = this._factory.blankNode();
|
|
486
521
|
|
|
522
|
+
// When reading a reified triple, store the list as subject in the stack, as this will be overridden when reading the triple.
|
|
523
|
+
if (token.type === '<<')
|
|
524
|
+
stack[stack.length - 1].subject = this._subject;
|
|
525
|
+
|
|
487
526
|
// Is this the first element of the list?
|
|
488
527
|
if (previousList === null) {
|
|
489
528
|
// This list is either the subject or the object of its parent
|
|
@@ -524,9 +563,10 @@ export default class N3Parser {
|
|
|
524
563
|
}
|
|
525
564
|
|
|
526
565
|
// ### `_completeLiteral` completes a literal with an optional datatype or language
|
|
527
|
-
_completeLiteral(token) {
|
|
566
|
+
_completeLiteral(token, component) {
|
|
528
567
|
// Create a simple string literal by default
|
|
529
568
|
let literal = this._factory.literal(this._literalValue);
|
|
569
|
+
let readCb;
|
|
530
570
|
|
|
531
571
|
switch (token.type) {
|
|
532
572
|
// Create a datatyped literal
|
|
@@ -534,43 +574,82 @@ export default class N3Parser {
|
|
|
534
574
|
case 'typeIRI':
|
|
535
575
|
const datatype = this._readEntity(token);
|
|
536
576
|
if (datatype === undefined) return; // No datatype means an error occurred
|
|
577
|
+
if (datatype.value === namespaces.rdf.langString || datatype.value === namespaces.rdf.dirLangString) {
|
|
578
|
+
return this._error('Detected illegal (directional) languaged-tagged string with explicit datatype', token);
|
|
579
|
+
}
|
|
537
580
|
literal = this._factory.literal(this._literalValue, datatype);
|
|
538
581
|
token = null;
|
|
539
582
|
break;
|
|
540
583
|
// Create a language-tagged string
|
|
541
584
|
case 'langcode':
|
|
585
|
+
if (token.value.length > 8)
|
|
586
|
+
return this._error('Detected language tag of length larger than 8', token);
|
|
542
587
|
literal = this._factory.literal(this._literalValue, token.value);
|
|
588
|
+
this._literalLanguage = token.value;
|
|
543
589
|
token = null;
|
|
590
|
+
readCb = this._readDirCode.bind(this, component);
|
|
544
591
|
break;
|
|
545
592
|
}
|
|
546
593
|
|
|
547
|
-
return { token, literal };
|
|
594
|
+
return { token, literal, readCb };
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
_readDirCode(component, listItem, token) {
|
|
598
|
+
// Attempt to read a dircode
|
|
599
|
+
if (token.type === 'dircode') {
|
|
600
|
+
const term = this._factory.literal(this._literalValue, { language: this._literalLanguage, direction: token.value });
|
|
601
|
+
if (component === 'subject')
|
|
602
|
+
this._subject = term;
|
|
603
|
+
else
|
|
604
|
+
this._object = term;
|
|
605
|
+
this._literalLanguage = undefined;
|
|
606
|
+
token = null;
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
if (component === 'subject')
|
|
610
|
+
return token === null ? this._readPredicateOrNamedGraph : this._readPredicateOrNamedGraph(token);
|
|
611
|
+
return this._completeObjectLiteralPost(token, listItem);
|
|
548
612
|
}
|
|
549
613
|
|
|
550
614
|
// Completes a literal in subject position
|
|
551
615
|
_completeSubjectLiteral(token) {
|
|
552
|
-
|
|
616
|
+
const completed = this._completeLiteral(token, 'subject');
|
|
617
|
+
this._subject = completed.literal;
|
|
618
|
+
|
|
619
|
+
// Postpone completion if the literal is only partially completed (such as lang+dir).
|
|
620
|
+
if (completed.readCb)
|
|
621
|
+
return completed.readCb.bind(this, false);
|
|
622
|
+
|
|
553
623
|
return this._readPredicateOrNamedGraph;
|
|
554
624
|
}
|
|
555
625
|
|
|
556
626
|
// Completes a literal in object position
|
|
557
627
|
_completeObjectLiteral(token, listItem) {
|
|
558
|
-
const completed = this._completeLiteral(token);
|
|
628
|
+
const completed = this._completeLiteral(token, 'object');
|
|
559
629
|
if (!completed)
|
|
560
630
|
return;
|
|
631
|
+
|
|
561
632
|
this._object = completed.literal;
|
|
562
633
|
|
|
634
|
+
// Postpone completion if the literal is only partially completed (such as lang+dir).
|
|
635
|
+
if (completed.readCb)
|
|
636
|
+
return completed.readCb.bind(this, listItem);
|
|
637
|
+
|
|
638
|
+
return this._completeObjectLiteralPost(completed.token, listItem);
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
_completeObjectLiteralPost(token, listItem) {
|
|
563
642
|
// If this literal was part of a list, write the item
|
|
564
643
|
// (we could also check the context stack, but passing in a flag is faster)
|
|
565
644
|
if (listItem)
|
|
566
645
|
this._emit(this._subject, this.RDF_FIRST, this._object, this._graph);
|
|
567
646
|
// If the token was consumed, continue with the rest of the input
|
|
568
|
-
if (
|
|
647
|
+
if (token === null)
|
|
569
648
|
return this._getContextEndReader();
|
|
570
649
|
// Otherwise, consume the token now
|
|
571
650
|
else {
|
|
572
651
|
this._readCallback = this._getContextEndReader();
|
|
573
|
-
return this._readCallback(
|
|
652
|
+
return this._readCallback(token);
|
|
574
653
|
}
|
|
575
654
|
}
|
|
576
655
|
|
|
@@ -592,7 +671,7 @@ export default class N3Parser {
|
|
|
592
671
|
|
|
593
672
|
// ### `_readPunctuation` reads punctuation between quads or quad parts
|
|
594
673
|
_readPunctuation(token) {
|
|
595
|
-
let next, graph = this._graph;
|
|
674
|
+
let next, graph = this._graph, startingAnnotation = false;
|
|
596
675
|
const subject = this._subject, inversePredicate = this._inversePredicate;
|
|
597
676
|
switch (token.type) {
|
|
598
677
|
// A closing brace ends a graph
|
|
@@ -605,6 +684,7 @@ export default class N3Parser {
|
|
|
605
684
|
// A dot just ends the statement, without sharing anything with the next
|
|
606
685
|
case '.':
|
|
607
686
|
this._subject = null;
|
|
687
|
+
this._tripleTerm = null;
|
|
608
688
|
next = this._contextStack.length ? this._readSubject : this._readInTopContext;
|
|
609
689
|
if (inversePredicate) this._inversePredicate = false;
|
|
610
690
|
break;
|
|
@@ -616,20 +696,24 @@ export default class N3Parser {
|
|
|
616
696
|
case ',':
|
|
617
697
|
next = this._readObject;
|
|
618
698
|
break;
|
|
699
|
+
// ~ is allowed in the annotation syntax
|
|
700
|
+
case '~':
|
|
701
|
+
next = this._readReifierInAnnotation;
|
|
702
|
+
startingAnnotation = true;
|
|
703
|
+
break;
|
|
619
704
|
// {| means that the current triple is annotated with predicate-object pairs.
|
|
620
705
|
case '{|':
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
const predicate = this._predicate, object = this._object;
|
|
625
|
-
this._subject = this._factory.quad(subject, predicate, object, this.DEFAULTGRAPH);
|
|
706
|
+
// Continue using the last triple as reified triple subject for the predicate-object pairs.
|
|
707
|
+
this._subject = this._readTripleTerm();
|
|
708
|
+
startingAnnotation = true;
|
|
626
709
|
next = this._readPredicate;
|
|
627
710
|
break;
|
|
628
|
-
// |} means that the current
|
|
711
|
+
// |} means that the current reified triple in annotation syntax is finalized.
|
|
629
712
|
case '|}':
|
|
630
|
-
if (this.
|
|
631
|
-
return this._error('Unexpected
|
|
713
|
+
if (!this._annotation)
|
|
714
|
+
return this._error('Unexpected annotation syntax closing', token);
|
|
632
715
|
this._subject = null;
|
|
716
|
+
this._annotation = false;
|
|
633
717
|
next = this._readPunctuation;
|
|
634
718
|
break;
|
|
635
719
|
default:
|
|
@@ -641,13 +725,16 @@ export default class N3Parser {
|
|
|
641
725
|
return this._error(`Expected punctuation to follow "${this._object.id}"`, token);
|
|
642
726
|
}
|
|
643
727
|
// A quad has been completed now, so return it
|
|
644
|
-
if (subject !== null) {
|
|
728
|
+
if (subject !== null && (!startingAnnotation || (startingAnnotation && !this._annotation))) {
|
|
645
729
|
const predicate = this._predicate, object = this._object;
|
|
646
730
|
if (!inversePredicate)
|
|
647
731
|
this._emit(subject, predicate, object, graph);
|
|
648
732
|
else
|
|
649
733
|
this._emit(object, predicate, subject, graph);
|
|
650
734
|
}
|
|
735
|
+
if (startingAnnotation) {
|
|
736
|
+
this._annotation = true;
|
|
737
|
+
}
|
|
651
738
|
return next;
|
|
652
739
|
}
|
|
653
740
|
|
|
@@ -705,6 +792,23 @@ export default class N3Parser {
|
|
|
705
792
|
return this._readDeclarationPunctuation;
|
|
706
793
|
}
|
|
707
794
|
|
|
795
|
+
// ### `_isValidVersion` checks if the given version is valid for this parser to handle.
|
|
796
|
+
_isValidVersion(version) {
|
|
797
|
+
return this._parseUnsupportedVersions || N3Parser.SUPPORTED_VERSIONS.includes(version);
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
// ### `_readVersion` reads version string declaration
|
|
801
|
+
_readVersion(token) {
|
|
802
|
+
if (token.type !== 'literal')
|
|
803
|
+
return this._error('Expected literal to follow version declaration', token);
|
|
804
|
+
if ((token.end - token.start) !== token.value.length + 2)
|
|
805
|
+
return this._error('Version declarations must use single quotes', token);
|
|
806
|
+
this._versionCallback(token.value);
|
|
807
|
+
if (!this._isValidVersion(token.value))
|
|
808
|
+
return this._error(`Detected unsupported version: "${token.value}"`, token);
|
|
809
|
+
return this._readDeclarationPunctuation;
|
|
810
|
+
}
|
|
811
|
+
|
|
708
812
|
// ### `_readNamedGraphLabel` reads the label of a named graph
|
|
709
813
|
_readNamedGraphLabel(token) {
|
|
710
814
|
switch (token.type) {
|
|
@@ -853,25 +957,15 @@ export default class N3Parser {
|
|
|
853
957
|
return this._readPath;
|
|
854
958
|
}
|
|
855
959
|
|
|
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);
|
|
960
|
+
// ### `_readTripleTermTail` reads the end of a triple term
|
|
961
|
+
_readTripleTermTail(token) {
|
|
962
|
+
if (token.type !== ')>>')
|
|
963
|
+
return this._error(`Expected )>> but got ${token.type}`, token);
|
|
871
964
|
// Read the quad and restore the previous context
|
|
872
965
|
const quad = this._factory.quad(this._subject, this._predicate, this._object,
|
|
873
|
-
|
|
874
|
-
this._restoreContext('<<', token);
|
|
966
|
+
this._graph || this.DEFAULTGRAPH);
|
|
967
|
+
this._restoreContext('<<(', token);
|
|
968
|
+
|
|
875
969
|
// If the triple was the subject, continue by reading the predicate.
|
|
876
970
|
if (this._subject === null) {
|
|
877
971
|
this._subject = quad;
|
|
@@ -884,6 +978,78 @@ export default class N3Parser {
|
|
|
884
978
|
}
|
|
885
979
|
}
|
|
886
980
|
|
|
981
|
+
// ### `_readReifiedTripleTailOrReifier` reads a reifier or the end of a nested reified triple
|
|
982
|
+
_readReifiedTripleTailOrReifier(token) {
|
|
983
|
+
if (token.type === '~') {
|
|
984
|
+
return this._readReifier;
|
|
985
|
+
}
|
|
986
|
+
return this._readReifiedTripleTail(token);
|
|
987
|
+
}
|
|
988
|
+
|
|
989
|
+
// ### `_readReifiedTripleTail` reads the end of a nested reified triple
|
|
990
|
+
_readReifiedTripleTail(token) {
|
|
991
|
+
if (token.type !== '>>')
|
|
992
|
+
return this._error(`Expected >> but got ${token.type}`, token);
|
|
993
|
+
// Read the triple term and restore the previous context
|
|
994
|
+
this._tripleTerm = null;
|
|
995
|
+
const reifier = this._readTripleTerm();
|
|
996
|
+
this._restoreContext('<<', token);
|
|
997
|
+
|
|
998
|
+
// // If we're in a list, continue processing that list
|
|
999
|
+
const stack = this._contextStack, parent = stack.length && stack[stack.length - 1];
|
|
1000
|
+
if (parent && parent.type === 'list') {
|
|
1001
|
+
this._emit(this._subject, this.RDF_FIRST, reifier, this._graph);
|
|
1002
|
+
return this._getContextEndReader();
|
|
1003
|
+
}
|
|
1004
|
+
// If the triple was the subject, continue by reading the predicate.
|
|
1005
|
+
else if (this._subject === null) {
|
|
1006
|
+
this._subject = reifier;
|
|
1007
|
+
return this._readPredicateOrReifierTripleEnd;
|
|
1008
|
+
}
|
|
1009
|
+
// If the triple was the object, read context end.
|
|
1010
|
+
else {
|
|
1011
|
+
this._object = reifier;
|
|
1012
|
+
return this._getContextEndReader();
|
|
1013
|
+
}
|
|
1014
|
+
}
|
|
1015
|
+
|
|
1016
|
+
_readPredicateOrReifierTripleEnd(token) {
|
|
1017
|
+
if (token.type === '.') {
|
|
1018
|
+
this._subject = null;
|
|
1019
|
+
return this._readPunctuation(token);
|
|
1020
|
+
}
|
|
1021
|
+
return this._readPredicate(token);
|
|
1022
|
+
}
|
|
1023
|
+
|
|
1024
|
+
// ### `_readReifier` reads the triple term identifier after a tilde when in a reifying triple.
|
|
1025
|
+
_readReifier(token) {
|
|
1026
|
+
this._reifier = this._readEntity(token);
|
|
1027
|
+
return this._readReifiedTripleTail;
|
|
1028
|
+
}
|
|
1029
|
+
|
|
1030
|
+
// ### `_readReifier` reads the optional triple term identifier after a tilde when in annotation syntax.
|
|
1031
|
+
_readReifierInAnnotation(token) {
|
|
1032
|
+
// If next token is a reifier, read it as such.
|
|
1033
|
+
if (token.type === 'IRI' || token.type === 'typeIRI' || token.type === 'type' || token.type === 'prefixed' || token.type === 'blank' || token.type === 'var') {
|
|
1034
|
+
this._reifier = this._readEntity(token);
|
|
1035
|
+
return this._readPunctuation;
|
|
1036
|
+
}
|
|
1037
|
+
// Otherwise, emit and assert triple term.
|
|
1038
|
+
this._readTripleTerm();
|
|
1039
|
+
this._subject = null;
|
|
1040
|
+
return this._readPunctuation(token);
|
|
1041
|
+
}
|
|
1042
|
+
|
|
1043
|
+
_readTripleTerm() {
|
|
1044
|
+
const stack = this._contextStack, parent = stack.length && stack[stack.length - 1];
|
|
1045
|
+
const parentGraph = parent ? parent.graph : undefined;
|
|
1046
|
+
const reifier = this._reifier || this._factory.blankNode();
|
|
1047
|
+
this._reifier = null;
|
|
1048
|
+
this._tripleTerm = this._tripleTerm || this._factory.quad(this._subject, this._predicate, this._object);
|
|
1049
|
+
this._emit(reifier, this.RDF_REIFIES, this._tripleTerm, parentGraph || this.DEFAULTGRAPH);
|
|
1050
|
+
return reifier;
|
|
1051
|
+
}
|
|
1052
|
+
|
|
887
1053
|
// ### `_getContextEndReader` gets the next reader function at the end of a context
|
|
888
1054
|
_getContextEndReader() {
|
|
889
1055
|
const contextStack = this._contextStack;
|
|
@@ -897,8 +1063,10 @@ export default class N3Parser {
|
|
|
897
1063
|
return this._readListItem;
|
|
898
1064
|
case 'formula':
|
|
899
1065
|
return this._readFormulaTail;
|
|
1066
|
+
case '<<(':
|
|
1067
|
+
return this._readTripleTermTail;
|
|
900
1068
|
case '<<':
|
|
901
|
-
return this.
|
|
1069
|
+
return this._readReifiedTripleTailOrReifier;
|
|
902
1070
|
}
|
|
903
1071
|
}
|
|
904
1072
|
|
|
@@ -1013,27 +1181,30 @@ export default class N3Parser {
|
|
|
1013
1181
|
// ## Public methods
|
|
1014
1182
|
|
|
1015
1183
|
// ### `parse` parses the N3 input and emits each parsed quad through the onQuad callback.
|
|
1016
|
-
parse(input, quadCallback, prefixCallback) {
|
|
1184
|
+
parse(input, quadCallback, prefixCallback, versionCallback) {
|
|
1017
1185
|
// The second parameter accepts an object { onQuad: ..., onPrefix: ..., onComment: ...}
|
|
1018
1186
|
// 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)) {
|
|
1187
|
+
let onQuad, onPrefix, onComment, onVersion;
|
|
1188
|
+
if (quadCallback && (quadCallback.onQuad || quadCallback.onPrefix || quadCallback.onComment || quadCallback.onVersion)) {
|
|
1021
1189
|
onQuad = quadCallback.onQuad;
|
|
1022
1190
|
onPrefix = quadCallback.onPrefix;
|
|
1023
1191
|
onComment = quadCallback.onComment;
|
|
1192
|
+
onVersion = quadCallback.onVersion;
|
|
1024
1193
|
}
|
|
1025
1194
|
else {
|
|
1026
1195
|
onQuad = quadCallback;
|
|
1027
1196
|
onPrefix = prefixCallback;
|
|
1197
|
+
onVersion = versionCallback;
|
|
1028
1198
|
}
|
|
1029
1199
|
// The read callback is the next function to be executed when a token arrives.
|
|
1030
1200
|
// We start reading in the top context.
|
|
1031
|
-
this._readCallback = this.
|
|
1201
|
+
this._readCallback = this._readBeforeTopContext;
|
|
1032
1202
|
this._sparqlStyle = false;
|
|
1033
1203
|
this._prefixes = Object.create(null);
|
|
1034
1204
|
this._prefixes._ = this._blankNodePrefix ? this._blankNodePrefix.substr(2)
|
|
1035
1205
|
: `b${blankNodePrefix++}_`;
|
|
1036
1206
|
this._prefixCallback = onPrefix || noop;
|
|
1207
|
+
this._versionCallback = onVersion || noop;
|
|
1037
1208
|
this._inversePredicate = false;
|
|
1038
1209
|
this._quantified = Object.create(null);
|
|
1039
1210
|
|
|
@@ -1089,17 +1260,22 @@ function initDataFactory(parser, factory) {
|
|
|
1089
1260
|
parser.DEFAULTGRAPH = factory.defaultGraph();
|
|
1090
1261
|
|
|
1091
1262
|
// Set common named nodes
|
|
1092
|
-
parser.RDF_FIRST
|
|
1093
|
-
parser.RDF_REST
|
|
1094
|
-
parser.RDF_NIL
|
|
1095
|
-
parser.
|
|
1096
|
-
parser.
|
|
1263
|
+
parser.RDF_FIRST = factory.namedNode(namespaces.rdf.first);
|
|
1264
|
+
parser.RDF_REST = factory.namedNode(namespaces.rdf.rest);
|
|
1265
|
+
parser.RDF_NIL = factory.namedNode(namespaces.rdf.nil);
|
|
1266
|
+
parser.RDF_REIFIES = factory.namedNode(namespaces.rdf.reifies);
|
|
1267
|
+
parser.N3_FORALL = factory.namedNode(namespaces.r.forAll);
|
|
1268
|
+
parser.N3_FORSOME = factory.namedNode(namespaces.r.forSome);
|
|
1097
1269
|
parser.ABBREVIATIONS = {
|
|
1098
1270
|
'a': factory.namedNode(namespaces.rdf.type),
|
|
1099
1271
|
'=': factory.namedNode(namespaces.owl.sameAs),
|
|
1100
1272
|
'>': factory.namedNode(namespaces.log.implies),
|
|
1101
|
-
'<': factory.namedNode(namespaces.log.isImpliedBy),
|
|
1102
1273
|
};
|
|
1103
1274
|
parser.QUANTIFIERS_GRAPH = factory.namedNode('urn:n3:quantifiers');
|
|
1104
1275
|
}
|
|
1276
|
+
N3Parser.SUPPORTED_VERSIONS = [
|
|
1277
|
+
'1.2',
|
|
1278
|
+
'1.2-basic',
|
|
1279
|
+
'1.1',
|
|
1280
|
+
];
|
|
1105
1281
|
initDataFactory(N3Parser.prototype, N3DataFactory);
|
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/N3Util.js
CHANGED
|
@@ -22,11 +22,6 @@ export function isVariable(term) {
|
|
|
22
22
|
return !!term && term.termType === 'Variable';
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
// Tests whether the given term represents a quad
|
|
26
|
-
export function isQuad(term) {
|
|
27
|
-
return !!term && term.termType === 'Quad';
|
|
28
|
-
}
|
|
29
|
-
|
|
30
25
|
// Tests whether the given term represents the default graph
|
|
31
26
|
export function isDefaultGraph(term) {
|
|
32
27
|
return !!term && term.termType === 'DefaultGraph';
|
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
|
|