PureYAML/Sources/Parsing/ParseError.LibYAML.swift
Mihaela Mihaljevic 561921df42 feat(parsing): route the event API through the ported libyaml engine
parseEvents now runs on the ported scanner+parser instead of the
hand-rolled approximation. Adds 1-based mark conversion at the boundary
(the port stays faithfully 0-based internally), translates the port's
scanner and parser errors into the diagnostic-aware ParseError with
precise codes (unterminatedQuotedString, unterminatedTag, tabIndentation)
and a readable malformed fallback, and retargets the canonical event gate
to track the port's gap set.

The port matches the canonical test.event on 253 of 308 valid cases;
the remaining gaps match libyaml's own behaviour and are the targets for
surpassing libyaml. Golden event and diagnostic expectations are rebased
onto the port where it is faithful or more correct (resolved verbatim
tags, libyaml's stream-end marks, reaching the real unterminated quote).
333 tests pass.
2026-06-24 17:32:29 +02:00

36 lines
1.7 KiB
Swift

extension PureYAML.Parsing.ParseError {
/// Translate a ported-scanner error into the package's diagnostic-aware error,
/// converting libyaml's 0-based mark to the 1-based convention and mapping the
/// well-known scanner failures to precise diagnostic codes.
init(translating error: PureYAML.Parsing.LibYAML.ScannerError) {
let line = error.mark.line + 1
let column = error.mark.column + 1
let context = error.context ?? ""
if error.problem.hasPrefix("found a tab") {
self = .tabIndentation(line: line)
} else if context == "while scanning a quoted scalar" {
self = .unterminatedQuotedString(line: line)
} else if context.hasPrefix("while scanning a tag") || context.hasSuffix("TAG directive") {
self = .unterminatedTag(line: line)
} else {
self = .malformed(reason: Self.reason(context: error.context, problem: error.problem), line: line, column: column)
}
}
/// Translate a ported-parser error into the package's diagnostic-aware error.
init(translating error: PureYAML.Parsing.LibYAML.ParserError) {
let line = error.mark.line + 1
let column = error.mark.column + 1
self = .malformed(reason: Self.reason(context: error.context, problem: error.problem), line: line, column: column)
}
/// Join a libyaml context and problem into one readable reason, e.g.
/// "while parsing a flow sequence, did not find expected ',' or ']'".
private static func reason(context: String?, problem: String) -> String {
guard let context else {
return problem
}
return "\(context), \(problem)"
}
}