fix(parsing): parse a leading ':' flow-sequence entry as an empty-key pair
A flow sequence entry that begins with ':' (e.g. '[ : v ]') is a single-pair mapping with an empty key, which YAML 1.2 permits but libyaml rejects by handing the leading VALUE token to its node parser. Open the implicit single-pair mapping on a leading ':' in the flow-sequence-entry parser, and leave the VALUE token for the mapping value state to consume so the value is parsed rather than dropped. Surpasses libyaml on CFD4. Port score 298 -> 299.
This commit is contained in:
parent
ff199516ac
commit
8092897612
@ -22,6 +22,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
### Fixed
|
||||
|
||||
- Parse a flow sequence entry that begins with `:` as a single-pair mapping with
|
||||
an empty key (`[ : v ]`). libyaml hands the leading VALUE token to its node
|
||||
parser and fails. The flow-sequence-entry parser now opens the implicit mapping
|
||||
on a leading `:` and leaves the indicator for the value state, so the value is
|
||||
parsed rather than dropped. Surpasses libyaml on CFD4.
|
||||
- Apply the YAML 1.2 flow `:` rule instead of libyaml's "always a value
|
||||
indicator in flow". In a flow collection a `:` only ends a node when it is
|
||||
followed by whitespace, the end of input, or a flow indicator, or when it is
|
||||
|
||||
@ -24,6 +24,12 @@ extension PureYAML.Parsing.LibYAML.Parser {
|
||||
skipToken()
|
||||
return .mappingStart(anchor: nil, tag: nil, style: .flow, mark: token.startMark)
|
||||
}
|
||||
if isValue(token) {
|
||||
// A leading `:` opens a single-pair mapping with an empty key
|
||||
// (`[ : v ]`). Keep the VALUE token for the mapping-key state.
|
||||
state = .flowSequenceEntryMappingKey
|
||||
return .mappingStart(anchor: nil, tag: nil, style: .flow, mark: token.startMark)
|
||||
}
|
||||
if !isFlowSequenceEnd(token) {
|
||||
states.append(.flowSequenceEntry)
|
||||
return try parseNode(block: false, indentlessSequence: false)
|
||||
@ -42,7 +48,9 @@ extension PureYAML.Parsing.LibYAML.Parser {
|
||||
states.append(.flowSequenceEntryMappingValue)
|
||||
return try parseNode(block: false, indentlessSequence: false)
|
||||
}
|
||||
if isFlowSequenceEnd(token) {
|
||||
// An empty key: leave a VALUE token for the value state to consume (so the
|
||||
// value is parsed); a closing `]` ends the pair with an empty value too.
|
||||
if isValue(token) || isFlowSequenceEnd(token) {
|
||||
state = .flowSequenceEntryMappingValue
|
||||
return processEmptyScalar(at: token.startMark)
|
||||
}
|
||||
|
||||
@ -12,7 +12,7 @@ struct CanonicalEventConformanceTests {
|
||||
/// Valid suite cases whose event stream PureYAML does NOT yet emit exactly.
|
||||
/// This is the authoritative gap set: a fix removes an id (and the test fails
|
||||
/// until it is removed), a regression adds one (and the test fails). Of these,
|
||||
/// 8 currently throw on valid input and 2 emit a wrong event stream.
|
||||
/// 7 currently throw on valid input and 2 emit a wrong event stream.
|
||||
static let knownEventGaps: Set<String> = [
|
||||
// Gap set for the ported libyaml engine. Verified against the libyaml
|
||||
// reference dumper: on all but four of these the port matches libyaml
|
||||
@ -22,7 +22,7 @@ struct CanonicalEventConformanceTests {
|
||||
//
|
||||
// false-rejects (parseEvents throws on valid input, as libyaml does)
|
||||
"6BCT", "6CA3",
|
||||
"A2M4", "CFD4", "DK95/00",
|
||||
"A2M4", "DK95/00",
|
||||
"DK95/04",
|
||||
"Q5MG",
|
||||
"Y79Y/010",
|
||||
|
||||
Loading…
Reference in New Issue
Block a user