fix(parsing): allow a directive after a document-end marker
A directive following a document-end marker ('...') begins the next
document's directive section, but the scanner rejected it: the
isDocumentClosed flag set by '...' tripped the directive guard, so a
multi-document stream where each document carries its own directives
('%TAG ...' / '--- doc' / '...' / '%TAG ...' / '--- doc') failed.
A directive now reopens the stream when it follows '...', clearing the
closed flag, while a directive after document content within the same
document stays rejected via the content guard. The directive still
requires its own '---', so a directive after '...' with no document start
is still an error. Multi-document streams already composed through the
stream mode; this removes the scanner-side block on per-document
directives.
Measured against the official YAML test-suite, parse-level conformance
rises from 278/333 (83.5%) to 283/333 (85.0%) with no regression.
This commit is contained in:
parent
25b1388dbb
commit
7e89ba1877
@ -23,6 +23,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
### Fixed
|
||||
|
||||
- A directive after a document-end marker (`...`) now begins the next document instead of being
|
||||
rejected. A multi-document stream where each document carries its own directives
|
||||
(`%TAG ...` / `--- doc` / `...` / `%TAG ...` / `--- doc`) is now accepted, since a directive
|
||||
following `...` opens the next document's directive section. A directive after document content
|
||||
within the same document is still rejected, and a directive after `...` still requires its own
|
||||
`---`. Lifts official test-suite parse-level conformance from 278/333 (83.5%) to 283/333
|
||||
(85.0%), with no regression.
|
||||
- A block sequence entry can no longer follow a flow collection that closed earlier on the same
|
||||
line (`- { y: z }- invalid`, `- [a] - b`); the entry would begin a sequence inline after a
|
||||
complete node. The scanner now tracks a top-level flow close on the current line and rejects a
|
||||
|
||||
@ -88,7 +88,12 @@ extension PureYAML.Parsing.Scanner {
|
||||
guard let name = parts.first else {
|
||||
return
|
||||
}
|
||||
guard !state.hasDocumentContent, !state.hasDocumentStartMarker, !state.isDocumentClosed else {
|
||||
// A directive after a document-end marker (`...`) begins the next document's directive
|
||||
// section, so it reopens the stream for a new document rather than being rejected.
|
||||
if state.isDocumentClosed {
|
||||
state.isDocumentClosed = false
|
||||
}
|
||||
guard !state.hasDocumentContent, !state.hasDocumentStartMarker else {
|
||||
throw PureYAML.Parsing.ParseError.unsupportedDirective(name: name, line: start.line)
|
||||
}
|
||||
// Every directive must be followed by an explicit `---`; record that one is now awaiting it.
|
||||
|
||||
28
Tests/DirectiveAfterDocumentEndTests.swift
Normal file
28
Tests/DirectiveAfterDocumentEndTests.swift
Normal file
@ -0,0 +1,28 @@
|
||||
@testable import PureYAML
|
||||
import Testing
|
||||
|
||||
@Suite("Directives after a document-end marker")
|
||||
struct DirectiveAfterDocumentEndTests {
|
||||
@Test("A directive after `...` begins the next document")
|
||||
func test_directiveAfterDocumentEndStartsNextDocument() throws {
|
||||
let docs = try PureYAML.parseStream("a\n...\n%YAML 1.2\n---\nb\n")
|
||||
#expect(docs.count == 2)
|
||||
#expect(docs[0].value == .string("a"))
|
||||
#expect(docs[1].value == .string("b"))
|
||||
}
|
||||
|
||||
@Test("A %TAG directive may be repeated for each document after `...`")
|
||||
func test_repeatedTagDirectivePerDocument() throws {
|
||||
let docs = try PureYAML.parseStream(
|
||||
"%TAG !m! !my-\n--- !m!light fluorescent\n...\n%TAG !m! !my-\n--- !m!light green\n",
|
||||
)
|
||||
#expect(docs.count == 2)
|
||||
}
|
||||
|
||||
@Test("A directive after `...` still requires its own document start")
|
||||
func test_directiveAfterDocumentEndStillRequiresDocument() throws {
|
||||
#expect(throws: PureYAML.Parsing.ParseError.self) {
|
||||
try PureYAML.parseStream("a\n...\n%YAML 1.2\n")
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user