PureYAML/Sources/Parsing/LibYAML.SimpleKey.swift
Mihaela Mihaljevic b2d2d2f595 fix(parsing): accept tabs as separation, reject them as indentation
libyaml refuses to skip a tab in the inter-token whitespace whenever a
simple key is allowed, so a tab used as valid separation (after a '-',
'?', or ':' indicator, or before a flow collection) is reported as a
character that cannot start a token. But a tab is legal in-line
separation; it is only illegal as indentation.

The scanner now skips tabs in scan_to_next_token and records in
tabbedSeparation whether one preceded the pending token. A block entry,
an explicit key, or an implicit mapping key promoted by ':' is rejected
when reached through a tab (there the tab would be indentation), while a
scalar value or a flow collection is accepted. Tab-indented keys and
'-\t-' nested entries still reject.

Surpasses libyaml on 6BCT, 6CA3, A2M4, DK95/00, Q5MG, Y79Y/010.
Port score 299 -> 305.
2026-06-24 19:14:12 +02:00

29 lines
1.4 KiB
Swift

extension PureYAML.Parsing.LibYAML {
/// Port of `yaml_simple_key_t`. A potential implicit ("simple") mapping key:
/// a node that may turn out to be a key once a `:` is seen on the same line.
/// `tokenNumber` records where its `KEY` token must be spliced into the queue.
struct SimpleKey: Equatable {
/// Whether a simple key is still possible at this flow level.
var possible: Bool
/// Whether a `:` is required (a key sitting exactly at the block indent).
var required: Bool
/// The absolute token number where the `KEY` token is inserted.
var tokenNumber: Int
/// The position the potential key started at.
var mark: PureYAML.Parsing.Mark
/// Whether this key is a JSON-style node (a quoted flow scalar). A `:`
/// adjacent to such a key is a value indicator even without a following
/// space, per the YAML flow "adjacent value" rule.
var isJSON = false
/// Whether a tab preceded this key in its indentation. A tab may be
/// separation but never indentation, so promoting such a key to a block
/// mapping key (a `:` follows) is an error.
var tabbed = false
/// The empty entry pushed for a new flow level (`{ 0, 0, 0, {0,0,0} }`).
static var empty: Self {
Self(possible: false, required: false, tokenNumber: 0, mark: .start)
}
}
}