n3 2.4.0 → 2.6.0
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 +10 -0
- package/browser/n3.esm.min.js +4 -4
- package/browser/n3.min.js +1 -1
- package/lib/N3Lexer.js +5 -0
- package/lib/N3Parser.js +26 -0
- package/package.json +1 -1
- package/src/N3Lexer.js +9 -0
- package/src/N3Parser.js +35 -0
package/lib/N3Lexer.js
CHANGED
|
@@ -88,6 +88,7 @@ class N3Lexer {
|
|
|
88
88
|
this._boolean = /^(?:true|false)(?=[.,;!\^\s#()\[\]\{\}"'<>])/;
|
|
89
89
|
this._atKeyword = /^@[a-z]+(?=[\s#<:])/i;
|
|
90
90
|
this._keyword = /^(?:PREFIX|BASE|VERSION|GRAPH)(?=[\s#<])/i;
|
|
91
|
+
this._n3Id = /^id(?=[\s#<])/;
|
|
91
92
|
this._shortPredicates = /^a(?=[\s#()\[\]\{\}"'<>])/;
|
|
92
93
|
this._newline = /^[ \t]*(?:#[^\n\r]*)?(?:\r\n|\n|\r)[ \t]*/;
|
|
93
94
|
this._comment = /#([^\n\r]*)/;
|
|
@@ -315,6 +316,10 @@ class N3Lexer {
|
|
|
315
316
|
// Try to find an abbreviated predicate
|
|
316
317
|
if (match = this._shortPredicates.exec(input)) type = 'abbreviation', value = 'a';else inconclusive = true;
|
|
317
318
|
break;
|
|
319
|
+
case 'i':
|
|
320
|
+
// Try to find the IRI property list identifier
|
|
321
|
+
if (this._n3Mode && (match = this._n3Id.exec(input))) type = 'id';else inconclusive = true;
|
|
322
|
+
break;
|
|
318
323
|
case '=':
|
|
319
324
|
// Try to find an implication arrow or equals sign
|
|
320
325
|
if (this._n3Mode && input.length > 1) {
|
package/lib/N3Parser.js
CHANGED
|
@@ -36,6 +36,8 @@ class N3Parser {
|
|
|
36
36
|
this._supportsQuads = !(isTurtle || isTriG || isNTriples || isN3);
|
|
37
37
|
// Whether the log:isImpliedBy predicate is supported
|
|
38
38
|
this._isImpliedBy = options.isImpliedBy;
|
|
39
|
+
// Whether an undeclared empty prefix resolves against the document IRI
|
|
40
|
+
this._implicitEmptyPrefix = !!options.implicitEmptyPrefix;
|
|
39
41
|
// Whether an empty formula is read as the boolean literal true,
|
|
40
42
|
// as in the N3 spec tests (opt-in until the next major version)
|
|
41
43
|
this._emptyFormulaAsTrue = !!options.emptyFormulaAsTrue;
|
|
@@ -457,11 +459,33 @@ class N3Parser {
|
|
|
457
459
|
if (parentParent.type === '<<') {
|
|
458
460
|
return this._error('Unexpected compound blank node expression in reified triple', token);
|
|
459
461
|
}
|
|
462
|
+
if (token.type === 'id') return this._readIriPropertyListId;
|
|
460
463
|
this._predicate = null;
|
|
461
464
|
return this._readPredicate(token);
|
|
462
465
|
}
|
|
463
466
|
}
|
|
464
467
|
|
|
468
|
+
// ### `_readIriPropertyListId` replaces a property list's blank node with its IRI
|
|
469
|
+
_readIriPropertyListId(token) {
|
|
470
|
+
const iri = this._readEntity(token);
|
|
471
|
+
if (iri === undefined) return;
|
|
472
|
+
if (iri.termType !== 'NamedNode') return this._error(`Expected IRI after id but got ${token.type}`, token);
|
|
473
|
+
const placeholder = this._subject;
|
|
474
|
+
this._subject = iri;
|
|
475
|
+
const context = this._contextStack[this._contextStack.length - 1];
|
|
476
|
+
if (context.subject === placeholder) context.subject = iri;
|
|
477
|
+
if (context.predicate === placeholder) context.predicate = iri;
|
|
478
|
+
if (context.object === placeholder) context.object = iri;
|
|
479
|
+
this._predicate = null;
|
|
480
|
+
return this._readIriPropertyListPredicate;
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
// ### `_readIriPropertyListPredicate` requires properties after an IRI property list ID
|
|
484
|
+
_readIriPropertyListPredicate(token) {
|
|
485
|
+
if (token.type === ';' || token.type === ']' || token.type === '.' || token.type === '}') return this._error(`Expected predicate but got ${token.type}`, token);
|
|
486
|
+
return this._readPredicate(token);
|
|
487
|
+
}
|
|
488
|
+
|
|
465
489
|
// ### `_readBlankNodeTail` reads the end of a blank node
|
|
466
490
|
_readBlankNodeTail(token) {
|
|
467
491
|
if (token.type !== ']') return this._readBlankNodePunctuation(token);
|
|
@@ -1384,6 +1408,8 @@ class N3Parser {
|
|
|
1384
1408
|
this._sparqlStyle = false;
|
|
1385
1409
|
this._prefixes = Object.create(null);
|
|
1386
1410
|
this._prefixes._ = this._blankNodePrefix ? this._blankNodePrefix.substr(2) : `b${blankNodePrefix++}_`;
|
|
1411
|
+
// Optionally bind the N3 empty prefix to the document's local namespace
|
|
1412
|
+
if (this._n3Mode && this._implicitEmptyPrefix && this._base) this._prefixes[''] = this._resolveIRI('#');
|
|
1387
1413
|
this._prefixCallback = onPrefix || noop;
|
|
1388
1414
|
this._versionCallback = onVersion || noop;
|
|
1389
1415
|
this._inversePredicate = false;
|
package/package.json
CHANGED
package/src/N3Lexer.js
CHANGED
|
@@ -57,6 +57,7 @@ export default class N3Lexer {
|
|
|
57
57
|
this._boolean = /^(?:true|false)(?=[.,;!\^\s#()\[\]\{\}"'<>])/;
|
|
58
58
|
this._atKeyword = /^@[a-z]+(?=[\s#<:])/i;
|
|
59
59
|
this._keyword = /^(?:PREFIX|BASE|VERSION|GRAPH)(?=[\s#<])/i;
|
|
60
|
+
this._n3Id = /^id(?=[\s#<])/;
|
|
60
61
|
this._shortPredicates = /^a(?=[\s#()\[\]\{\}"'<>])/;
|
|
61
62
|
this._newline = /^[ \t]*(?:#[^\n\r]*)?(?:\r\n|\n|\r)[ \t]*/;
|
|
62
63
|
this._comment = /#([^\n\r]*)/;
|
|
@@ -318,6 +319,14 @@ export default class N3Lexer {
|
|
|
318
319
|
inconclusive = true;
|
|
319
320
|
break;
|
|
320
321
|
|
|
322
|
+
case 'i':
|
|
323
|
+
// Try to find the IRI property list identifier
|
|
324
|
+
if (this._n3Mode && (match = this._n3Id.exec(input)))
|
|
325
|
+
type = 'id';
|
|
326
|
+
else
|
|
327
|
+
inconclusive = true;
|
|
328
|
+
break;
|
|
329
|
+
|
|
321
330
|
case '=':
|
|
322
331
|
// Try to find an implication arrow or equals sign
|
|
323
332
|
if (this._n3Mode && input.length > 1) {
|
package/src/N3Parser.js
CHANGED
|
@@ -29,6 +29,8 @@ export default class N3Parser {
|
|
|
29
29
|
this._supportsQuads = !(isTurtle || isTriG || isNTriples || isN3);
|
|
30
30
|
// Whether the log:isImpliedBy predicate is supported
|
|
31
31
|
this._isImpliedBy = options.isImpliedBy;
|
|
32
|
+
// Whether an undeclared empty prefix resolves against the document IRI
|
|
33
|
+
this._implicitEmptyPrefix = !!options.implicitEmptyPrefix;
|
|
32
34
|
// Whether an empty formula is read as the boolean literal true,
|
|
33
35
|
// as in the N3 spec tests (opt-in until the next major version)
|
|
34
36
|
this._emptyFormulaAsTrue = !!options.emptyFormulaAsTrue;
|
|
@@ -480,11 +482,41 @@ export default class N3Parser {
|
|
|
480
482
|
if (parentParent.type === '<<') {
|
|
481
483
|
return this._error('Unexpected compound blank node expression in reified triple', token);
|
|
482
484
|
}
|
|
485
|
+
if (token.type === 'id')
|
|
486
|
+
return this._readIriPropertyListId;
|
|
483
487
|
this._predicate = null;
|
|
484
488
|
return this._readPredicate(token);
|
|
485
489
|
}
|
|
486
490
|
}
|
|
487
491
|
|
|
492
|
+
// ### `_readIriPropertyListId` replaces a property list's blank node with its IRI
|
|
493
|
+
_readIriPropertyListId(token) {
|
|
494
|
+
const iri = this._readEntity(token);
|
|
495
|
+
if (iri === undefined)
|
|
496
|
+
return;
|
|
497
|
+
if (iri.termType !== 'NamedNode')
|
|
498
|
+
return this._error(`Expected IRI after id but got ${token.type}`, token);
|
|
499
|
+
|
|
500
|
+
const placeholder = this._subject;
|
|
501
|
+
this._subject = iri;
|
|
502
|
+
const context = this._contextStack[this._contextStack.length - 1];
|
|
503
|
+
if (context.subject === placeholder)
|
|
504
|
+
context.subject = iri;
|
|
505
|
+
if (context.predicate === placeholder)
|
|
506
|
+
context.predicate = iri;
|
|
507
|
+
if (context.object === placeholder)
|
|
508
|
+
context.object = iri;
|
|
509
|
+
this._predicate = null;
|
|
510
|
+
return this._readIriPropertyListPredicate;
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
// ### `_readIriPropertyListPredicate` requires properties after an IRI property list ID
|
|
514
|
+
_readIriPropertyListPredicate(token) {
|
|
515
|
+
if (token.type === ';' || token.type === ']' || token.type === '.' || token.type === '}')
|
|
516
|
+
return this._error(`Expected predicate but got ${token.type}`, token);
|
|
517
|
+
return this._readPredicate(token);
|
|
518
|
+
}
|
|
519
|
+
|
|
488
520
|
// ### `_readBlankNodeTail` reads the end of a blank node
|
|
489
521
|
_readBlankNodeTail(token) {
|
|
490
522
|
if (token.type !== ']')
|
|
@@ -1492,6 +1524,9 @@ export default class N3Parser {
|
|
|
1492
1524
|
this._prefixes = Object.create(null);
|
|
1493
1525
|
this._prefixes._ = this._blankNodePrefix ? this._blankNodePrefix.substr(2)
|
|
1494
1526
|
: `b${blankNodePrefix++}_`;
|
|
1527
|
+
// Optionally bind the N3 empty prefix to the document's local namespace
|
|
1528
|
+
if (this._n3Mode && this._implicitEmptyPrefix && this._base)
|
|
1529
|
+
this._prefixes[''] = this._resolveIRI('#');
|
|
1495
1530
|
this._prefixCallback = onPrefix || noop;
|
|
1496
1531
|
this._versionCallback = onVersion || noop;
|
|
1497
1532
|
this._inversePredicate = false;
|