From 671ce00e99f7e833495fb62aae3d9189668ea7ba Mon Sep 17 00:00:00 2001 From: "Ruben D." Date: Wed, 6 Dec 2023 13:21:04 +0100 Subject: [PATCH 1/2] fix: support empty graphs in subject and object positions for parsing text/n3 --- src/N3Parser.js | 19 +++++++++++++++++-- test/N3Parser-test.js | 41 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 57 insertions(+), 3 deletions(-) diff --git a/src/N3Parser.js b/src/N3Parser.js index 7537661b..2bd6b4da 100644 --- a/src/N3Parser.js +++ b/src/N3Parser.js @@ -663,8 +663,23 @@ export default class N3Parser { const graph = this._graph; // Store the last quad of the formula - if (this._subject !== null) - this._emit(this._subject, this._predicate, this._object, graph); + + if (this._subject !== null) { + // Catch the empty graph being closed when parsing N3. + // In this case, we emit the empty graph as the value "true"^^xsd:boolean + if (!this._predicate && !this._object) { + const outerGraph = this._contextStack[this._contextStack.length - 1].graph; + this._emit( + graph, + this._namedNode('http://www.w3.org/1999/02/22-rdf-syntax-ns#value'), + this._literal('true', this._namedNode('http://www.w3.org/2001/XMLSchema#boolean')), + outerGraph + ); // Restore the parent context containing this formula + } + else { + this._emit(this._subject, this._predicate, this._object, graph); + } + } // Restore the parent context containing this formula this._restoreContext('formula', token); diff --git a/test/N3Parser-test.js b/test/N3Parser-test.js index 5a5eca47..659904af 100644 --- a/test/N3Parser-test.js +++ b/test/N3Parser-test.js @@ -1763,7 +1763,7 @@ describe('Parser', () => { return isImpliedBy ? [to, 'http://www.w3.org/2000/10/swap/log#isImpliedBy', from] : [from, 'http://www.w3.org/2000/10/swap/log#implies', to]; } - describe(`A Parser instance for the N3 format with rdfStar support disabled and with ${isImpliedBy ? 'enabled' : 'disabled'}`, () => { + describe(`A Parser instance for the N3 format with rdfStar support disabled and with isImpliedBy ${isImpliedBy ? 'enabled' : 'disabled'}`, () => { function parser() { return new Parser({ baseIRI: BASE_IRI, format: 'N3', rdfStar: false, isImpliedBy }); } describe('should parse a single triple', @@ -2337,6 +2337,45 @@ describe('Parser', () => { it('should not parse RDF-star in the object position', shouldNotParse(parser, ' << >>.', 'Unexpected RDF-star syntax on line 1.')); + + describe('should parse the empty graph as an rdf:value of "true"^^xsd:boolean in the object position', + shouldParse(parser, ' {}.', + ['a', 'b', '_:b0'], + ['_:b0', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#value', '"true"^^http://www.w3.org/2001/XMLSchema#boolean'] + )); + + // describe('should parse the empty graph as an rdf:value of "true"^^xsd:boolean in the predicate position', + // shouldParse(parser, ' {} .', + // ['a', '_:b0', 'c'], + // ['_:b0', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#value', '"true"^^http://www.w3.org/2001/XMLSchema#boolean'] + // )); + + describe('should parse the empty graph as an rdf:value of "true"^^xsd:boolean in the subject position', + shouldParse(parser, '{} .', + ['_:b0', 'b', 'c'], + ['_:b0', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#value', '"true"^^http://www.w3.org/2001/XMLSchema#boolean'] + )); + + describe('should parse the empty graph in the object position as an rdf:value of "true"^^xsd:boolean while retaining the encompassing graph', + shouldParse(parser, ' { {} }.', + ['a', 'b', '_:b0'], + ['x', 'y', '_:b1', '_:b0'], + ['_:b1', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#value', '"true"^^http://www.w3.org/2001/XMLSchema#boolean', '_:b0'] + )); + + // describe('should parse the empty graph in the predicate position as an rdf:value of "true"^^xsd:boolean while retaining the encompassing graph', + // shouldParse(parser, ' { {} }.', + // ['a', 'b', '_:b0'], + // ['x', '_:b1', 'z', '_:b0'], + // ['_:b1', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#value', '"true"^^http://www.w3.org/2001/XMLSchema#boolean', '_:b0'] + // )); + + describe('should parse the empty graph in the subject position as an rdf:value of "true"^^xsd:boolean while retaining the encompassing graph', + shouldParse(parser, ' { {} }.', + ['a', 'b', '_:b0'], + ['_:b1', 'y', 'z', '_:b0'], + ['_:b1', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#value', '"true"^^http://www.w3.org/2001/XMLSchema#boolean', '_:b0'] + )); }); } From fcd0d9b138b7636a1f4271f3d1a724b8a5b59b87 Mon Sep 17 00:00:00 2001 From: "Ruben D." Date: Wed, 6 Dec 2023 15:58:45 +0100 Subject: [PATCH 2/2] fix: empty graphs are now correctly represented as true^^xsd:boolean --- src/N3Parser.js | 23 +++++++++++++++-------- test/N3Parser-test.js | 25 ++++--------------------- 2 files changed, 19 insertions(+), 29 deletions(-) diff --git a/src/N3Parser.js b/src/N3Parser.js index 2bd6b4da..a2dd92c1 100644 --- a/src/N3Parser.js +++ b/src/N3Parser.js @@ -662,19 +662,17 @@ export default class N3Parser { const graph = this._graph; + let closingEmptyGraph = false; + // Store the last quad of the formula if (this._subject !== null) { // Catch the empty graph being closed when parsing N3. // In this case, we emit the empty graph as the value "true"^^xsd:boolean - if (!this._predicate && !this._object) { - const outerGraph = this._contextStack[this._contextStack.length - 1].graph; - this._emit( - graph, - this._namedNode('http://www.w3.org/1999/02/22-rdf-syntax-ns#value'), - this._literal('true', this._namedNode('http://www.w3.org/2001/XMLSchema#boolean')), - outerGraph - ); // Restore the parent context containing this formula + // The predicate value is set to 'null' in the _readSubject function, + // after which the graph is closed directly when processing an empty graph. + if (!this._predicate) { + closingEmptyGraph = true; } else { this._emit(this._subject, this._predicate, this._object, graph); @@ -684,6 +682,15 @@ export default class N3Parser { // Restore the parent context containing this formula this._restoreContext('formula', token); + if (closingEmptyGraph) { + const xsdBoolean = 'http://www.w3.org/2001/XMLSchema#boolean'; + if (this._subject && this._subject.equals(graph)) + this._subject = this._literal('true', this._namedNode(xsdBoolean)); + + if (this._object && this._object.equals(graph)) + this._object = this._literal('true', this._namedNode(xsdBoolean)); + } + // If the formula was in a list context, continue reading the list if (this._contextStack.length > 0 && this._contextStack[this._contextStack.length - 1].type === 'list') { return this._readListItem(token, graph); diff --git a/test/N3Parser-test.js b/test/N3Parser-test.js index 659904af..dbfbbcb2 100644 --- a/test/N3Parser-test.js +++ b/test/N3Parser-test.js @@ -2340,41 +2340,24 @@ describe('Parser', () => { describe('should parse the empty graph as an rdf:value of "true"^^xsd:boolean in the object position', shouldParse(parser, ' {}.', - ['a', 'b', '_:b0'], - ['_:b0', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#value', '"true"^^http://www.w3.org/2001/XMLSchema#boolean'] + ['a', 'b', '"true"^^http://www.w3.org/2001/XMLSchema#boolean'] )); - // describe('should parse the empty graph as an rdf:value of "true"^^xsd:boolean in the predicate position', - // shouldParse(parser, ' {} .', - // ['a', '_:b0', 'c'], - // ['_:b0', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#value', '"true"^^http://www.w3.org/2001/XMLSchema#boolean'] - // )); - describe('should parse the empty graph as an rdf:value of "true"^^xsd:boolean in the subject position', shouldParse(parser, '{} .', - ['_:b0', 'b', 'c'], - ['_:b0', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#value', '"true"^^http://www.w3.org/2001/XMLSchema#boolean'] + ['"true"^^http://www.w3.org/2001/XMLSchema#boolean', 'b', 'c'] )); describe('should parse the empty graph in the object position as an rdf:value of "true"^^xsd:boolean while retaining the encompassing graph', shouldParse(parser, ' { {} }.', ['a', 'b', '_:b0'], - ['x', 'y', '_:b1', '_:b0'], - ['_:b1', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#value', '"true"^^http://www.w3.org/2001/XMLSchema#boolean', '_:b0'] + ['x', 'y', '"true"^^http://www.w3.org/2001/XMLSchema#boolean', '_:b0'] )); - // describe('should parse the empty graph in the predicate position as an rdf:value of "true"^^xsd:boolean while retaining the encompassing graph', - // shouldParse(parser, ' { {} }.', - // ['a', 'b', '_:b0'], - // ['x', '_:b1', 'z', '_:b0'], - // ['_:b1', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#value', '"true"^^http://www.w3.org/2001/XMLSchema#boolean', '_:b0'] - // )); - describe('should parse the empty graph in the subject position as an rdf:value of "true"^^xsd:boolean while retaining the encompassing graph', shouldParse(parser, ' { {} }.', ['a', 'b', '_:b0'], - ['_:b1', 'y', 'z', '_:b0'], - ['_:b1', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#value', '"true"^^http://www.w3.org/2001/XMLSchema#boolean', '_:b0'] + ['"true"^^http://www.w3.org/2001/XMLSchema#boolean', 'y', 'z', '_:b0'] )); }); }