Allow mixing explicit and implicit map keys

This commit is contained in:
Felix Krause 2015-12-22 21:08:58 +01:00
parent c1880b5117
commit ca077e54ca
2 changed files with 23 additions and 16 deletions

View File

@ -39,8 +39,8 @@ type
DocumentLevelMode = enum DocumentLevelMode = enum
mBlockSequenceItem, mFlowSequenceItem, mExplicitBlockMapKey, mBlockSequenceItem, mFlowSequenceItem, mExplicitBlockMapKey,
mExplicitBlockMapValue, mImplicitBlockMapKey, mImplicitBlockMapValue, mImplicitBlockMapKey, mBlockMapValue, mFlowMapKey, mFlowMapValue,
mFlowMapKey, mFlowMapValue, mScalar, mUnknown mScalar, mUnknown
DocumentLevel = object DocumentLevel = object
mode: DocumentLevelMode mode: DocumentLevelMode
@ -193,8 +193,7 @@ template closeLevel(lvl: DocumentLevel) {.dirty.} =
case lvl.mode case lvl.mode
of mExplicitBlockMapKey, mFlowMapKey: of mExplicitBlockMapKey, mFlowMapKey:
yieldError("Missing Map value!") yieldError("Missing Map value!")
of mExplicitBlockMapValue, mImplicitBlockMapKey, mImplicitBlockMapValue, of mImplicitBlockMapKey, mBlockMapValue, mFlowMapValue:
mFlowMapValue:
yield YamlParserEvent(kind: yamlEndMap) yield YamlParserEvent(kind: yamlEndMap)
of mBlockSequenceItem, mFlowSequenceItem: of mBlockSequenceItem, mFlowSequenceItem:
yield YamlParserEvent(kind: yamlEndSequence) yield YamlParserEvent(kind: yamlEndSequence)
@ -215,7 +214,7 @@ template leaveMoreIndentedLevels() {.dirty.} =
parent.indentationColumn >= lex.column): parent.indentationColumn >= lex.column):
closeLevel(level) closeLevel(level)
level = ancestry.pop() level = ancestry.pop()
if level.mode == mImplicitBlockMapValue: if level.mode == mBlockMapValue:
level.mode = mImplicitBlockMapKey level.mode = mImplicitBlockMapKey
else: else:
break break
@ -226,11 +225,13 @@ template closeAllLevels() {.dirty.} =
if ancestry.len == 0: break if ancestry.len == 0: break
level = ancestry.pop() level = ancestry.pop()
template handleBlockIndicator(expected, next: DocumentLevelMode, template handleBlockIndicator(expected: openarray[DocumentLevelMode],
next: DocumentLevelMode,
entering: YamlParserEventKind) {.dirty.} = entering: YamlParserEventKind) {.dirty.} =
leaveMoreIndentedLevels() leaveMoreIndentedLevels()
if level.indicatorColumn == lex.column: if level.indicatorColumn == lex.column or
if level.mode == expected: level.indicatorColumn == -1 and level.indentationColumn == lex.column:
if level.mode in expected:
level.mode = next level.mode = next
ancestry.add(level) ancestry.add(level)
level = DocumentLevel(mode: mUnknown, indicatorColumn: -1, level = DocumentLevel(mode: mUnknown, indicatorColumn: -1,
@ -380,14 +381,14 @@ iterator events*(parser: var YamlSequentialParser,
of yamlLineStart: of yamlLineStart:
discard discard
of yamlDash: of yamlDash:
handleBlockIndicator(mBlockSequenceItem, mBlockSequenceItem, handleBlockIndicator([mBlockSequenceItem], mBlockSequenceItem,
yamlStartSequence) yamlStartSequence)
of yamlQuestionmark: of yamlQuestionmark:
handleBlockIndicator(mExplicitBlockMapValue, handleBlockIndicator([mImplicitBlockMapKey, mBlockMapValue],
mExplicitBlockMapKey, yamlStartMap) mExplicitBlockMapKey, yamlStartMap)
of yamlColon: of yamlColon:
handleBlockIndicator(mExplicitBlockMapKey, handleBlockIndicator([mExplicitBlockMapKey],
mExplicitBlockMapValue, yamlError) mBlockMapValue, yamlError)
of yamlPipe, yamlGreater: of yamlPipe, yamlGreater:
blockScalar = if token == yamlPipe: bsLiteral else: bsFolded blockScalar = if token == yamlPipe: bsLiteral else: bsFolded
blockScalarIndentation = -1 blockScalarIndentation = -1
@ -417,7 +418,7 @@ iterator events*(parser: var YamlSequentialParser,
scalarCache = lex.content scalarCache = lex.content
scalarCacheIsQuoted = false scalarCacheIsQuoted = false
scalarIndentation = lex.column scalarIndentation = lex.column
of mImplicitBlockMapValue: of mBlockMapValue:
ancestry.add(level) ancestry.add(level)
scalarCache = lex.content scalarCache = lex.content
scalarCacheIsQuoted = false scalarCacheIsQuoted = false
@ -511,7 +512,7 @@ iterator events*(parser: var YamlSequentialParser,
yield YamlParserEvent(kind: yamlStartMap, yield YamlParserEvent(kind: yamlStartMap,
objAnchor: anchorNone, objAnchor: anchorNone,
objTag: tagQuestionMark) objTag: tagQuestionMark)
level.mode = mImplicitBlockMapValue level.mode = mBlockMapValue
ancestry.add(level) ancestry.add(level)
level = DocumentLevel(mode: mUnknown, indicatorColumn: -1, level = DocumentLevel(mode: mUnknown, indicatorColumn: -1,
indentationColumn: -1) indentationColumn: -1)
@ -548,7 +549,7 @@ iterator events*(parser: var YamlSequentialParser,
yield YamlParserEvent(kind: yamlStartMap, yield YamlParserEvent(kind: yamlStartMap,
objAnchor: anchorNone, objAnchor: anchorNone,
objTag: tagQuestionMark) objTag: tagQuestionMark)
level.mode = mImplicitBlockMapValue level.mode = mBlockMapValue
ancestry.add(level) ancestry.add(level)
level = DocumentLevel(mode: mUnknown, indicatorColumn: -1, level = DocumentLevel(mode: mUnknown, indicatorColumn: -1,
indentationColumn: -1) indentationColumn: -1)
@ -628,7 +629,7 @@ iterator events*(parser: var YamlSequentialParser,
of lexer.yamlScalar: of lexer.yamlScalar:
yieldScalar(lex.content, true) yieldScalar(lex.content, true)
level = ancestry.pop() level = ancestry.pop()
assert level.mode == mImplicitBlockMapValue assert level.mode == mBlockMapValue
level.mode = mImplicitBlockMapKey level.mode = mImplicitBlockMapKey
state = ylBlockLineEnd state = ylBlockLineEnd
of yamlScalarPart: of yamlScalarPart:

View File

@ -129,6 +129,12 @@ suite "Parsing":
ensure("? key\n: value\n? key2\n: value2", startDoc(), startMap(), ensure("? key\n: value\n? key2\n: value2", startDoc(), startMap(),
scalar("key"), scalar("value"), scalar("key2"), scalar("value2"), scalar("key"), scalar("value"), scalar("key2"), scalar("value2"),
endMap(), endDoc()) 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": test "Parsing: Map in Sequence":
ensure(" - key: value", startDoc(), startSequence(), startMap(), ensure(" - key: value", startDoc(), startSequence(), startMap(),
scalar("key"), scalar("value"), endMap(), endSequence(), scalar("key"), scalar("value"), endMap(), endSequence(),