n3 2.11.0 → 2.11.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/src/N3Parser.js CHANGED
@@ -18,7 +18,7 @@ export default class N3Parser {
18
18
 
19
19
  // Set supported features depending on the format
20
20
  const format = (typeof options.format === 'string') ?
21
- options.format.match(/\w*$/)[0].toLowerCase() : '',
21
+ options.format.match(/(?:^|\W)(\w*)$/)[1].toLowerCase() : '',
22
22
  isTurtle = /turtle/.test(format), isTriG = /trig/.test(format),
23
23
  isNTriples = /triple/.test(format), isNQuads = /quad/.test(format),
24
24
  isN3 = this._n3Mode = /n3/.test(format),
@@ -78,8 +78,10 @@ export default class N3Parser {
78
78
  baseIRI = baseIRI.substr(0, fragmentPos);
79
79
  // Set base IRI and its components
80
80
  this._base = baseIRI;
81
+ const queryPos = baseIRI.indexOf('?');
82
+ const path = queryPos < 0 ? baseIRI : baseIRI.substr(0, queryPos);
81
83
  this._basePath = baseIRI.indexOf('/') < 0 ? baseIRI :
82
- baseIRI.replace(/[^\/?]*(?:\?.*)?$/, '');
84
+ path.substr(0, path.lastIndexOf('/') + 1);
83
85
  baseIRI = baseIRI.match(/^(?:([a-z][a-z0-9+.-]*:))?(?:\/\/[^\/]*)?/i);
84
86
  this._baseRoot = baseIRI[0];
85
87
  this._baseScheme = baseIRI[1];
@@ -100,14 +102,15 @@ export default class N3Parser {
100
102
  inverse: this._inversePredicate,
101
103
  expectOf: this._expectOf,
102
104
  blankPrefix: this._prefixes._,
103
- quantified: this._quantified,
105
+ prefixChanges: this._prefixChanges,
106
+ quantifiedChanges: this._quantifiedChanges,
104
107
  emptyFormula: this._emptyFormula,
105
108
  };
106
- // Prefix and base declarations are scoped to their formula
109
+ // Prefix and base declarations are scoped to their formula,
110
+ // so record prefix changes to undo them when the formula ends
107
111
  if (type === 'formula') {
108
- context.prefixes = this._prefixes;
109
112
  context.base = [this._base, this._basePath, this._baseRoot, this._baseScheme];
110
- this._prefixes = Object.create(this._prefixes);
113
+ this._prefixChanges = [];
111
114
  }
112
115
  this._contextStack.push(context);
113
116
  // Every new scope resets the predicate direction
@@ -120,7 +123,7 @@ export default class N3Parser {
120
123
  // Label the scope with the enclosing formula's blank node
121
124
  // (using a dot as separator, as a blank node label cannot start with it)
122
125
  this._prefixes._ = (this._graph ? `${this._graph.value}.` : '.');
123
- this._quantified = Object.create(this._quantified);
126
+ this._quantifiedChanges = [];
124
127
  }
125
128
  // A formula starts empty and must not inherit its parent's subject
126
129
  if (type === 'formula') {
@@ -147,13 +150,17 @@ export default class N3Parser {
147
150
  if (this._n3Mode) {
148
151
  this._inversePredicate = context.inverse;
149
152
  this._expectOf = context.expectOf;
150
- if (type === 'formula') {
151
- this._prefixes = context.prefixes;
153
+ if (type === 'formula')
152
154
  [this._base, this._basePath, this._baseRoot, this._baseScheme] = context.base;
155
+ if (this._prefixChanges !== context.prefixChanges) {
156
+ undoChanges(this._prefixes, this._prefixChanges);
157
+ this._prefixChanges = context.prefixChanges;
158
+ }
159
+ this._prefixes._ = context.blankPrefix;
160
+ if (this._quantifiedChanges !== context.quantifiedChanges) {
161
+ undoChanges(this._quantified, this._quantifiedChanges);
162
+ this._quantifiedChanges = context.quantifiedChanges;
153
163
  }
154
- else
155
- this._prefixes._ = context.blankPrefix;
156
- this._quantified = context.quantified;
157
164
  this._emptyFormula = context.emptyFormula;
158
165
  }
159
166
  }
@@ -1055,6 +1062,8 @@ export default class N3Parser {
1055
1062
  if (token.type !== 'IRI')
1056
1063
  return this._error(`Expected IRI to follow prefix "${this._prefix}:"`, token);
1057
1064
  const prefixNode = this._readEntity(token);
1065
+ if (this._prefixChanges !== null)
1066
+ this._prefixChanges.push(this._prefix, this._prefixes[this._prefix]);
1058
1067
  this._prefixes[this._prefix] = prefixNode.value;
1059
1068
  this._prefixCallback(this._prefix, prefixNode);
1060
1069
  return this._readDeclarationPunctuation;
@@ -1133,8 +1142,11 @@ export default class N3Parser {
1133
1142
  return this._error(`Unexpected ${token.type}`, token);
1134
1143
  }
1135
1144
  // Without explicit quantifiers, map entities to a quantified entity
1136
- if (!this._explicitQuantifiers)
1145
+ if (!this._explicitQuantifiers) {
1146
+ if (this._quantifiedChanges !== null)
1147
+ this._quantifiedChanges.push(entity.id, this._quantified[entity.id]);
1137
1148
  this._quantified[entity.id] = this._factory[this._quantifier](this._factory.blankNode().value);
1149
+ }
1138
1150
  // With explicit quantifiers, output the reified quantifier
1139
1151
  else {
1140
1152
  // If this is the first item, start a new quantifier list
@@ -1521,7 +1533,10 @@ export default class N3Parser {
1521
1533
  // Resolve relative fragment IRIs against the base IRI
1522
1534
  case '#': return this._base + iri;
1523
1535
  // Resolve relative query string IRIs by replacing the query string
1524
- case '?': return this._base.replace(/(?:\?.*)?$/, iri);
1536
+ case '?': {
1537
+ const queryPos = this._base.indexOf('?');
1538
+ return (queryPos < 0 ? this._base : this._base.substr(0, queryPos)) + iri;
1539
+ }
1525
1540
  // Resolve root-relative IRIs at the root of the base IRI
1526
1541
  case '/':
1527
1542
  // Resolve scheme-relative IRIs to the scheme
@@ -1632,6 +1647,9 @@ export default class N3Parser {
1632
1647
  this._inversePredicate = false;
1633
1648
  this._expectOf = false;
1634
1649
  this._quantified = Object.create(null);
1650
+ // Changes to prefixes and quantifiers in nested scopes, to undo when leaving them
1651
+ this._prefixChanges = null;
1652
+ this._quantifiedChanges = null;
1635
1653
  this._emptyFormula = false;
1636
1654
 
1637
1655
  let readToken = token => {
@@ -1694,6 +1712,16 @@ export default class N3Parser {
1694
1712
  }
1695
1713
  }
1696
1714
 
1715
+ // ### `undoChanges` restores the entries of a map from a list of key and previous value pairs
1716
+ function undoChanges(map, changes) {
1717
+ for (let i = changes.length - 2; i >= 0; i -= 2) {
1718
+ if (changes[i + 1] === undefined)
1719
+ delete map[changes[i]];
1720
+ else
1721
+ map[changes[i]] = changes[i + 1];
1722
+ }
1723
+ }
1724
+
1697
1725
  // The empty function
1698
1726
  function noop() {}
1699
1727
 
package/src/N3Store.js CHANGED
@@ -30,8 +30,10 @@ function merge(target, source, depth = 4) {
30
30
  size++;
31
31
  target[key] = depth === 0 ? null : merge(Object.create(null), source[key], depth - 1);
32
32
  }
33
+ // Merge into the existing object in place,
34
+ // as graph objects are frozen and cannot be reassigned
33
35
  else if (depth !== 0)
34
- target[key] = merge(target[key], source[key], depth - 1);
36
+ merge(target[key], source[key], depth - 1);
35
37
  }
36
38
  // Depth 2 is the level of the `subjects`, `predicates`, and `objects` indexes.
37
39
  if (depth <= 2)
@@ -1010,7 +1012,7 @@ export default class N3Store {
1010
1012
  if (!first)
1011
1013
  malformed = onError(current, 'has no list head');
1012
1014
  else
1013
- items.unshift(first.object);
1015
+ items.push(first.object);
1014
1016
  current = parent && parent.subject;
1015
1017
  }
1016
1018
 
@@ -1018,12 +1020,16 @@ export default class N3Store {
1018
1020
  if (malformed)
1019
1021
  remove = false;
1020
1022
  else {
1023
+ // Items were collected from the tail to the head
1024
+ items.reverse();
1021
1025
  // Store the list under the value of its head
1022
1026
  if (head)
1023
1027
  lists[head[headPos].value] = items;
1024
1028
  // Leave lists with extra arcs fully intact; otherwise queue this list once.
1025
- if (remove && !extraArcs)
1026
- toRemove.push(...listQuads);
1029
+ if (remove && !extraArcs) {
1030
+ for (let i = 0; i < listQuads.length; i++)
1031
+ toRemove.push(listQuads[i]);
1032
+ }
1027
1033
  }
1028
1034
  });
1029
1035