Skip to content

Commit 47e41f0

Browse files
authored
fix: support predicates in the list position in Notation3 (#345)
* fix: support predicates in the list position in Notation3 * chore: remove TODOs
1 parent 5d49813 commit 47e41f0

File tree

2 files changed

+71
-18
lines changed

2 files changed

+71
-18
lines changed

src/N3Parser.js

Lines changed: 30 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,17 @@ export default class N3Parser {
187187
return value;
188188
}
189189

190+
_readList(token, subject, predicate, object) {
191+
// Lists are not allowed inside quoted triples
192+
if (this._contextStack.length > 0 && this._contextStack[this._contextStack.length - 1].type === '<<') {
193+
return this._error('Unexpected list inside quoted triple', token);
194+
}
195+
// Start a new list
196+
this._saveContext('list', this._graph, subject, predicate, object);
197+
this._subject = null;
198+
return this._readListItem;
199+
}
200+
190201
// ### `_readSubject` reads a quad's subject
191202
_readSubject(token) {
192203
this._predicate = null;
@@ -197,14 +208,7 @@ export default class N3Parser {
197208
this._subject = this._blankNode(), null, null);
198209
return this._readBlankNodeHead;
199210
case '(':
200-
// Lists are not allowed inside quoted triples
201-
if (this._contextStack.length > 0 && this._contextStack[this._contextStack.length - 1].type === '<<') {
202-
return this._error('Unexpected list inside quoted triple', token);
203-
}
204-
// Start a new list
205-
this._saveContext('list', this._graph, this.RDF_NIL, null, null);
206-
this._subject = null;
207-
return this._readListItem;
211+
return this._readList(token, this.RDF_NIL, null, null);
208212
case '{':
209213
// Start a new formula
210214
if (!this._n3Mode)
@@ -282,6 +286,10 @@ export default class N3Parser {
282286
// Additional semicolons can be safely ignored
283287
return this._predicate !== null ? this._readPredicate :
284288
this._error('Expected predicate but got ;', token);
289+
case '(':
290+
return this._n3Mode ?
291+
this._readList(token, this._subject, this.RDF_NIL, null) :
292+
this._error(`Expected entity but got ${type}`, token);
285293
case '[':
286294
if (this._n3Mode) {
287295
// Start a new quad with a new blank node as subject
@@ -319,14 +327,7 @@ export default class N3Parser {
319327
this._subject = this._blankNode());
320328
return this._readBlankNodeHead;
321329
case '(':
322-
// Lists are not allowed inside quoted triples
323-
if (this._contextStack.length > 0 && this._contextStack[this._contextStack.length - 1].type === '<<') {
324-
return this._error('Unexpected list inside quoted triple', token);
325-
}
326-
// Start a new list
327-
this._saveContext('list', this._graph, this._subject, this._predicate, this.RDF_NIL);
328-
this._subject = null;
329-
return this._readListItem;
330+
return this._readList(token, this._subject, this._predicate, this.RDF_NIL);
330331
case '{':
331332
// Start a new formula
332333
if (!this._n3Mode)
@@ -468,6 +469,14 @@ export default class N3Parser {
468469
// No list tail if this was an empty list
469470
if (this._subject === this.RDF_NIL)
470471
return next;
472+
// Was this list the parent's predicate?
473+
}
474+
else if (this._object === null) {
475+
next = this._readObject;
476+
477+
// No list tail if this was an empty list
478+
if (this._predicate === this.RDF_NIL)
479+
return next;
471480
}
472481
// The list was in the parent context's object
473482
else {
@@ -519,9 +528,13 @@ export default class N3Parser {
519528

520529
// Is this the first element of the list?
521530
if (previousList === null) {
522-
// This list is either the subject or the object of its parent
531+
// This list is the subject of the parent
523532
if (parent.predicate === null)
524533
parent.subject = list;
534+
// The list is the predicate of the parent
535+
else if (parent.object === null)
536+
parent.predicate = list;
537+
// The list is the object of the parent
525538
else
526539
parent.object = list;
527540
}

test/N3Parser-test.js

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2052,6 +2052,46 @@ describe('Parser', () => {
20522052
['_:b0', 'f:knows', '_:b1'],
20532053
['_:b1', 'f:son', 'ex:joe']));
20542054

2055+
describe('should parse an empty list in the subject position',
2056+
shouldParse(parser, '@prefix : <ex:>. @prefix fam: <f:>.' +
2057+
'() <p> <o> .',
2058+
['http://www.w3.org/1999/02/22-rdf-syntax-ns#nil', 'p', 'o']
2059+
));
2060+
2061+
describe('should parse an empty list in the predicate position',
2062+
shouldParse(parser, '@prefix : <ex:>. @prefix fam: <f:>.' +
2063+
'<s> () <o> .',
2064+
['s', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#nil', 'o']
2065+
));
2066+
2067+
describe('should parse an empty list in the object position',
2068+
shouldParse(parser, '@prefix : <ex:>. @prefix fam: <f:>.' +
2069+
'<s> <p> () .',
2070+
['s', 'p', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#nil']
2071+
));
2072+
2073+
describe('should parse a single element list in the subject position',
2074+
shouldParse(parser, '@prefix : <ex:>. @prefix fam: <f:>.' +
2075+
'( <s> ) <p> <o> .',
2076+
...list(['_:b0', 's']),
2077+
['_:b0', 'p', 'o']
2078+
));
2079+
2080+
2081+
describe('should parse a single element list in the predicate position',
2082+
shouldParse(parser, '@prefix : <ex:>. @prefix fam: <f:>.' +
2083+
'<s> ( <p> ) <o> .',
2084+
...list(['_:b0', 'p']),
2085+
['s', '_:b0', 'o']
2086+
));
2087+
2088+
describe('should parse a single element list in the object position',
2089+
shouldParse(parser, '@prefix : <ex:>. @prefix fam: <f:>.' +
2090+
'<s> <p> ( <o> ) .',
2091+
...list(['_:b0', 'o']),
2092+
['s', 'p', '_:b0']
2093+
));
2094+
20552095
describe('should parse a ! path in a list as subject',
20562096
shouldParse(parser, '@prefix : <ex:>. @prefix fam: <f:>.' +
20572097
'(<x> :joe!fam:mother <y>) a :List.',
@@ -2269,7 +2309,7 @@ describe('Parser', () => {
22692309

22702310
for (const [f, triple] of [
22712311
[x => `(${x}) a :List .`, ['_:b0', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type', 'ex:List']],
2272-
// [x => `<l> (${x}) <m> .`, ['l', '_:b0', 'm']],
2312+
[x => `<l> (${x}) <m> .`, ['l', '_:b0', 'm']],
22732313
[x => `<l> <is> (${x}) .`, ['l', 'is', '_:b0']],
22742314
]) {
22752315
// eslint-disable-next-line no-inner-declarations

0 commit comments

Comments
 (0)