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/browser/n3.esm.min.js +12 -12
- package/browser/n3.min.js +12 -12
- package/lib/BaseIRI.js +6 -3
- package/lib/N3DataFactory.js +4 -1
- package/lib/N3Lexer.js +152 -130
- package/lib/N3Parser.js +40 -15
- package/lib/N3Store.js +10 -3
- package/package.json +24 -19
- package/src/BaseIRI.js +7 -3
- package/src/N3DataFactory.js +2 -1
- package/src/N3Lexer.js +168 -139
- package/src/N3Parser.js +42 -14
- package/src/N3Store.js +10 -4
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(
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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 '?':
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
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
|
|