Routes the value and stream APIs through the ported scanner+parser (the event API already was), so PureYAML now parses entirely on the libyaml port. Adds the features needed to match and exceed the previous engine: JSON UTF-16 surrogate-pair \u escapes, bare documents after an explicit `...`, reserved-directive handling that still requires a following `---`, and a 64-level nesting bound enforced on the event stream so deeply nested input fails with nestingTooDeep instead of overflowing a recursive consumer. Parser errors are translated to the diagnostic-aware ParseError, recovering precise codes where identifiable and a readable malformed fallback otherwise; error-reporting fixtures are rebased onto the port. Canonical event conformance: 268 -> 271 of 308 (7Z25, HWV9, QT73). 393 tests pass.
68 lines
2.6 KiB
Swift
68 lines
2.6 KiB
Swift
extension PureYAML.Parsing.Parser {
|
|
func parseEvents(_ yaml: String) throws -> [PureYAML.Parsing.Event] {
|
|
let events: [PureYAML.Parsing.Event]
|
|
do {
|
|
var parser = try PureYAML.Parsing.LibYAML.Parser(yaml)
|
|
events = try parser.parse().map { $0.bumpingMark() }
|
|
} catch let error as PureYAML.Parsing.LibYAML.ScannerError {
|
|
throw PureYAML.Parsing.ParseError(translating: error)
|
|
} catch let error as PureYAML.Parsing.LibYAML.ParserError {
|
|
throw PureYAML.Parsing.ParseError(translating: error)
|
|
}
|
|
try enforceNestingLimit(events)
|
|
return events
|
|
}
|
|
|
|
/// The deepest collection nesting the value/event composers will build. The
|
|
/// ported parser produces events iteratively without recursion, but the
|
|
/// composers, equality, hashing, and `Model/Value` teardown all recurse with
|
|
/// the nesting depth, so the event stream is bounded here before any recursive
|
|
/// consumer runs. 64 accepts every realistic document yet rejects pathological
|
|
/// input well before it can overflow the stack.
|
|
static var maxNestingDepth: Int {
|
|
64
|
|
}
|
|
|
|
/// Reject an event stream that nests collections past ``maxNestingDepth`` with
|
|
/// a ``ParseError/nestingTooDeep(line:column:)`` so deeply nested input fails
|
|
/// cleanly instead of overflowing a recursive consumer's stack.
|
|
private func enforceNestingLimit(_ events: [PureYAML.Parsing.Event]) throws {
|
|
var depth = 0
|
|
for event in events {
|
|
switch event {
|
|
case .sequenceStart, .mappingStart:
|
|
depth += 1
|
|
if depth > Self.maxNestingDepth {
|
|
throw PureYAML.Parsing.ParseError.nestingTooDeep(line: event.mark.line, column: event.mark.column)
|
|
}
|
|
case .sequenceEnd, .mappingEnd:
|
|
depth -= 1
|
|
default:
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
func parseStreaming(_ yaml: String) throws -> PureYAML.Model.Value {
|
|
var composer = PureYAML.Parsing.EventStreamComposer(
|
|
scalarParser: self,
|
|
mode: .singleDocument,
|
|
)
|
|
for event in try parseEvents(yaml) {
|
|
try composer.consume(event)
|
|
}
|
|
return try composer.composedValue()
|
|
}
|
|
|
|
func parseStreamStreaming(_ yaml: String) throws -> [PureYAML.Stream.Document] {
|
|
var composer = PureYAML.Parsing.EventStreamComposer(
|
|
scalarParser: self,
|
|
mode: .stream,
|
|
)
|
|
for event in try parseEvents(yaml) {
|
|
try composer.consume(event)
|
|
}
|
|
return try composer.composedStream()
|
|
}
|
|
}
|