mirror of https://github.com/status-im/NimYAML.git
Support missing keys/values in maps
This commit is contained in:
parent
ca077e54ca
commit
545bff673a
|
@ -192,7 +192,8 @@ template yieldDocumentEnd() {.dirty.} =
|
|||
template closeLevel(lvl: DocumentLevel) {.dirty.} =
|
||||
case lvl.mode
|
||||
of mExplicitBlockMapKey, mFlowMapKey:
|
||||
yieldError("Missing Map value!")
|
||||
yieldScalar("")
|
||||
yield YamlParserEvent(kind: yamlEndMap)
|
||||
of mImplicitBlockMapKey, mBlockMapValue, mFlowMapValue:
|
||||
yield YamlParserEvent(kind: yamlEndMap)
|
||||
of mBlockSequenceItem, mFlowSequenceItem:
|
||||
|
@ -225,9 +226,10 @@ template closeAllLevels() {.dirty.} =
|
|||
if ancestry.len == 0: break
|
||||
level = ancestry.pop()
|
||||
|
||||
template handleBlockIndicator(expected: openarray[DocumentLevelMode],
|
||||
template handleBlockIndicator(expected, possible: openarray[DocumentLevelMode],
|
||||
next: DocumentLevelMode,
|
||||
entering: YamlParserEventKind) {.dirty.} =
|
||||
entering: YamlParserEventKind,
|
||||
emptyScalarOnOpening: bool = false) {.dirty.} =
|
||||
leaveMoreIndentedLevels()
|
||||
if level.indicatorColumn == lex.column or
|
||||
level.indicatorColumn == -1 and level.indentationColumn == lex.column:
|
||||
|
@ -236,6 +238,17 @@ template handleBlockIndicator(expected: openarray[DocumentLevelMode],
|
|||
ancestry.add(level)
|
||||
level = DocumentLevel(mode: mUnknown, indicatorColumn: -1,
|
||||
indentationColumn: -1)
|
||||
else:
|
||||
# `in` does not work if possible is [], so we have to check for that
|
||||
when possible.len > 0:
|
||||
if level.mode in possible:
|
||||
yieldScalar("")
|
||||
level.mode = next
|
||||
ancestry.add(level)
|
||||
level = DocumentLevel(mode: mUnknown, indicatorColumn: -1,
|
||||
indentationColumn: -1)
|
||||
else:
|
||||
yieldError("Invalid token after " & $level.mode)
|
||||
else:
|
||||
yieldError("Invalid token after " & $level.mode)
|
||||
elif level.mode != mUnknown:
|
||||
|
@ -246,6 +259,8 @@ template handleBlockIndicator(expected: openarray[DocumentLevelMode],
|
|||
level.mode = next
|
||||
level.indicatorColumn = lex.column
|
||||
yieldStart(entering)
|
||||
if emptyScalarOnOpening:
|
||||
yieldScalar("")
|
||||
ancestry.add(level)
|
||||
level = DocumentLevel(mode: mUnknown, indicatorColumn: -1,
|
||||
indentationColumn: -1)
|
||||
|
@ -381,14 +396,16 @@ iterator events*(parser: var YamlSequentialParser,
|
|||
of yamlLineStart:
|
||||
discard
|
||||
of yamlDash:
|
||||
handleBlockIndicator([mBlockSequenceItem], mBlockSequenceItem,
|
||||
yamlStartSequence)
|
||||
handleBlockIndicator([mBlockSequenceItem], [],
|
||||
mBlockSequenceItem, yamlStartSequence)
|
||||
of yamlQuestionmark:
|
||||
handleBlockIndicator([mImplicitBlockMapKey, mBlockMapValue],
|
||||
[mExplicitBlockMapKey],
|
||||
mExplicitBlockMapKey, yamlStartMap)
|
||||
of yamlColon:
|
||||
handleBlockIndicator([mExplicitBlockMapKey],
|
||||
mBlockMapValue, yamlError)
|
||||
[mBlockMapValue, mImplicitBlockMapKey],
|
||||
mBlockMapValue, yamlStartMap, true)
|
||||
of yamlPipe, yamlGreater:
|
||||
blockScalar = if token == yamlPipe: bsLiteral else: bsFolded
|
||||
blockScalarIndentation = -1
|
||||
|
@ -419,15 +436,16 @@ iterator events*(parser: var YamlSequentialParser,
|
|||
scalarCacheIsQuoted = false
|
||||
scalarIndentation = lex.column
|
||||
of mBlockMapValue:
|
||||
ancestry.add(level)
|
||||
scalarCache = lex.content
|
||||
scalarCacheIsQuoted = false
|
||||
scalarIndentation = lex.column
|
||||
level = DocumentLevel(mode: mScalar, indicatorColumn: -1,
|
||||
indentationColumn:
|
||||
ancestry[ancestry.high].indentationColumn + 1)
|
||||
level.mode = mImplicitBlockMapKey
|
||||
of mExplicitBlockMapKey:
|
||||
yieldScalar()
|
||||
level.mode = mBlockMapValue
|
||||
continue
|
||||
else:
|
||||
yieldError("Unexpected scalar")
|
||||
yieldError("Unexpected scalar in " & $level.mode)
|
||||
state = ylBlockAfterScalar
|
||||
of lexer.yamlScalar:
|
||||
leaveMoreIndentedLevels()
|
||||
|
|
|
@ -68,15 +68,15 @@ proc printDifference(expected, actual: YamlParserEvent) =
|
|||
let msg = "[scalar] expected content \"" &
|
||||
expected.scalarContent & "\", got \"" &
|
||||
actual.scalarContent & "\" "
|
||||
if expected.scalarContent.len != actual.scalarContent.len:
|
||||
echo msg, "(length does not match)"
|
||||
else:
|
||||
for i in 0..expected.scalarContent.high:
|
||||
if i >= actual.scalarContent.high:
|
||||
echo msg, "(expected more chars, first char missing: ",
|
||||
cast[int](expected.scalarContent[i]), ")"
|
||||
break
|
||||
elif expected.scalarContent[i] != actual.scalarContent[i]:
|
||||
if expected.scalarContent[i] != actual.scalarContent[i]:
|
||||
echo msg, "(first different char at pos ", i,
|
||||
": expected ",
|
||||
cast[int](expected.scalarContent[i]), ", got ",
|
||||
cast[int](expected.scalarContent[i]),
|
||||
", got ",
|
||||
cast[int](actual.scalarContent[i]), ")"
|
||||
break
|
||||
else:
|
||||
|
@ -135,6 +135,17 @@ suite "Parsing":
|
|||
test "Parsing: Mixed Map (implicit to explicit)":
|
||||
ensure("a: b\n? c\n: d", startDoc(), startMap(), scalar("a"),
|
||||
scalar("b"), scalar("c"), scalar("d"), endMap(), endDoc())
|
||||
test "Parsing: Missing values in map":
|
||||
ensure("? a\n? b\nc:", startDoc(), startMap(), scalar("a"), scalar(""),
|
||||
scalar("b"), scalar(""), scalar("c"), scalar(""), endMap(),
|
||||
endDoc())
|
||||
test "Parsing: Missing keys in map":
|
||||
ensure(": a\n: b", startDoc(), startMap(), scalar(""), scalar("a"),
|
||||
scalar(""), scalar("b"), endMap(), endDoc())
|
||||
test "Parsing: Multiline scalars in explicit map":
|
||||
ensure("? a\n b\n: c\n d\n? e\n f", startDoc(), startMap(),
|
||||
scalar("a b"), scalar("c d"), scalar("e f"), scalar(""),
|
||||
endMap(), endDoc())
|
||||
test "Parsing: Map in Sequence":
|
||||
ensure(" - key: value", startDoc(), startSequence(), startMap(),
|
||||
scalar("key"), scalar("value"), endMap(), endSequence(),
|
||||
|
|
Loading…
Reference in New Issue