PureYAML/Tests/AliasAsMappingKeyTests.swift
Mihaela M b45b7a4b7d fix(parsing): accept an alias node as an implicit mapping key
An alias may stand where a mapping key is expected (`*a : value`). The scanner
emits the implicit-key indicator before a scalar key that a `:` follows, but
not before an alias, so the parser, which already accepts an alias node in key
position, never entered the pair and rejected the alias as an unexpected token.

The scanner now emits the same indicator before an alias that a `:` (after
optional spaces) follows, in block context. A `:` written directly against the
alias stays part of its name, since `:` is a valid anchor-name character, so
only a space-separated `:` marks the alias as a key.

Fixes yaml-test-suite E76Z and 26DV; raises parse-level conformance to 310/333
(93.1%) and value-level to 203/203 (100.0%), with the should-error rate
unchanged.
2026-06-29 03:35:56 +02:00

35 lines
1.8 KiB
Swift

@testable import PureYAML
import Testing
@Suite("An alias node can serve as an implicit mapping key")
struct AliasAsMappingKeyTests {
/// yaml-test-suite E76Z: an alias may stand where a mapping key is expected (`*b : value`). The
/// scanner now emits the implicit-key indicator before an alias followed by a `:`, exactly as it
/// does for a scalar key, and the alias resolves to the anchored node's value.
@Test("An alias followed by a value indicator is a mapping key")
func test_aliasIsImplicitKey() throws {
let mapping = try requireMapping(PureYAML.parse("&a a: &b b\n*b : *a\n"))
#expect(mapping?["a"] == .string("b"))
#expect(mapping?["b"] == .string("a"))
}
/// yaml-test-suite 26DV exercises an alias key nested inside a block-mapping value, where the
/// alias resolves to an earlier anchored scalar and becomes that nested mapping's key.
@Test("An alias key resolves inside a nested block mapping value")
func test_aliasKeyInNestedMapping() throws {
let root = try requireMapping(PureYAML.parse("top1: &x scalar1\ntop3:\n *x : scalar3\n"))
#expect(root?["top1"] == .string("scalar1"))
let nested = try requireMapping(#require(root?["top3"]))
#expect(nested?["scalar1"] == .string("scalar3"))
}
/// A `:` written directly against an alias with no separating space is part of the alias name,
/// not a value indicator (`:` is a valid anchor-name character), so the alias is not a key here.
@Test("An alias with an adjacent colon keeps the colon in its name")
func test_adjacentColonStaysInName() throws {
let mapping = try requireMapping(PureYAML.parse("key: &a: scalar\nref: *a:\n"))
#expect(mapping?["key"] == .string("scalar"))
#expect(mapping?["ref"] == .string("scalar"))
}
}