Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for empty graphs in the subject and object positions #374

Draft
wants to merge 2 commits into
base: versions/2.0.0
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 17 additions & 2 deletions src/N3Parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it sufficient to check that there is no predicate?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The predicate check should be sufficient, as the flow goes as follows:
at the start of the formula the this._readSubject function is called. This one sets the this._predicate value to null.
As the token here is }, the this._readPunctuation function is called, that then calls the this._readFormulaTail function.
In here, we find this code. So I concluded that we should only check on the this._predicate value being null, and not the this._object, as the predicate value alone should be enough of an indicator and I am unsure how the object gets there in all flows.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay. so let's do if (this._predicate === null) indeed.

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'),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably want to use a constant for this.

this._literal('true', this._namedNode('http://www.w3.org/2001/XMLSchema#boolean')),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably want to use a constant for this.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was an error on my part.
I represented the empty graph as a blank node with an rdf:value of "true"^^xsd:boolean,
whereas I was corrected that it should be directly replaced with "true"^^xsd: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);
Expand Down
41 changes: 40 additions & 1 deletion test/N3Parser-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down Expand Up @@ -2337,6 +2337,45 @@ describe('Parser', () => {
it('should not parse RDF-star in the object position',
shouldNotParse(parser, '<a> <b> <<<a> <b> <c>>>.',
'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> {}.',
['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> {} <c>.',
// ['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, '{} <b> <c>.',
['_: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> { <x> <y> {} }.',
['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> { <x> {} <z> }.',
// ['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> { {} <y> <z> }.',
['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']
));
});
}

Expand Down
Loading