fix(parsing): reject a lone dash before a flow indicator
In a flow collection a '-' that begins a plain scalar must be followed by
a non-indicator character. Immediately before a flow indicator ('[-]',
'[-, -]', '{a: -}') the dash is not a valid scalar, but the scanner
accepted it as the scalar '-'.
scanToken now rejects a '-' in flow context when the next character is a
flow indicator, before falling through to plain-scalar scanning. A dash
followed by ordinary content stays valid: negative numbers, a dash inside
a scalar, a dash starting a word, and a quoted dash are unaffected.
Measured against the official YAML test-suite, parse-level conformance
rises from 273/333 (82.0%) to 275/333 (82.6%) with no regression.
This commit is contained in:
parent
f1db1344da
commit
30dbd9316b
@ -23,6 +23,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
### Fixed
|
||||
|
||||
- A `-` immediately before a flow indicator is no longer treated as a scalar. In a flow collection
|
||||
a `-` that begins a plain scalar must be followed by a non-indicator character, so `[-]`,
|
||||
`[-, -]`, and `{a: -}` are now rejected. A dash followed by ordinary content is unaffected:
|
||||
negative numbers (`[-1, -2]`), a dash inside a scalar (`a-b`), a dash starting a word (`-x`), and
|
||||
a quoted dash all stay valid. Lifts official test-suite parse-level conformance from 273/333
|
||||
(82.0%) to 275/333 (82.6%), with no regression.
|
||||
- A block scalar leading blank line that is more indented than the content is now rejected. The
|
||||
spec forbids a leading empty line from containing more spaces than the first non-empty line, so a
|
||||
block scalar whose blank lines are wider than its content (`|` then a 5-space blank then 2-space
|
||||
|
||||
@ -164,6 +164,16 @@ extension PureYAML.Parsing.Scanner {
|
||||
if try scanNodePropertyToken(character, state: &state) {
|
||||
return
|
||||
}
|
||||
// In a flow collection, a `-` that begins a plain scalar must be followed by a non-indicator
|
||||
// character. Immediately before a flow indicator (`[-]`, `[-, -]`) it is not a valid scalar.
|
||||
if state.flowDepth > 0, character == "-", let next = state.reader.peek(offset: 1), isFlowDelimiter(next) {
|
||||
throw PureYAML.Parsing.ParseError.unexpectedToken(
|
||||
expected: "a flow value",
|
||||
actual: "-",
|
||||
line: state.reader.mark.line,
|
||||
column: state.reader.mark.column,
|
||||
)
|
||||
}
|
||||
scanPlainScalar(&state)
|
||||
}
|
||||
|
||||
|
||||
26
Tests/FlowDashScalarTests.swift
Normal file
26
Tests/FlowDashScalarTests.swift
Normal file
@ -0,0 +1,26 @@
|
||||
@testable import PureYAML
|
||||
import Testing
|
||||
|
||||
@Suite("A dash before a flow indicator")
|
||||
struct FlowDashScalarTests {
|
||||
@Test("A `-` immediately before a flow indicator is not a valid scalar", arguments: [
|
||||
"[-]\n", // a lone dash before `]`
|
||||
"---\n- [-, -]\n", // dashes before `,` and `]`
|
||||
"{a: -}\n", // a lone dash before `}`
|
||||
])
|
||||
func test_dashBeforeFlowIndicatorRejected(_ yaml: String) throws {
|
||||
#expect(throws: PureYAML.Parsing.ParseError.self) {
|
||||
try PureYAML.parse(yaml)
|
||||
}
|
||||
}
|
||||
|
||||
@Test("A dash followed by a non-indicator character stays a valid scalar", arguments: [
|
||||
"[-1, -2]\n", // negative numbers
|
||||
"[a-b, c-d]\n", // a dash inside a scalar
|
||||
"[-x, -y]\n", // a dash starting a word
|
||||
"[\"-\", '-']\n", // a quoted dash
|
||||
])
|
||||
func test_validDashScalars(_ yaml: String) throws {
|
||||
_ = try PureYAML.parse(yaml)
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user