From 2c9d065ecb0e5dbd6f5629efb926b3b3345b69e0 Mon Sep 17 00:00:00 2001 From: Felix Krause Date: Sun, 27 Dec 2015 17:37:42 +0100 Subject: [PATCH] Support tags for sequences and maps in block style --- src/private/lexer.nim | 1 + src/private/sequential.nim | 36 ++++++++++++++++++++---------------- test/parsing.nim | 10 ++++++++-- 3 files changed, 29 insertions(+), 18 deletions(-) diff --git a/src/private/lexer.nim b/src/private/lexer.nim index 9fdea60..a97e52d 100644 --- a/src/private/lexer.nim +++ b/src/private/lexer.nim @@ -731,6 +731,7 @@ iterator tokens(my: var YamlLexer): YamlLexerToken {.closure.} = state = ylTagHandle my.content = "!" lastSpecialChar = '\0' + my.column = curPos - 1 else: my.content.add(lastSpecialChar) advanceTypeHint(lastSpecialChar) diff --git a/src/private/sequential.nim b/src/private/sequential.nim index ba46626..9d3e0cf 100644 --- a/src/private/sequential.nim +++ b/src/private/sequential.nim @@ -106,6 +106,10 @@ template yieldScalar(content: string, typeHint: YamlTypeHint, when defined(yamlDebug): echo "Parser token [mode=", level.mode, ", state=", state, "]: ", "scalar[\"", content, "\", type=", typeHint, "]" + if objectTag.len > 0: + if tag.len > 0: + yieldError("Duplicate tag for scalar") + tag = objectTag yield YamlStreamEvent(kind: yamlScalar, scalarAnchor: resolveAnchor(parser, anchor), scalarTag: resolveTag(parser, tag, quoted), @@ -227,7 +231,7 @@ template handleBlockIndicator(expected, possible: openarray[DocumentLevelMode], cachedAnchor = anchor cachedTag = tag anchor = "" - tag = "" + tag = objectTag yieldStart(entering) anchor = cachedAnchor tag = cachedTag @@ -286,6 +290,7 @@ proc parse*(parser: YamlSequentialParser, s: Stream): YamlStream = # cached values tag: string = "" + objectTag: string = "" anchor: string = "" scalarCache: string = nil scalarCacheType: YamlTypeHint @@ -363,6 +368,8 @@ proc parse*(parser: YamlSequentialParser, s: Stream): YamlStream = case token of tTagHandle: handleTagHandle() + objectTag = tag + tag = "" state = ypBlockLineEnd of tComment: state = ypBlockLineEnd @@ -373,7 +380,11 @@ proc parse*(parser: YamlSequentialParser, s: Stream): YamlStream = of ypBlockLineStart: case token of tLineStart: - discard + if objectTag.len > 0: + yieldError("Duplicate tag for object") + else: + objectTag = tag + tag = "" of tDash: handleBlockIndicator([mBlockSequenceItem], [], mBlockSequenceItem, yamlStartSequence) @@ -499,21 +510,20 @@ proc parse*(parser: YamlSequentialParser, s: Stream): YamlStream = closeAllLevels() state = ypAfterDirectivesEnd continue - of tAlias: + else: leaveMoreIndentedLevels() + if level.mode == mScalar: + yieldUnexpectedToken() state = ypBlockLineStart continue - else: - yieldUnexpectedToken() of ypBlockAfterScalar: case token of tColon: assert level.mode in [mUnknown, mImplicitBlockMapKey, mScalar] if level.mode in [mUnknown, mScalar]: - # tags and anchors are for key scalar, not for map. yield YamlStreamEvent(kind: yamlStartMap, mapAnchor: anchorNone, - mapTag: tagQuestionMark) + mapTag: parser.resolveTag(objectTag)) level.mode = mBlockMapValue ancestry.add(level) level = DocumentLevel(mode: mUnknown, indicatorColumn: -1, @@ -584,11 +594,9 @@ proc parse*(parser: YamlSequentialParser, s: Stream): YamlStream = of tAnchor: anchor = lex.content state = ypBlockAfterAnchorAndTag - of tScalar, tColon, tStreamEnd: + of tScalar, tColon, tStreamEnd, tScalarPart: state = ypBlockLineStart continue - of tScalarPart: - startPlainScalar() of tLineStart: state = ypBlockLineStart of tOpeningBracket, tOpeningBrace: @@ -602,11 +610,9 @@ proc parse*(parser: YamlSequentialParser, s: Stream): YamlStream = state = ypBlockLineStart continue case token - of tScalar, tColon, tStreamEnd: + of tScalar, tColon, tStreamEnd, tScalarPart: state = ypBlockLineStart continue - of tScalarPart: - startPlainScalar() of tLineStart: discard of tOpeningBracket, tOpeningBrace: @@ -627,11 +633,9 @@ proc parse*(parser: YamlSequentialParser, s: Stream): YamlStream = state = ypBlockLineStart continue case token - of tScalar, tColon, tStreamEnd: + of tScalar, tColon, tStreamEnd, tScalarPart: state = ypBlockLineStart continue - of tScalarPart: - startPlainScalar() of tLineStart: discard of tOpeningBracket, tOpeningBrace: diff --git a/test/parsing.nim b/test/parsing.nim index 8c1064a..49fda03 100644 --- a/test/parsing.nim +++ b/test/parsing.nim @@ -50,8 +50,8 @@ proc printDifference(expected, actual: YamlStreamEvent) = if expected.kind != actual.kind: echo "expected " & $expected.kind & ", got " & $actual.kind if actual.kind == yamlError: - echo "Error message: (", actual.line, ", ", actual.column, ") ", - actual.description + echo "Error message: (line: ", actual.line, ", column: ", + actual.column, ") ", actual.description elif actual.kind == yamlWarning: echo "Warning message: " & actual.description else: @@ -238,6 +238,12 @@ suite "Parsing": ensure("? !!str a\n: !!int b\n? c\n: !!str d", startDoc(), startMap(), scalar("a", tagString), scalar("b", tagInteger), scalar("c"), scalar("d", tagString), endMap(), endDoc()) + test "Parsing: tags for block objects": + ensure("--- !!map\nfoo: !!seq\n - a\n - !!str b\n!!str bar: !!str baz", + startDoc(), startMap(tagMap), scalar("foo"), + startSequence(tagSequence), scalar("a"), scalar("b", tagString), + endSequence(), scalar("bar", tagString), + scalar("baz", tagString), endMap(), endDoc()) test "Parsing: tags for flow objects": ensure("!!map { k: !!seq [ a, !!str b] }", startDoc(), startMap(tagMap), scalar("k"), startSequence(tagSequence), scalar("a"),