linkeddata / rdflib.js

Linked Data API for JavaScript
http://linkeddata.github.io/rdflib.js/doc/
Other
566 stars 143 forks source link

Use SPARQL Query prefix declaration instead of relying on an N3 parser without sparqlPrefix implementation #651

Open csarven opened 3 months ago

csarven commented 3 months ago

It seems that sparqlUpdateParser in src/patch-parser.js is partly relying on src/n3parser.js instead of conforming to SPARQL Query, in particular the prefix declaration. Also, PREFIX line ending with a dot (.) is not valid syntax in SPARQL Query AFAICT:

The syntax of the prefix declaration in SPARQL 1.1 Query Language is as follows ( https://www.w3.org/TR/sparql11-query/#rPrefixDecl ):

[6] PrefixDecl ::= 'PREFIX' PNAME_NS IRIREF

And SPARQL Update states ( https://www.w3.org/TR/sparql11-update/#languageForm ):

PREFIX definitions and the syntax for IRIs in update requests in general follow the same conventions as in the SPARQL1.1 Query Language.

SPARQL 1.2 Query language ( https://w3c.github.io/sparql-query/spec/#rPrefixDecl ) uses the same declaration as SPARQL 1.1 Query Language.


The following code causes two issues: 1) finds @prefix valid when it should be invalid, and 2) finds PREFIX invalid when it should be valid:

https://github.com/linkeddata/rdflib.js/blob/cfc0f8c437d7872d76dc384d686c28d5d6100e35/src/patch-parser.js#L76-L91

I think instead of @prefix, it should be PREFIX (and adjust the length):

if (!found && str.slice(j, j + 6) === 'PREFIX') {

and the prefix declaration line does not end with a dot (.) so perhaps the following is unnecessary:

i = p.checkDot(str, i);

That's close to getting it working but the following line:

i = p.directive(str, j);

depends on n3parser. See:

var _n3parser = _interopRequireDefault(require("./n3parser"));
var p = (0, _n3parser.default)(kb, kb, base, base, null, null, '', null);

And going further down the rabbit-hole we have this in token checker in n3parser:

https://github.com/linkeddata/rdflib.js/blob/cfc0f8c437d7872d76dc384d686c28d5d6100e35/src/n3parser.js#L450

which essentially checks to see if there is "@" before prefix. Since the valid syntax "PREFIX" does not, it all falls apart.


So I don't know if there is a quick fix here but as far as conformance goes PrefixDecl is defined in SPARQL Query. I do not know if rdflib.js has a SPARQL Query parser somewhere or can borrow from somewhere.

Perhaps src/sparql-to-query is of help? See https://github.com/linkeddata/rdflib.js/blob/main/src/sparql-to-query.js#L267-L285

I was going to PR something but think that what I wrote here should be reviewed. I don't have the bandwidth to dig deeper or find a clever solution because there is some legacy code and it can use more eyes.


sparqlPrefix (in the issue title) implementation is in reference to current work on Notation 3 Language where it defines https://w3c.github.io/N3/spec/#grammar-production-sparqlPrefix :

[1] n3Doc ::= ( ( n3Statement ".") | sparqlDirective) * [4] sparqlDirective ::= sparqlBase | sparqlPrefix [6] sparqlPrefix ::= PREFIX PNAME_NS IRIREF

So, an alterative way of fixing this issue is potentially updating or changing the N3 Parser which may or may not be supporting SPARQL directives, if all things generally remain the same, i.e., patch-parser could use an N3 parser's prefix declarations (for both @prefix and PREFIX).


This whole thing causes an issue in code depending on it like, e.g., NSS. So, AFAICT, NSS does not conform in that it rejects requests with valid payload containing PREFIX, and also accepts invalid syntax @prefix.