n3 2.6.3 → 2.7.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/browser/n3.esm.min.js +7 -7
- package/browser/n3.min.js +4 -4
- package/lib/N3Lexer.js +10 -2
- package/lib/N3Parser.js +24 -0
- package/lib/N3Store.js +13 -16
- package/package.json +1 -1
- package/src/N3Lexer.js +16 -1
- package/src/N3Parser.js +27 -0
- package/src/N3Store.js +20 -16
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._n3Verb = /^(?:has|is|of)(?=[\s#()\[\]\{\}"'<>?_+\-0-9])/;
|
|
91
92
|
this._n3Id = /^id(?=[\s#<])/;
|
|
92
93
|
this._shortPredicates = /^a(?=[\s#()\[\]\{\}"'<>])/;
|
|
93
94
|
this._newline = /^[ \t]*(?:#[^\n\r]*)?(?:\r\n|\n|\r)[ \t]*/;
|
|
@@ -200,6 +201,8 @@ class N3Lexer {
|
|
|
200
201
|
matchLength = 2;
|
|
201
202
|
if (this._isImpliedBy) type = 'abbreviation', value = '<';else type = 'inverse', value = '>';
|
|
202
203
|
}
|
|
204
|
+
// Try to find an inverted predicate marker
|
|
205
|
+
else if (this._n3Mode && input.length > 1 && input[1] === '-') type = 'inversePredicate', matchLength = 2;
|
|
203
206
|
break;
|
|
204
207
|
case '>':
|
|
205
208
|
// Try to find a reified triple
|
|
@@ -316,9 +319,14 @@ class N3Lexer {
|
|
|
316
319
|
// Try to find an abbreviated predicate
|
|
317
320
|
if (match = this._shortPredicates.exec(input)) type = 'abbreviation', value = 'a';else inconclusive = true;
|
|
318
321
|
break;
|
|
322
|
+
case 'h':
|
|
323
|
+
case 'o':
|
|
324
|
+
// Try to find an N3 verb keyword
|
|
325
|
+
if (this._n3Mode && (match = this._n3Verb.exec(input))) type = match[0];else inconclusive = true;
|
|
326
|
+
break;
|
|
319
327
|
case 'i':
|
|
320
|
-
// Try to find
|
|
321
|
-
if (this._n3Mode && (match = this._n3Id.exec(input))) type = 'id';else inconclusive = true;
|
|
328
|
+
// Try to find an IRI property list identifier or N3 verb keyword
|
|
329
|
+
if (this._n3Mode && (match = this._n3Id.exec(input))) type = 'id';else if (this._n3Mode && (match = this._n3Verb.exec(input))) type = match[0];else inconclusive = true;
|
|
322
330
|
break;
|
|
323
331
|
case '=':
|
|
324
332
|
// Try to find an implication arrow or equals sign
|
package/lib/N3Parser.js
CHANGED
|
@@ -106,6 +106,7 @@ class N3Parser {
|
|
|
106
106
|
object,
|
|
107
107
|
graph,
|
|
108
108
|
inverse: this._inversePredicate,
|
|
109
|
+
expectOf: this._expectOf,
|
|
109
110
|
blankPrefix: this._prefixes._,
|
|
110
111
|
quantified: this._quantified,
|
|
111
112
|
emptyFormula: this._emptyFormula
|
|
@@ -119,6 +120,7 @@ class N3Parser {
|
|
|
119
120
|
this._contextStack.push(context);
|
|
120
121
|
// Every new scope resets the predicate direction
|
|
121
122
|
this._inversePredicate = false;
|
|
123
|
+
this._expectOf = false;
|
|
122
124
|
// In N3, blank nodes are scoped to a formula
|
|
123
125
|
// (using a dot as separator, as a blank node label cannot start with it)
|
|
124
126
|
this._prefixes._ = this._graph ? `${this._graph.value}.` : '.';
|
|
@@ -147,6 +149,7 @@ class N3Parser {
|
|
|
147
149
|
// Restore N3 context settings
|
|
148
150
|
if (this._n3Mode) {
|
|
149
151
|
this._inversePredicate = context.inverse;
|
|
152
|
+
this._expectOf = context.expectOf;
|
|
150
153
|
if (type === 'formula') {
|
|
151
154
|
this._prefixes = context.prefixes;
|
|
152
155
|
[this._base, this._basePath, this._baseRoot, this._baseScheme] = context.base;
|
|
@@ -343,6 +346,15 @@ class N3Parser {
|
|
|
343
346
|
case 'abbreviation':
|
|
344
347
|
this._predicate = this.ABBREVIATIONS[token.value];
|
|
345
348
|
break;
|
|
349
|
+
case 'has':
|
|
350
|
+
return this._readPredicateAfterVerb;
|
|
351
|
+
case 'is':
|
|
352
|
+
this._inversePredicate = true;
|
|
353
|
+
this._expectOf = true;
|
|
354
|
+
return this._readPredicateAfterVerb;
|
|
355
|
+
case 'inversePredicate':
|
|
356
|
+
this._inversePredicate = true;
|
|
357
|
+
return this._readPredicateAfterVerb;
|
|
346
358
|
case '.':
|
|
347
359
|
case ']':
|
|
348
360
|
case '}':
|
|
@@ -391,8 +403,19 @@ class N3Parser {
|
|
|
391
403
|
return pathable ? this._getPathReader(this._readObject, 'predicate') : this._readObject;
|
|
392
404
|
}
|
|
393
405
|
|
|
406
|
+
// ### `_readPredicateAfterVerb` reads the predicate following `has` or `is`
|
|
407
|
+
_readPredicateAfterVerb(token) {
|
|
408
|
+
if (token.type === 'has' || token.type === 'is' || token.type === 'of' || token.type === 'inversePredicate') return this._error(`Expected expression but got ${token.type}`, token);
|
|
409
|
+
return this._readPredicate(token);
|
|
410
|
+
}
|
|
411
|
+
|
|
394
412
|
// ### `_readObject` reads a quad's object
|
|
395
413
|
_readObject(token) {
|
|
414
|
+
if (this._expectOf) {
|
|
415
|
+
if (token.type !== 'of') return this._error(`Expected of but got ${token.type}`, token);
|
|
416
|
+
this._expectOf = false;
|
|
417
|
+
return this._readObject;
|
|
418
|
+
}
|
|
396
419
|
switch (token.type) {
|
|
397
420
|
case 'literal':
|
|
398
421
|
// Regular literal, can still get a datatype or language
|
|
@@ -1413,6 +1436,7 @@ class N3Parser {
|
|
|
1413
1436
|
this._prefixCallback = onPrefix || noop;
|
|
1414
1437
|
this._versionCallback = onVersion || noop;
|
|
1415
1438
|
this._inversePredicate = false;
|
|
1439
|
+
this._expectOf = false;
|
|
1416
1440
|
this._quantified = Object.create(null);
|
|
1417
1441
|
this._emptyFormula = false;
|
|
1418
1442
|
|
package/lib/N3Store.js
CHANGED
|
@@ -331,28 +331,25 @@ class N3Store {
|
|
|
331
331
|
|
|
332
332
|
// ### `_countInIndex` counts matching quads in a three-layered index.
|
|
333
333
|
// The index base is `index0` and the keys at each level are `key0`, `key1`, and `key2`.
|
|
334
|
-
//
|
|
334
|
+
// A key and any keys after it can be null or undefined, which is interpreted as a wildcard.
|
|
335
335
|
_countInIndex(index0, key0, key1, key2) {
|
|
336
336
|
let count = 0,
|
|
337
|
-
tmp,
|
|
338
337
|
index1,
|
|
339
338
|
index2;
|
|
340
339
|
|
|
341
|
-
//
|
|
342
|
-
if (key0)
|
|
343
|
-
|
|
344
|
-
if (
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
for (const value1 in index1) {
|
|
348
|
-
if (index2 = index1[value1]) {
|
|
349
|
-
// If a key is specified, count the quad if it exists
|
|
350
|
-
if (key2) key2 in index2 && count++;
|
|
351
|
-
// Otherwise, count all quads
|
|
352
|
-
else count += index2[SIZE];
|
|
353
|
-
}
|
|
354
|
-
}
|
|
340
|
+
// Bound outer keys can be looked up directly.
|
|
341
|
+
if (key0) {
|
|
342
|
+
if (!(index1 = index0[key0])) return 0;
|
|
343
|
+
if (key1) {
|
|
344
|
+
if (!(index2 = index1[key1])) return 0;
|
|
345
|
+
return key2 ? key2 in index2 ? 1 : 0 : index2[SIZE];
|
|
355
346
|
}
|
|
347
|
+
for (const value1 in index1) count += index1[value1][SIZE];
|
|
348
|
+
return count;
|
|
349
|
+
}
|
|
350
|
+
for (const value0 in index0) {
|
|
351
|
+
index1 = index0[value0];
|
|
352
|
+
for (const value1 in index1) count += index1[value1][SIZE];
|
|
356
353
|
}
|
|
357
354
|
return count;
|
|
358
355
|
}
|
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._n3Verb = /^(?:has|is|of)(?=[\s#()\[\]\{\}"'<>?_+\-0-9])/;
|
|
60
61
|
this._n3Id = /^id(?=[\s#<])/;
|
|
61
62
|
this._shortPredicates = /^a(?=[\s#()\[\]\{\}"'<>])/;
|
|
62
63
|
this._newline = /^[ \t]*(?:#[^\n\r]*)?(?:\r\n|\n|\r)[ \t]*/;
|
|
@@ -174,6 +175,9 @@ export default class N3Lexer {
|
|
|
174
175
|
if (this._isImpliedBy) type = 'abbreviation', value = '<';
|
|
175
176
|
else type = 'inverse', value = '>';
|
|
176
177
|
}
|
|
178
|
+
// Try to find an inverted predicate marker
|
|
179
|
+
else if (this._n3Mode && input.length > 1 && input[1] === '-')
|
|
180
|
+
type = 'inversePredicate', matchLength = 2;
|
|
177
181
|
break;
|
|
178
182
|
|
|
179
183
|
case '>':
|
|
@@ -319,10 +323,21 @@ export default class N3Lexer {
|
|
|
319
323
|
inconclusive = true;
|
|
320
324
|
break;
|
|
321
325
|
|
|
326
|
+
case 'h':
|
|
327
|
+
case 'o':
|
|
328
|
+
// Try to find an N3 verb keyword
|
|
329
|
+
if (this._n3Mode && (match = this._n3Verb.exec(input)))
|
|
330
|
+
type = match[0];
|
|
331
|
+
else
|
|
332
|
+
inconclusive = true;
|
|
333
|
+
break;
|
|
334
|
+
|
|
322
335
|
case 'i':
|
|
323
|
-
// Try to find
|
|
336
|
+
// Try to find an IRI property list identifier or N3 verb keyword
|
|
324
337
|
if (this._n3Mode && (match = this._n3Id.exec(input)))
|
|
325
338
|
type = 'id';
|
|
339
|
+
else if (this._n3Mode && (match = this._n3Verb.exec(input)))
|
|
340
|
+
type = match[0];
|
|
326
341
|
else
|
|
327
342
|
inconclusive = true;
|
|
328
343
|
break;
|
package/src/N3Parser.js
CHANGED
|
@@ -89,6 +89,7 @@ export default class N3Parser {
|
|
|
89
89
|
type,
|
|
90
90
|
subject, predicate, object, graph,
|
|
91
91
|
inverse: this._inversePredicate,
|
|
92
|
+
expectOf: this._expectOf,
|
|
92
93
|
blankPrefix: this._prefixes._,
|
|
93
94
|
quantified: this._quantified,
|
|
94
95
|
emptyFormula: this._emptyFormula,
|
|
@@ -102,6 +103,7 @@ export default class N3Parser {
|
|
|
102
103
|
this._contextStack.push(context);
|
|
103
104
|
// Every new scope resets the predicate direction
|
|
104
105
|
this._inversePredicate = false;
|
|
106
|
+
this._expectOf = false;
|
|
105
107
|
// In N3, blank nodes are scoped to a formula
|
|
106
108
|
// (using a dot as separator, as a blank node label cannot start with it)
|
|
107
109
|
this._prefixes._ = (this._graph ? `${this._graph.value}.` : '.');
|
|
@@ -131,6 +133,7 @@ export default class N3Parser {
|
|
|
131
133
|
// Restore N3 context settings
|
|
132
134
|
if (this._n3Mode) {
|
|
133
135
|
this._inversePredicate = context.inverse;
|
|
136
|
+
this._expectOf = context.expectOf;
|
|
134
137
|
if (type === 'formula') {
|
|
135
138
|
this._prefixes = context.prefixes;
|
|
136
139
|
[this._base, this._basePath, this._baseRoot, this._baseScheme] = context.base;
|
|
@@ -346,6 +349,15 @@ export default class N3Parser {
|
|
|
346
349
|
case 'abbreviation':
|
|
347
350
|
this._predicate = this.ABBREVIATIONS[token.value];
|
|
348
351
|
break;
|
|
352
|
+
case 'has':
|
|
353
|
+
return this._readPredicateAfterVerb;
|
|
354
|
+
case 'is':
|
|
355
|
+
this._inversePredicate = true;
|
|
356
|
+
this._expectOf = true;
|
|
357
|
+
return this._readPredicateAfterVerb;
|
|
358
|
+
case 'inversePredicate':
|
|
359
|
+
this._inversePredicate = true;
|
|
360
|
+
return this._readPredicateAfterVerb;
|
|
349
361
|
case '.':
|
|
350
362
|
case ']':
|
|
351
363
|
case '}':
|
|
@@ -407,8 +419,22 @@ export default class N3Parser {
|
|
|
407
419
|
return pathable ? this._getPathReader(this._readObject, 'predicate') : this._readObject;
|
|
408
420
|
}
|
|
409
421
|
|
|
422
|
+
// ### `_readPredicateAfterVerb` reads the predicate following `has` or `is`
|
|
423
|
+
_readPredicateAfterVerb(token) {
|
|
424
|
+
if (token.type === 'has' || token.type === 'is' || token.type === 'of' ||
|
|
425
|
+
token.type === 'inversePredicate')
|
|
426
|
+
return this._error(`Expected expression but got ${token.type}`, token);
|
|
427
|
+
return this._readPredicate(token);
|
|
428
|
+
}
|
|
429
|
+
|
|
410
430
|
// ### `_readObject` reads a quad's object
|
|
411
431
|
_readObject(token) {
|
|
432
|
+
if (this._expectOf) {
|
|
433
|
+
if (token.type !== 'of')
|
|
434
|
+
return this._error(`Expected of but got ${token.type}`, token);
|
|
435
|
+
this._expectOf = false;
|
|
436
|
+
return this._readObject;
|
|
437
|
+
}
|
|
412
438
|
switch (token.type) {
|
|
413
439
|
case 'literal':
|
|
414
440
|
// Regular literal, can still get a datatype or language
|
|
@@ -1530,6 +1556,7 @@ export default class N3Parser {
|
|
|
1530
1556
|
this._prefixCallback = onPrefix || noop;
|
|
1531
1557
|
this._versionCallback = onVersion || noop;
|
|
1532
1558
|
this._inversePredicate = false;
|
|
1559
|
+
this._expectOf = false;
|
|
1533
1560
|
this._quantified = Object.create(null);
|
|
1534
1561
|
this._emptyFormula = false;
|
|
1535
1562
|
|
package/src/N3Store.js
CHANGED
|
@@ -351,25 +351,29 @@ export default class N3Store {
|
|
|
351
351
|
|
|
352
352
|
// ### `_countInIndex` counts matching quads in a three-layered index.
|
|
353
353
|
// The index base is `index0` and the keys at each level are `key0`, `key1`, and `key2`.
|
|
354
|
-
//
|
|
354
|
+
// A key and any keys after it can be null or undefined, which is interpreted as a wildcard.
|
|
355
355
|
_countInIndex(index0, key0, key1, key2) {
|
|
356
|
-
let count = 0,
|
|
356
|
+
let count = 0, index1, index2;
|
|
357
|
+
|
|
358
|
+
// Bound outer keys can be looked up directly.
|
|
359
|
+
if (key0) {
|
|
360
|
+
if (!(index1 = index0[key0]))
|
|
361
|
+
return 0;
|
|
362
|
+
if (key1) {
|
|
363
|
+
if (!(index2 = index1[key1]))
|
|
364
|
+
return 0;
|
|
365
|
+
return key2 ? (key2 in index2 ? 1 : 0) : index2[SIZE];
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
for (const value1 in index1)
|
|
369
|
+
count += index1[value1][SIZE];
|
|
370
|
+
return count;
|
|
371
|
+
}
|
|
357
372
|
|
|
358
|
-
// If a key is specified, count only that part of index 0
|
|
359
|
-
if (key0) (tmp = index0, index0 = {})[key0] = tmp[key0];
|
|
360
373
|
for (const value0 in index0) {
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
for (const value1 in index1) {
|
|
365
|
-
if (index2 = index1[value1]) {
|
|
366
|
-
// If a key is specified, count the quad if it exists
|
|
367
|
-
if (key2) (key2 in index2) && count++;
|
|
368
|
-
// Otherwise, count all quads
|
|
369
|
-
else count += index2[SIZE];
|
|
370
|
-
}
|
|
371
|
-
}
|
|
372
|
-
}
|
|
374
|
+
index1 = index0[value0];
|
|
375
|
+
for (const value1 in index1)
|
|
376
|
+
count += index1[value1][SIZE];
|
|
373
377
|
}
|
|
374
378
|
return count;
|
|
375
379
|
}
|