A ':' that opens a line with no key before it is a mapping entry with a
null key (': value', a bare ':', or a null-keyed entry among others). The
scanner emitted the ':' with no preceding key, so the parser rejected it
as a missing node.
The scanner now synthesizes the empty key and its node for such a ':'. To
avoid mistaking an explicit key's value indicator for a null key, it tracks
a pending block-level '?' key: a ':' opening a line is that key's value
when one is pending, and only a synthesized null key otherwise. The flag
is set and cleared only at flow depth zero, so a ':' inside a flow complex
key ('? {a: b}' then ': c') does not disturb the pending block key.
Measured against the official YAML test-suite, parse-level conformance
rises from 283/333 (85.0%) to 287/333 (86.2%) with no regression.
34 lines
1.3 KiB
Swift
34 lines
1.3 KiB
Swift
@testable import PureYAML
|
|
import Testing
|
|
|
|
@Suite("Implicit null mapping keys")
|
|
struct ImplicitNullKeyTests {
|
|
@Test("A `:` opening a line is an implicit null key")
|
|
func test_implicitNullKey() throws {
|
|
#expect(try PureYAML.parse(": value\n") == .mapping(.init([
|
|
.init(keyNode: .string(""), value: .string("value")),
|
|
])))
|
|
}
|
|
|
|
@Test("Several null-keyed entries and a bare `:` parse")
|
|
func test_multipleNullKeys() throws {
|
|
_ = try PureYAML.parse(": a\n: b\n")
|
|
_ = try PureYAML.parse(":\n")
|
|
#expect(try PureYAML.parse("a: 1\n: b\n") == .mapping(.init([
|
|
.init(key: "a", value: .int(1)),
|
|
.init(keyNode: .string(""), value: .string("b")),
|
|
])))
|
|
}
|
|
|
|
@Test("Explicit keys, including a complex one, are not mistaken for null keys")
|
|
func test_explicitKeysUnaffected() throws {
|
|
#expect(try PureYAML.parse("? a\n: b\n") == .mapping(.init([
|
|
.init(key: "a", value: .string("b")),
|
|
])))
|
|
// The `:` after a flow complex key is the key's value, not a null key.
|
|
#expect(try PureYAML.parse("? {a: b}\n: c\n") == .mapping(.init([
|
|
.init(keyNode: .mapping(.init([.init(key: "a", value: .string("b"))])), value: .string("c")),
|
|
])))
|
|
}
|
|
}
|