n3 2.6.4 → 2.7.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/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 the IRI property list identifier
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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "n3",
3
- "version": "2.6.4",
3
+ "version": "2.7.1",
4
4
  "description": "Lightning fast, asynchronous, streaming Turtle / N3 / RDF library.",
5
5
  "author": "Ruben Verborgh <ruben.verborgh@gmail.com>",
6
6
  "keywords": [
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 the IRI property list identifier
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