Skip to content

Annotation syntax: predicate-object list after {| |} is silently dropped #677

Description

@ericprud

A predicate-object list that continues after an annotation block loses everything following the block. No error is raised — the triples are silently absent from the output.

Verified against main @ 5875575.

Reproduction

new Parser({ format: 'text/turtle', baseIRI: 'http://ex/' })
  .parse('<a> <b> <c> {| <d> <e> |} ; <f> <g> .');

Actual — 3 quads:

_:b0 rdf:reifies <<( <a> <b> <c> )>>
<a>  <b> <c>
_:b0 <d> <e>

Expected — 4 quads, additionally:

<a>  <f> <g>

Same with ,:

<a> <b> <c> {| <d> <e> |} , <h> .     # <a> <b> <h> is missing

And everything after the block is lost, not just the first pair:

<a> <b> <c> {| <d> <e> |} ; <f> <g> ; <h> <i> .    # both pairs missing

Without the annotation block the same continuation is fine, so it is the block that breaks it:

<a> <b> <c> ; <f> <g> .    # => <a> <b> <c>, <a> <f> <g>

Per the RDF 1.2 Turtle grammar this is valid — objectList ::= object annotation? (',' object annotation?)*, and predicateObjectList continues with ; — so the annotation is a suffix of the object, not a terminator of the list.

Cause

Reading {| replaces the subject with the reifier so the block's predicate-object pairs attach to it, and |} clears the subject rather than putting back the triple that was annotated:

https://github.com/rdfjs/N3.js/blob/5875575/src/N3Parser.js#L755-L763

case '|}':
  ...
  this._subject = null;
  this._annotation = false;
  next = this._readPunctuation;
  break;

The this._subject = null is what suppresses a second emission of the annotated triple when the statement ends at .. But it also discards <a>, so the ; that follows has no subject to share, and the guard at the end of _readPunctuation (if (subject !== null && ...)) silently skips every subsequent quad.

Note on a fix

Restoring the annotated triple's subject/predicate/object at |} is not sufficient on its own: _readPunctuation would then emit <a> <b> <c> a second time when the statement ends. A fix needs to both restore that triple and record that it has already been asserted — for example by saving it on _contextStack with an "already emitted" flag and consulting that flag in the emit guard, which would let the existing _annotation / _validAnnotation booleans go away.

I have not sent a patch for this because the change is larger than the surrounding bugs I did send PRs for, and I would rather not guess at the design you want. Happy to implement it if you tell me which direction you prefer.

Related

The same root cause shows up inside a blank node property list, where it currently dereferences the null subject instead of dropping quads. #681 adds a syntax error there so it fails loudly rather than throwing a TypeError, but the construct stays unsupported until this is fixed.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions