Commit Graph

46 Commits

Author SHA1 Message Date
27e8defac6 fix(parsing): fold line breaks in multi-line single-quoted scalars
Single-quoted scalars share the same flow line folding as double-quoted,
which the previous commit added: a single break folds to a space, a blank
line to one newline, whitespace adjacent to a break is stripped, and the
first-line leading and last-line trailing whitespace are kept. The
single-quoted decoder kept its raw breaks; it now reuses the shared
foldFlowScalarLineBreaks helper, while doubled quotes ('') still escape to
one quote.

Measured against the official YAML test-suite, value-level conformance
rises from 143/169 (84.6%) to 147/169 (87.0%) with no regression.
Parse-level is unchanged: these documents already parsed, just to the
wrong tree.
2026-06-26 21:18:55 +02:00
08e1979085 fix(parsing): fold line breaks in multi-line double-quoted scalars
The double-quoted decoder appended real line breaks and continuation-line
indentation verbatim, so a multi-line "..." scalar kept its raw newlines
and leading whitespace instead of folding. It now applies YAML flow
folding at each unescaped break: a single break folds to a space, a blank
line to one newline, and whitespace adjacent to a break (the line's
trailing, the next line's leading) is stripped. First-line leading and
last-line trailing whitespace stay (they sit next to a quote, not a
break), and \n escapes are still decoded to literal newlines.

Measured against the official YAML test-suite, value-level conformance
rises from 135/169 (79.9%) to 143/169 (84.6%) with no regression.
Parse-level is unchanged: these documents already parsed, just to the
wrong tree, which only the value-level metric exposes.
2026-06-26 21:13:13 +02:00
455cd07f4a fix(parsing): keep a root node that begins on the document-marker line
A document-start marker scan skipped the rest of the '---' line
unconditionally, so a root node written on that same line was discarded:
a block-scalar header ('--- >' / '--- |') was dropped and its body
mis-read as a plain scalar (folded to spaces, no trailing newline), and a
same-line plain or flow node was lost entirely. The document start now
skips only trailing spaces and leaves any real same-line content for the
parser; an empty rest-of-line or a comment is still consumed, and a node
on the line below the marker is unaffected. Document end ('...') still
takes no same-line node.

Measured against the official YAML test-suite, value-level conformance
rises from 130/170 (76.5%) to 135/169 (79.9%) with no regression.
Parse-level is unchanged: these documents already parsed, just to the
wrong tree, which only the value-level metric exposes.
2026-06-26 20:50:24 +02:00
d90a091ab0 fix(parsing): fold a plain scalar value that begins on its own line
A multi-line plain scalar whose value sits one line below its mapping key
stopped after the first line: the continuation check compared the next
line's indent against the value's own indent, which had been pushed onto
the indentation stack, so a continuation at the same indent failed the
strict '>'. It now compares against the parent block's indent (the level
below the value's, when the scalar begins exactly at the indentation top),
matching the spec: a continuation must exceed the mapping's indentation,
not the value's own. Inline values are unaffected, since their top-of-
stack already is the parent block's indent.

Measured against the official YAML test-suite, parse-level conformance
rises from 211/333 (63.4%) to 221/333 (66.4%) with no regression across
the existing 306 tests. The +10 covers the multi-line plain scalar family
the harness flagged, not just the case investigated.
2026-06-26 18:52:09 +02:00
ceb12295a4 fix(parsing): preserve leading blank lines in block scalars
Blank lines between a block scalar header and its first content line come
before the indent token, so the earlier blank-line capture skipped them.
Buffer leading blanks while the block indentation is still pending and
flush them as empty content once the indent is established, in the shared
indentation path used by both scan loops. Also fix folded bodies to emit
a break for a leading blank rather than folding it into a leading space.
This closes the last block-scalar blank-line edge from #57.
2026-06-26 08:42:16 +02:00
234e0382e6 refactor(parsing): remove three unreachable ParseError cases
emptyDocument, expectedMappingKey, and tabIndentation were never thrown
anywhere in the parser. Empty and comment-only documents parse to null,
the mapping-key path throws unexpectedToken with an "expected mapping
key" message, and tabs in indentation are reported by the validation
layer's PreflightScanner rather than the parser. Drop the dead cases and
their switch arms and description test assertions. No reachable behavior
changes; the PropertyMutation.tabIndentation test mutation is unrelated
and untouched.
2026-06-26 08:37:53 +02:00
4358cf02cc fix(parsing): keep more-indented folded lines literal
A folded block scalar folded every non-blank line into the surrounding
text, including more-indented lines, which YAML keeps literal with their
line breaks. Detect a more-indented line by its retained leading
whitespace and keep the breaks adjacent to it instead of folding them.
Plain and blank-line folding are unchanged.
2026-06-26 08:13:43 +02:00
d3ff3823a5 fix(parsing): preserve blank lines in block scalars
The scanner dropped every blank line within and after a block scalar, so
a literal block lost internal blank lines, a folded block turned a blank
line into a space rather than a newline, and the keep indicator could not
preserve trailing blank lines. Capture blank lines as empty content in
both the batch scan loop and the streaming TokenCursor loop, which had
drifted as duplicate copies. Rework blockScalarValue to apply literal
versus folded line semantics and clip/strip/keep chomping over the
captured lines; content without blank lines is unchanged. Re-pin the
multiline-scalar test whose expectation encoded the old dropped-blank
behavior, and add a chomping-and-folding test matrix.
2026-06-26 08:09:45 +02:00
fadde56a05 fix(parsing): classify the keep block-scalar chomping indicator
The scanner consumed the `+` indicator of a `|+` / `>+` block scalar but
mapped it to nothing, so keep was silently treated as clip, and a scanner
test baked that in. Add a `keep` case to BlockScalarChomping, recognize
`+` in the header scanner, and correct the test. Full keep value semantics
(preserving trailing blank lines) depend on scanner blank-line capture and
are tracked in #57; this commit fixes the token classification only.
2026-06-26 07:50:07 +02:00
c4f7f9dccc refactor(code-style): one top-level type per source file
Split the six files that declared multiple sibling types under one
namespace extension so each file declares exactly one top-level type:
the Tagged node component types (Node, NodeKind, Scalar, Sequence,
Mapping, Pair), the validation report types (Report, Source,
SourceReport, BatchReport), DiagnosticKind, TokenKind, ScannerFlowContext
kind, and the event-stream composer helpers. Public type names are
unchanged; the shared report-rendering helpers move from file-private to
internal so the split report types still reach them.

Make check-namespacing.sh namespace-aware: the previous column-anchored
scan was blind to types declared inside indented extension blocks, so it
passed while the rule was violated. It now counts direct members of a
PureYAML namespace extension and ignores nested types and private helpers.
2026-06-26 06:14:21 +02:00
9ae6c3baff refactor(parsing): share merge-key resolution between composers
The buffered and streaming event composers each carried an identical
copy of the merge-key (<<) override logic and its invalid-value error.
Extract both into one internal Parsing.MergeResolution helper so the
precedence rules (local keys win, earlier sources win, inherited then
local order) have a single source of truth. No behavior change; all
tests pass.
2026-06-26 05:50:28 +02:00
16a47df118 docs(parsing): document why the nesting bound is necessary and sufficient 2026-06-23 11:08:30 +02:00
64a171bff4 fix(parsing): bound nesting depth so pathological input errors instead of crashing 2026-06-23 09:29:45 +02:00
5d76d184cb fix(parsing): treat leading '#' in block scalars as literal content 2026-06-23 04:00:07 +02:00
208b892019 feat(parser): harden diagnostics and streaming
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.
2026-06-06 07:57:48 +02:00
37239fe613 fix(parser): match block continuation parsing 2026-06-05 22:12:12 +02:00
3a90df095d fix(ci): prepare 0.1.0 release 2026-06-05 21:20:20 +02:00
68883f2104 feat(validation): add diagnostic report errors 2026-06-05 21:06:42 +02:00
13183a4353 Add machine-readable validation reports 2026-06-05 20:39:32 +02:00
0e92e31d89 Add production validation reports 2026-06-05 20:23:20 +02:00
bc54528353 Harden parser against real YAML fixtures 2026-06-05 19:34:30 +02:00
906f0c454d feat(emitting): dump YAML streams 2026-06-05 17:14:41 +02:00
91a2c24901 feat(tagged): add typed constructor policy 2026-06-05 16:24:11 +02:00
697b9cc519 feat(model): support complex mapping keys 2026-06-05 16:08:45 +02:00
9c45419496 feat(tagged): add tag-preserving validation 2026-06-05 15:35:52 +02:00
e1f8acb3a0 feat(parser): expand YAML merge keys 2026-06-05 15:12:55 +02:00
8be6e68a23 feat(parser): add multi-document stream parsing 2026-06-05 14:55:54 +02:00
92b0d7c92d feat(emitting): broaden literal block fixtures 2026-06-05 13:37:33 +02:00
84a2de9ea1 test(compatibility): document unsupported yaml gaps 2026-06-05 13:29:22 +02:00
efdce11a9a Add scalar compatibility corpus 2026-06-05 13:07:04 +02:00
29ecce451a feat(codable): broaden compatibility coverage 2026-06-05 12:49:20 +02:00
5c3de786bf feat(coding): add unkeyed typed conversion 2026-06-05 12:23:52 +02:00
f80d7460ea feat(coding): add keyed typed conversion 2026-06-05 12:11:53 +02:00
8662de5403 feat(coding): add scalar typed conversion 2026-06-05 11:45:00 +02:00
e26c0917d4 critic-fix(validation): make rules immutable 2026-06-05 11:27:06 +02:00
66de760ff2 feat(validation): add predicate-gated rules 2026-06-05 11:21:23 +02:00
d06a00c9a6 test(emitting): add emitter corpus evidence 2026-06-05 11:13:29 +02:00
5fe9c1b8d1 feat(emitting): add flow collection output 2026-06-05 11:09:58 +02:00
6197c23e6f feat(emitting): add literal block scalar output 2026-06-05 11:06:19 +02:00
35fb919b74 feat(emitting): add scalar output options 2026-06-05 10:40:28 +02:00
7a71110bb4 feat(parsing): support directives and scalar tags 2026-06-05 10:16:34 +02:00
bc04c4815e feat(parsing): compose events into values 2026-06-05 10:07:28 +02:00
bee7683ee2 feat(parsing): parse token stream into events 2026-06-05 09:56:18 +02:00
11e7382ab1 feat(parsing): add reader scanner core 2026-06-05 07:40:23 +02:00
3436160306 feat(parsing): add parse event model
Add internal parsing events with marks, scalar styles, collection styles, alias events, and anchor/tag metadata. Add golden parser event tests for current block parser behavior.

Closes #2
2026-06-05 07:16:23 +02:00
9c718e3303 feat(package): bootstrap pure swift yaml package 2026-06-05 06:34:20 +02:00