rdfjs / N3.js

Lightning fast, spec-compatible, streaming RDF for JavaScript
http://rdf.js.org/N3.js/
Other
714 stars 130 forks source link

Literals should be valid subjects in text/n3 #328

Open jeswr opened 1 year ago

jeswr commented 1 year ago

See https://github.com/eyereasoner/eye/issues/76#issuecomment-1450996748. Currently an error is thrown when they are encountered.

joachimvh commented 1 year ago

Are you sure this is an issue? I happen to be looking into something related and can confirm that the following code does not throw an error:

  const n3 = `"1"^^<http://www.w3.org/2001/XMLSchema#boolean> <http://example.com/p> <https://example.com/s> .`;
  const parser = new Parser({ format: 'text/n3' });
  const store = new Store(parser.parse(n3));

It does throw an error if you use text/turtle as format.

jeswr commented 1 year ago

The example complains if we just have a plain string

const n3 = `"1" <http://example.com/p> <https://example.com/s> .`;
const parser = new Parser({ format: 'text/n3' });
const store = new Store(parser.parse(n3));

with the following log

/home/jesse/Documents/github/eyer-js/experiment-shacl-alignment/clean-demo/node_modules/n3/lib/N3Parser.js:936
    const err = new Error(`${message} on line ${token.line}.`);
                ^
Error: Expected entity but got . on line 1.
    at N3Parser._error (/home/jesse/Documents/github/eyer-js/experiment-shacl-alignment/clean-demo/node_modules/n3/lib/N3Parser.js:936:17)
    at N3Parser._readEntity (/home/jesse/Documents/github/eyer-js/experiment-shacl-alignment/clean-demo/node_modules/n3/lib/N3Parser.js:203:21)
    at N3Parser._readObject (/home/jesse/Documents/github/eyer-js/experiment-shacl-alignment/clean-demo/node_modules/n3/lib/N3Parser.js:372:34)
    at /home/jesse/Documents/github/eyer-js/experiment-shacl-alignment/clean-demo/node_modules/n3/lib/N3Parser.js:1074:42
    at Array.every (<anonymous>)
    at N3Parser.parse (/home/jesse/Documents/github/eyer-js/experiment-shacl-alignment/clean-demo/node_modules/n3/lib/N3Parser.js:1073:35)
    at Object.<anonymous> (/home/jesse/Documents/github/eyer-js/experiment-shacl-alignment/clean-demo/badEye.ts:15:32)
    at Module._compile (node:internal/modules/cjs/loader:1218:14)
    at Module.m._compile (/home/jesse/.nvm/versions/node/v19.3.0/lib/node_modules/ts-node/src/index.ts:1618:23)
    at Module._extensions..js (node:internal/modules/cjs/loader:1272:10) {
  context: {
    token: { type: '.', value: '', prefix: '', line: 1, start: 51, end: 52 },
    line: 1,
    previousToken: { type: '.', value: '', prefix: '', line: 1, start: 51, end: 52 }
  }
}
jeswr commented 1 year ago

@joachimvh I've been having some more fun with this ...


I think the following dupes #329 - but for completeness

import { Parser, Writer } from 'n3';

const parser = new Parser({ format: 'text/n3' });
const writer = new Writer({ format: 'text/n3' });
console.log(writer.quadsToString(parser.parse('true => true .')))

writes (note the lack of braces on the datatype)

"true"^^http://www.w3.org/2001/XMLSchema#boolean <http://www.w3.org/2000/10/swap/log#implies> true .

import { Parser, Writer } from 'n3';

const parser = new Parser({ format: 'text/n3' });
console.log(parser.parse('{} => true .'))

outputs a quad with undefined subject predicate and object

[
  Quad {
    id: '',
    _subject: undefined,
    _predicate: null,
    _object: undefined,
    _graph: BlankNode { id: '_:n3-0' }
  },
  Quad {
    id: '',
    _subject: BlankNode { id: '_:n3-0' },
    _predicate: NamedNode { id: 'http://www.w3.org/2000/10/swap/log#implies' },
    _object: Literal { id: '"true"^^http://www.w3.org/2001/XMLSchema#boolean' },
    _graph: DefaultGraph { id: '' }
  }
]

and consequently crashes if you try to re-serialize it.

jeswr commented 1 year ago

As an actionable item could we please get the following tests passing in N3Parser-test.js

  describe('A Parser instance for the N3 format', () => {
    function parser() { return new Parser({ baseIRI: BASE_IRI, format: 'text/n3' }); }

    it('should parse an integer literal as subject',
      shouldParse(parser, '1 <a> <b>.', ['"1"^^http://www.w3.org/2001/XMLSchema#integer', 'a', 'b']));

    it('should parse a string literal as subject',
      shouldParse(parser, '"1" <a> <b>.', ['"1"', 'a', 'b']));

    it('should parse a string literal as subject list element',
      shouldParse(parser, '("1") <a> <b>.', 
      ['_:b0', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#first', '"1"'],
      ['_:b0', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#rest', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#nil'],
      ['_:b0', 'a', 'b']));

    it('should parse a string literal as object list element',
      shouldParse(parser, '<a> <b> ("1") .', ['_:b0', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#first', '"1"'],
      ['_:b0', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#rest', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#nil'],
      ['a', 'b', '_:b0']));

    it('should parse a string literal as predicate',
      shouldParse(parser, '<a> "1" <b>.', ['a', '"1"', 'b']));

    it('should parse a string literal as object',
      shouldParse(parser, '<a> <b> "1".', ['a', 'b', '"1"']));
  });
jeswr commented 1 year ago

And a test case for :s :p [ :p1 {"a" :p2 "b"} ]. and :s :p {"a" :p2 "b"}.