A flow mapping entry may begin with its `:` indicator for an empty key
(`{ : value }`) or carry only properties before the `:` (`{ !!str : value }`).
Both resolve to a null key, but parseFlowMappingPair required a node before
the `:` and raised "expected a YAML node".
Emit a null key in that position instead, mirroring the empty-value handling
already present after the `:`. The change consumes the key's properties first
so a property-only key keeps its tag or anchor, and is confined to flow
mapping key position, where a null key is unambiguously valid; an entry with
no `:` at all (`{ a, }`) still errors.
Raises yaml-test-suite parse-level to 297/333 (89.2%) and value-level to
174/192, with the should-error rejection rate unchanged (no invalid document
newly accepted). 422 tests pass.
52 lines
2.0 KiB
Swift
52 lines
2.0 KiB
Swift
@testable import PureYAML
|
|
import Testing
|
|
|
|
/// A flow mapping entry may begin with its `:` indicator, giving an empty (null) key, e.g. `{ : v }`,
|
|
/// or carry only properties before the `:`, e.g. `{ !!str : v }`. Both resolve to a null key, which
|
|
/// the parser now emits rather than demanding a node before the `:`. The allowance is local to flow
|
|
/// mapping key position, so an entry with no `:` at all (`{ a, }`) is still an error.
|
|
@Suite("Flow mapping empty key")
|
|
struct FlowMappingEmptyKeyTests {
|
|
@Test("A flow mapping entry that begins with a colon has an empty key")
|
|
func test_emptyKey() throws {
|
|
#expect(try PureYAML.parse("{ : a }\n") == .mapping(.init([
|
|
.init(keyNode: .string(""), value: .string("a")),
|
|
])))
|
|
}
|
|
|
|
@Test("An empty key sits alongside ordinary entries")
|
|
func test_emptyKeyAmongEntries() throws {
|
|
#expect(try PureYAML.parse("{ a: b, : c }\n") == .mapping(.init([
|
|
.init(key: "a", value: .string("b")),
|
|
.init(keyNode: .string(""), value: .string("c")),
|
|
])))
|
|
}
|
|
|
|
@Test("Both key and value may be empty in one entry")
|
|
func test_emptyKeyAndValue() throws {
|
|
#expect(try PureYAML.parse("{ : }\n") == .mapping(.init([
|
|
.init(keyNode: .string(""), value: .null),
|
|
])))
|
|
}
|
|
|
|
@Test("A key carrying only a tag is a null key and parses")
|
|
func test_propertyOnlyKey() throws {
|
|
// `{ foo : !!str, !!str : bar }`: the first value and the second key are property-only nulls.
|
|
_ = try PureYAML.parse("{ foo : !!str, !!str : bar }\n")
|
|
}
|
|
|
|
@Test("An empty value is still accepted, unchanged")
|
|
func test_emptyValueUnchanged() throws {
|
|
#expect(try PureYAML.parse("{ a: }\n") == .mapping(.init([
|
|
.init(key: "a", value: .null),
|
|
])))
|
|
}
|
|
|
|
@Test("A flow mapping entry with no colon at all is still an error")
|
|
func test_entryWithoutColonRejected() {
|
|
#expect(throws: PureYAML.Parsing.ParseError.self) {
|
|
try PureYAML.parse("{ a, }\n")
|
|
}
|
|
}
|
|
}
|