From ca077e54ca2e2c55849612d744eac615f716f820 Mon Sep 17 00:00:00 2001 From: Felix Krause Date: Tue, 22 Dec 2015 21:08:58 +0100 Subject: [PATCH] Allow mixing explicit and implicit map keys --- src/yaml/sequential.nim | 33 +++++++++++++++++---------------- test/parsing.nim | 6 ++++++ 2 files changed, 23 insertions(+), 16 deletions(-) diff --git a/src/yaml/sequential.nim b/src/yaml/sequential.nim index ca72eda..f9b3156 100644 --- a/src/yaml/sequential.nim +++ b/src/yaml/sequential.nim @@ -39,8 +39,8 @@ type DocumentLevelMode = enum mBlockSequenceItem, mFlowSequenceItem, mExplicitBlockMapKey, - mExplicitBlockMapValue, mImplicitBlockMapKey, mImplicitBlockMapValue, - mFlowMapKey, mFlowMapValue, mScalar, mUnknown + mImplicitBlockMapKey, mBlockMapValue, mFlowMapKey, mFlowMapValue, + mScalar, mUnknown DocumentLevel = object mode: DocumentLevelMode @@ -193,8 +193,7 @@ template closeLevel(lvl: DocumentLevel) {.dirty.} = case lvl.mode of mExplicitBlockMapKey, mFlowMapKey: yieldError("Missing Map value!") - of mExplicitBlockMapValue, mImplicitBlockMapKey, mImplicitBlockMapValue, - mFlowMapValue: + of mImplicitBlockMapKey, mBlockMapValue, mFlowMapValue: yield YamlParserEvent(kind: yamlEndMap) of mBlockSequenceItem, mFlowSequenceItem: yield YamlParserEvent(kind: yamlEndSequence) @@ -215,7 +214,7 @@ template leaveMoreIndentedLevels() {.dirty.} = parent.indentationColumn >= lex.column): closeLevel(level) level = ancestry.pop() - if level.mode == mImplicitBlockMapValue: + if level.mode == mBlockMapValue: level.mode = mImplicitBlockMapKey else: break @@ -226,11 +225,13 @@ template closeAllLevels() {.dirty.} = if ancestry.len == 0: break level = ancestry.pop() -template handleBlockIndicator(expected, next: DocumentLevelMode, +template handleBlockIndicator(expected: openarray[DocumentLevelMode], + next: DocumentLevelMode, entering: YamlParserEventKind) {.dirty.} = leaveMoreIndentedLevels() - if level.indicatorColumn == lex.column: - if level.mode == expected: + if level.indicatorColumn == lex.column or + level.indicatorColumn == -1 and level.indentationColumn == lex.column: + if level.mode in expected: level.mode = next ancestry.add(level) level = DocumentLevel(mode: mUnknown, indicatorColumn: -1, @@ -380,14 +381,14 @@ iterator events*(parser: var YamlSequentialParser, of yamlLineStart: discard of yamlDash: - handleBlockIndicator(mBlockSequenceItem, mBlockSequenceItem, + handleBlockIndicator([mBlockSequenceItem], mBlockSequenceItem, yamlStartSequence) of yamlQuestionmark: - handleBlockIndicator(mExplicitBlockMapValue, + handleBlockIndicator([mImplicitBlockMapKey, mBlockMapValue], mExplicitBlockMapKey, yamlStartMap) of yamlColon: - handleBlockIndicator(mExplicitBlockMapKey, - mExplicitBlockMapValue, yamlError) + handleBlockIndicator([mExplicitBlockMapKey], + mBlockMapValue, yamlError) of yamlPipe, yamlGreater: blockScalar = if token == yamlPipe: bsLiteral else: bsFolded blockScalarIndentation = -1 @@ -417,7 +418,7 @@ iterator events*(parser: var YamlSequentialParser, scalarCache = lex.content scalarCacheIsQuoted = false scalarIndentation = lex.column - of mImplicitBlockMapValue: + of mBlockMapValue: ancestry.add(level) scalarCache = lex.content scalarCacheIsQuoted = false @@ -511,7 +512,7 @@ iterator events*(parser: var YamlSequentialParser, yield YamlParserEvent(kind: yamlStartMap, objAnchor: anchorNone, objTag: tagQuestionMark) - level.mode = mImplicitBlockMapValue + level.mode = mBlockMapValue ancestry.add(level) level = DocumentLevel(mode: mUnknown, indicatorColumn: -1, indentationColumn: -1) @@ -548,7 +549,7 @@ iterator events*(parser: var YamlSequentialParser, yield YamlParserEvent(kind: yamlStartMap, objAnchor: anchorNone, objTag: tagQuestionMark) - level.mode = mImplicitBlockMapValue + level.mode = mBlockMapValue ancestry.add(level) level = DocumentLevel(mode: mUnknown, indicatorColumn: -1, indentationColumn: -1) @@ -628,7 +629,7 @@ iterator events*(parser: var YamlSequentialParser, of lexer.yamlScalar: yieldScalar(lex.content, true) level = ancestry.pop() - assert level.mode == mImplicitBlockMapValue + assert level.mode == mBlockMapValue level.mode = mImplicitBlockMapKey state = ylBlockLineEnd of yamlScalarPart: diff --git a/test/parsing.nim b/test/parsing.nim index 9efdbba..969a0fd 100644 --- a/test/parsing.nim +++ b/test/parsing.nim @@ -129,6 +129,12 @@ suite "Parsing": ensure("? key\n: value\n? key2\n: value2", startDoc(), startMap(), scalar("key"), scalar("value"), scalar("key2"), scalar("value2"), endMap(), endDoc()) + test "Parsing: Mixed Map (explicit to implicit)": + ensure("? a\n: b\nc: d", startDoc(), startMap(), scalar("a"), + scalar("b"), scalar("c"), scalar("d"), endMap(), endDoc()) + 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: Map in Sequence": ensure(" - key: value", startDoc(), startSequence(), startMap(), scalar("key"), scalar("value"), endMap(), endSequence(),