The scalar event now carries the scanner token's end mark, so a located scalar's range spans the whole token (end exclusive, one past the last character) instead of being start-anchored. This gives consumers exact highlight widths and is the prerequisite for surgical, position-based text edits. Only the scalar event case gained a field; the value tree, its equality, and the event dump (which compares value and style, not marks) are unchanged, so the canonical-event and whole-suite gates stay green (343 tests).
135 lines
4.9 KiB
Swift
135 lines
4.9 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, endMark: 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 {
|
|
/// Re-emit the event with libyaml's 0-based line/column mark converted to the
|
|
/// package's 1-based convention (the byte index is already 0-based in both).
|
|
func bumpingMark() -> Self {
|
|
let source = mark
|
|
let bumped = PureYAML.Parsing.Mark(line: source.line + 1, column: source.column + 1, index: source.index)
|
|
switch self {
|
|
case .streamStart:
|
|
return .streamStart(mark: bumped)
|
|
case .streamEnd:
|
|
return .streamEnd(mark: bumped)
|
|
case let .documentStart(explicit, _):
|
|
return .documentStart(explicit: explicit, mark: bumped)
|
|
case let .documentEnd(explicit, _):
|
|
return .documentEnd(explicit: explicit, mark: bumped)
|
|
case let .sequenceStart(anchor, tag, style, _):
|
|
return .sequenceStart(anchor: anchor, tag: tag, style: style, mark: bumped)
|
|
case .sequenceEnd:
|
|
return .sequenceEnd(mark: bumped)
|
|
case let .mappingStart(anchor, tag, style, _):
|
|
return .mappingStart(anchor: anchor, tag: tag, style: style, mark: bumped)
|
|
case .mappingEnd:
|
|
return .mappingEnd(mark: bumped)
|
|
case let .scalar(value, anchor, tag, style, _, endMark):
|
|
let bumpedEnd = PureYAML.Parsing.Mark(line: endMark.line + 1, column: endMark.column + 1, index: endMark.index)
|
|
return .scalar(value: value, anchor: anchor, tag: tag, style: style, mark: bumped, endMark: bumpedEnd)
|
|
case let .alias(anchor, _):
|
|
return .alias(anchor: anchor, mark: bumped)
|
|
}
|
|
}
|
|
|
|
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
|
|
}
|
|
}
|