fix(parsing): carry spanned properties to a deeper indented node
An inline anchor with a tag on the next indented line, above a mapping indented deeper still (`key: &anchor` / ` !!map` / ` a: b`), left the node introduced by a further indent token after the properties were consumed. The parser could not read a node from that indent and rejected it as a missing node. The indented mapping value now descends through the deeper indent, carrying the accumulated anchor and tag to the node it introduces, so the properties attach to the mapping rather than to an empty value. Fixes yaml-test-suite BU8L; raises parse-level conformance to 312/333 (93.7%) and value-level to 205/205 (100.0%), with the should-error rate unchanged.
This commit is contained in:
parent
5528ce9aa4
commit
4dcedbd6aa
@ -84,6 +84,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
### Fixed
|
||||
|
||||
- Node properties that span their own indented lines above a further-indented node now attach to
|
||||
that node (`key: &anchor` then ` !!map` then ` a: b`). An inline anchor with a tag on the next
|
||||
indented line, above a mapping indented deeper still, left the node introduced by another indent
|
||||
token, which the parser could not read and rejected as a missing node. The indented mapping value
|
||||
now descends through that deeper indent, carrying the accumulated properties to the node. Fixes
|
||||
yaml-test-suite BU8L; raises parse-level conformance to 312/333 (93.7%) and value-level to 205/205
|
||||
(100.0%), with the should-error rate unchanged.
|
||||
|
||||
- A node property written on its own indented line above a zero-indent block sequence (`seq:` then
|
||||
` &anchor` then `- a` back at the key's column) now binds to that sequence. The grammar lets a
|
||||
block-in-block sequence sit at its parent's indentation while its property sits one level deeper,
|
||||
|
||||
@ -76,7 +76,14 @@ extension PureYAML.Parsing.TokenEventParser {
|
||||
_ = try expect("dedent") { $0.isDedent }
|
||||
return try parseBlockSequence(properties: carried, allowMappingKeyTerminator: true)
|
||||
}
|
||||
let node = try parseNode(properties: carried)
|
||||
// The node carrying the properties may itself be indented further, when the properties
|
||||
// span their own lines above it (`key: &anchor` / ` !!map` / ` a: b`): descend into that
|
||||
// deeper indented value rather than expecting the node directly after the properties.
|
||||
let node: PureYAML.Parsing.NodeResult = if cursor.current?.kind.isIndent == true {
|
||||
try parseIndentedMappingValue(properties: carried)
|
||||
} else {
|
||||
try parseNode(properties: carried)
|
||||
}
|
||||
try consumeIndentedMappingValueClose()
|
||||
return node
|
||||
}
|
||||
|
||||
24
Tests/MultilinePropertyIndentTests.swift
Normal file
24
Tests/MultilinePropertyIndentTests.swift
Normal file
@ -0,0 +1,24 @@
|
||||
@testable import PureYAML
|
||||
import Testing
|
||||
|
||||
@Suite("Node properties may span indented lines above a further-indented node")
|
||||
struct MultilinePropertyIndentTests {
|
||||
/// yaml-test-suite BU8L: an inline anchor and a tag on the next indented line are both properties
|
||||
/// of a mapping that is indented further still (`key: &anchor` / ` !!map` / ` a: b`). The parser
|
||||
/// descends through the deeper indent to the node rather than rejecting it as a missing node.
|
||||
@Test("An anchor then an indented tag attach to a further-indented mapping")
|
||||
func test_anchorThenTagOnDeeperMapping() throws {
|
||||
let root = try requireMapping(PureYAML.parse("key: &anchor\n !!map\n a: b\n"))
|
||||
let value = try requireMapping(#require(root?["key"]))
|
||||
#expect(value?["a"] == .string("b"))
|
||||
}
|
||||
|
||||
/// The same anchored mapping is reachable through an alias, confirming the anchor registered with
|
||||
/// the nested mapping and not with an empty node.
|
||||
@Test("The anchor on the spanned properties registers the nested mapping")
|
||||
func test_spannedPropertyAnchorRegisters() throws {
|
||||
let root = try requireMapping(PureYAML.parse("key: &anchor\n !!map\n a: b\nref: *anchor\n"))
|
||||
let aliased = try requireMapping(#require(root?["ref"]))
|
||||
#expect(aliased?["a"] == .string("b"))
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user