extension PureYAML.Parsing.Scanner { /// Emits the implicit-key marker before a block-level flow collection that a `: ` follows, so the /// flow node is parsed as a mapping key (e.g. `[a, b]: value`) through the same path a scalar key /// takes. Skipped inside a flow context, after a mapping value already on the line (block style /// allows one pair per line), and under a pending explicit `?` key, which marks its own key. func appendFlowImplicitKeyMarkerIfNeeded(state: inout State) { guard state.flowDepth == 0, !state.sawMappingValueOnLine, !state.pendingExplicitKey, flowCollectionIsImplicitKey(state: state) else { return } let mark = state.reader.mark state.append(.mappingKey, mark: mark, endMark: mark) } /// Looks ahead from a block-level flow collection opener (`[` or `{`) to decide whether the whole /// collection is an implicit mapping key: a flow node immediately followed by a `: ` mapping-value /// indicator, e.g. `[a, b]: value` or `{a: 1}: value`. Quoted scalars are skipped so brackets and /// colons inside them do not affect the nesting count, and the `:` must sit on the same line as /// the close (only spaces between), since a block implicit key carries its `:` on its own line. /// Returns false if the brackets do not balance before end of input. func flowCollectionIsImplicitKey(state: State) -> Bool { var depth = 0 var offset = 0 while let character = state.reader.peek(offset: offset) { // A block implicit key must lie on a single line, so a flow collection that spans a line // break (outside any quoted scalar) before its `:` cannot be one: `[23\n]: 42` is an error. if isLineBreak(character) { return false } switch character { case "'": offset = skipSingleQuotedLookahead(after: offset, state: state) case "\"": offset = skipDoubleQuotedLookahead(after: offset, state: state) case "[", "{": depth += 1 offset += 1 case "]", "}": depth -= 1 offset += 1 guard depth > 0 else { while state.reader.peek(offset: offset) == " " { offset += 1 } return state.reader.peek(offset: offset) == ":" && isBlockMappingValueBoundary(state.reader.peek(offset: offset + 1)) } default: offset += 1 } } return false } /// Returns the offset just past the closing `'` of a single-quoted scalar that opened at `open`, /// treating a doubled `''` as an escaped quote rather than a close. private func skipSingleQuotedLookahead(after open: Int, state: State) -> Int { var offset = open + 1 while let character = state.reader.peek(offset: offset) { if character == "'" { if state.reader.peek(offset: offset + 1) == "'" { offset += 2 continue } return offset + 1 } offset += 1 } return offset } /// Returns the offset just past the closing `"` of a double-quoted scalar that opened at `open`, /// skipping `\`-escaped characters so an escaped quote does not end the scan early. private func skipDoubleQuotedLookahead(after open: Int, state: State) -> Int { var offset = open + 1 while let character = state.reader.peek(offset: offset) { if character == "\\" { offset += 2 continue } if character == "\"" { return offset + 1 } offset += 1 } return offset } }