The conformance number was measured against a lossy oracle: the JSON projection (in.json) discards anchors, tags, and scalar styles, and exists for only about half the cases, so "passing" often meant only "parse did not throw". Measured against the official suite's own test.event event streams, the true exact conformance is 254 of 308 valid cases (40 emit a wrong event stream, 14 false-reject), well below the JSON-proxy figure. Add a canonical-event gate (Tests/CanonicalEventConformanceTests.swift) that serializes the parser's events into the yaml-test-suite yeast format and compares them exactly to each case's test.event, checking anchors, tags, scalar styles, flow vs block, and explicit document markers, for every valid case. The gate records the gap set and fails on any regression or unrecorded fix. All 402 test.event files are vendored alongside their inputs. To make the comparison exact, the parser Event model now records whether a document boundary was explicit (documentStart/documentEnd carry an `explicit` flag), distinguishing `---`/`...` from an implicit boundary. This resolves 89 cases that were previously correct but unverifiable without normalization. No parser behavior changed; this is measurement and model fidelity. The 40 wrong-event and 14 false-reject cases are the real remaining gaps, to be fixed against this gate.
105 lines
3.4 KiB
Swift
105 lines
3.4 KiB
Swift
extension PureYAML.Parsing {
|
|
enum Event: Equatable, CustomStringConvertible {
|
|
case streamStart(mark: Mark)
|
|
case streamEnd(mark: Mark)
|
|
case documentStart(explicit: Bool, mark: Mark)
|
|
case documentEnd(explicit: Bool, mark: Mark)
|
|
case sequenceStart(anchor: String?, tag: String?, style: CollectionStyle, mark: Mark)
|
|
case sequenceEnd(mark: Mark)
|
|
case mappingStart(anchor: String?, tag: String?, style: CollectionStyle, mark: Mark)
|
|
case mappingEnd(mark: Mark)
|
|
case scalar(value: String, anchor: String?, tag: String?, style: ScalarStyle, mark: Mark)
|
|
case alias(anchor: String, mark: Mark)
|
|
|
|
var description: String {
|
|
switch self {
|
|
case let .streamStart(mark):
|
|
"streamStart @\(mark)"
|
|
case let .streamEnd(mark):
|
|
"streamEnd @\(mark)"
|
|
case let .documentStart(explicit, mark):
|
|
"documentStart explicit=\(explicit) @\(mark)"
|
|
case let .documentEnd(explicit, mark):
|
|
"documentEnd explicit=\(explicit) @\(mark)"
|
|
case let .sequenceStart(anchor, tag, style, mark):
|
|
"sequenceStart anchor=\(describe(anchor)) tag=\(describe(tag)) style=\(style) @\(mark)"
|
|
case let .sequenceEnd(mark):
|
|
"sequenceEnd @\(mark)"
|
|
case let .mappingStart(anchor, tag, style, mark):
|
|
"mappingStart anchor=\(describe(anchor)) tag=\(describe(tag)) style=\(style) @\(mark)"
|
|
case let .mappingEnd(mark):
|
|
"mappingEnd @\(mark)"
|
|
case let .scalar(value, anchor, tag, style, mark):
|
|
"scalar value=\"\(escape(value))\" anchor=\(describe(anchor)) tag=\(describe(tag)) style=\(style) @\(mark)"
|
|
case let .alias(anchor, mark):
|
|
"alias anchor=\(anchor) @\(mark)"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
extension PureYAML.Parsing.Event {
|
|
var isMappingEnd: Bool {
|
|
if case .mappingEnd = self {
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
var isSequenceEnd: Bool {
|
|
if case .sequenceEnd = self {
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
var isStreamEnd: Bool {
|
|
if case .streamEnd = self {
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
var mark: PureYAML.Parsing.Mark {
|
|
switch self {
|
|
case let .alias(_, mark),
|
|
let .mappingEnd(mark),
|
|
let .mappingStart(_, _, _, mark),
|
|
let .scalar(_, _, _, _, mark),
|
|
let .sequenceEnd(mark),
|
|
let .sequenceStart(_, _, _, mark),
|
|
let .streamEnd(mark),
|
|
let .streamStart(mark):
|
|
mark
|
|
case let .documentEnd(_, mark),
|
|
let .documentStart(_, mark):
|
|
mark
|
|
}
|
|
}
|
|
|
|
private func describe(_ value: String?) -> String {
|
|
value ?? "-"
|
|
}
|
|
|
|
private func escape(_ value: String) -> String {
|
|
var output = ""
|
|
for character in value {
|
|
switch character {
|
|
case "\\":
|
|
output += "\\\\"
|
|
case "\"":
|
|
output += "\\\""
|
|
case "\n":
|
|
output += "\\n"
|
|
case "\r":
|
|
output += "\\r"
|
|
case "\t":
|
|
output += "\\t"
|
|
default:
|
|
output.append(character)
|
|
}
|
|
}
|
|
return output
|
|
}
|
|
}
|