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:
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.
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
Actual — 3 quads:
Expected — 4 quads, additionally:
Same with
,:And everything after the block is lost, not just the first pair:
Without the annotation block the same continuation is fine, so it is the block that breaks it:
Per the RDF 1.2 Turtle grammar this is valid —
objectList ::= object annotation? (',' object annotation?)*, andpredicateObjectListcontinues 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
The
this._subject = nullis 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:_readPunctuationwould 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_contextStackwith an "already emitted" flag and consulting that flag in the emit guard, which would let the existing_annotation/_validAnnotationbooleans 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.