Content after a '...' document-end marker begins a new bare document, but
the scanner rejected it as an unsupported multi-document stream and the
parser expected the document to end at the marker. A stream like
'--- scalar / ... / key: value' or 'a / ... / b' is two documents.
The scanner now reopens the stream when content follows '...', and
parseDocument returns at a '...' so the outer stream loop parses the next
document, bare or marked. A trailing '...' with nothing after it still
leaves a single document. The single-document composer still rejects a
multi-document stream, so 'parse' is unchanged. Two tests that asserted
content after '...' is an error are corrected, since the construct is valid
per the grammar and the official test-suite.
Measured against the official YAML test-suite, parse-level conformance
rises from 288/333 (86.5%) to 289/333 (86.8%) with no regression.
A node property always attaches to a node, and an empty node is allowed, so
an anchor or tag with nothing after it (a bare '&anchor', a 'key: &a', or a
'!!str'/'!!null' with no value) denotes that property applied to a null
node. parseNode rejected it as a missing node.
parseNode now emits a null scalar carrying the properties when a node
position holds only an anchor or tag, via a small helper to stay within the
complexity limit; with no properties, a missing node is still an error. A
'!!str' empty node resolves to the empty string and '!!null' to null. The
error-path test that asserted a dangling property throws is corrected, as
the construct is valid per the grammar and the official test-suite.
Measured against the official YAML test-suite, parse-level conformance
rises from 287/333 (86.2%) to 288/333 (86.5%), with value-level up one and
no regression.
An alias is a bare reference and cannot carry node properties, so '&b *a'
(an anchor on an alias) and a tag on an alias are malformed. parseNode
ignored any pending anchor or tag when it reached an alias token, dropping
the property and accepting the document.
The alias case now rejects a pending anchor or tag, and moves to its own
parseAlias helper so parseNode stays within the complexity limit. A bare
alias and an anchor or tag on a real node are unaffected.
Measured against the official YAML test-suite, parse-level conformance
rises from 266/333 (79.9%) to 267/333 (80.2%) with no regression.
A comment terminates a plain scalar, so a multi-line plain scalar cannot
resume after one. The parser accepted 'key: word1' then a '#' line then
' word2', and 'a' then 'b # ...' then 'c', merging the trailing content
back into the value ('word1 word2', 'a b c').
The scanner folds a genuine multi-line plain scalar into a single token
and splits it into a value-line scalar, an indent, and a further scalar
only when a comment broke its continuation folding. That token shape
therefore always denotes a comment-interrupted scalar, so the parser now
rejects it rather than re-merging. The re-merge path and its helper are
removed as they only ever served this malformed shape. A real multi-line
plain scalar and a trailing comment after a value stay valid.
Measured against the official YAML test-suite, parse-level conformance
rises from 264/333 (79.3%) to 266/333 (79.9%) with no regression.
Add structured validation diagnostics, JSON and Yams comparison gates, and lazy token/event parsing so production behavior is measured without retaining full intermediate parser arrays.