Improved mixing block and flow content

This commit is contained in:
Felix Krause 2015-12-10 23:02:06 +01:00
parent ed7176131e
commit 01416f61be
2 changed files with 46 additions and 20 deletions

View File

@ -39,7 +39,7 @@ type
DocumentLevel = object DocumentLevel = object
kind: LevelKind kind: LevelKind
indicatorColumn: int indicatorColumn: int
readKey: bool readKey, implicit: bool
anchor: string anchor: string
tag: string tag: string
@ -225,6 +225,7 @@ iterator events*(input: Stream): YamlParserEvent {.closure.} =
var level = addr(levels[levels.high]) var level = addr(levels[levels.high])
if level.kind == lUnknown: if level.kind == lUnknown:
level.kind = lMap level.kind = lMap
level.implicit = (token.kind == yamlColon)
level.indicatorColumn = lex.column level.indicatorColumn = lex.column
levels.add(DocumentLevel(kind: lUnknown, levels.add(DocumentLevel(kind: lUnknown,
indicatorColumn: -1, indicatorColumn: -1,
@ -238,18 +239,19 @@ iterator events*(input: Stream): YamlParserEvent {.closure.} =
scalarAnchor: level.anchor, scalarAnchor: level.anchor,
scalarTag: level.tag, scalarTag: level.tag,
scalarContent: "") scalarContent: "")
level.readKey = false level.readKey = true
elif level.indicatorColumn < lex.column: elif level.indicatorColumn < lex.column:
yieldError("Invalid indentation for '?'") yieldError("Invalid indentation for '?'")
elif level.kind == lMap and level.readKey == elif level.kind == lMap and level.readKey ==
(token.kind == yamlColon): (token.kind == yamlQuestionmark) and not level.implicit:
level.readKey = true level.readKey = token.kind == yamlColon
levels.add(DocumentLevel(kind: lUnknown, levels.add(DocumentLevel(kind: lUnknown,
indicatorColumn: -1, indicatorColumn: -1,
readKey: (token.kind == yamlQuestionmark), readKey: (token.kind == yamlQuestionmark),
anchor: nil, tag: nil)) anchor: nil, tag: nil))
else: else:
yieldError("Unexpected token: '?'") echo "implicit: ", level.implicit, ", readKey: ", level.readKey
yieldError("Unexpected token: " & $token.kind)
of yamlTagHandle: of yamlTagHandle:
var level = addr(levels[levels.high]) var level = addr(levels[levels.high])
let handle = lex.content let handle = lex.content
@ -268,15 +270,25 @@ iterator events*(input: Stream): YamlParserEvent {.closure.} =
levels[levels.high].tag = lex.content levels[levels.high].tag = lex.content
of lexer.yamlScalar: of lexer.yamlScalar:
closeLevelsByIndicator() closeLevelsByIndicator()
let level = levels.pop() let level = addr(levels[levels.high])
if level.kind != lUnknown: case level.kind
yieldError("Unexpected scalar in " & $level.kind) of lSequence:
else: yieldError("Unexpected scalar in sequence")
of lUnknown:
cachedScalar = YamlParserEvent(kind: yamlScalar, cachedScalar = YamlParserEvent(kind: yamlScalar,
scalarAnchor: level.anchor, scalarAnchor: level.anchor,
scalarTag: level.tag, scalarTag: level.tag,
scalarContent: lex.content) scalarContent: lex.content)
cachedScalarIndentation = lex.column cachedScalarIndentation = lex.column
discard levels.pop()
of lMap:
if level.implicit:
yield YamlParserEvent(kind: yamlScalar,
scalarAnchor: level.anchor,
scalarTag: level.tag,
scalarContent: lex.content)
else:
yieldError("Unexpected implicit key in map")
state = ylBlockAfterScalar state = ylBlockAfterScalar
of yamlStreamEnd: of yamlStreamEnd:
closeAllLevels() closeAllLevels()
@ -300,17 +312,26 @@ iterator events*(input: Stream): YamlParserEvent {.closure.} =
var level: ptr DocumentLevel = nil var level: ptr DocumentLevel = nil
if levels.len > 0: if levels.len > 0:
level = addr(levels[levels.high]) level = addr(levels[levels.high])
if level == nil or level.kind != lUnknown: if level == nil or level.kind == lSequence:
levels.add(DocumentLevel(kind: lUnknown)) levels.add(DocumentLevel(kind: lUnknown))
level = addr(levels[levels.high]) level = addr(levels[levels.high])
level.kind = lMap case level.kind
level.indicatorColumn = cachedScalarIndentation of lUnknown:
level.readKey = true level.kind = lMap
yield YamlParserEvent(kind: yamlStartMap) level.implicit = true
yield cachedScalar level.indicatorColumn = cachedScalarIndentation
levels.add(DocumentLevel(kind: lUnknown, level.readKey = true
indicatorColumn: -1)) yield YamlParserEvent(kind: yamlStartMap)
cachedScalar = nil yield cachedScalar
levels.add(DocumentLevel(kind: lUnknown,
indicatorColumn: -1))
cachedScalar = nil
of lMap:
level.readKey = true
levels.add(DocumentLevel(kind: lUnknown,
indicatorColumn: -1))
of lSequence:
discard # never happens
state = ylBlockAfterColon state = ylBlockAfterColon
of yamlLineStart: of yamlLineStart:
yield cachedScalar yield cachedScalar

View File

@ -87,8 +87,13 @@ suite "Parsing":
ensure("- item", startDoc(), startSequence(), scalar("item"), ensure("- item", startDoc(), startSequence(), scalar("item"),
endSequence(), endDoc()) endSequence(), endDoc())
test "Parsing: Simple Map": test "Parsing: Simple Map":
ensure("key: value", startDoc(), startMap(), scalar("key"), ensure("key: value\nkey2: value2", startDoc(), startMap(),
scalar("value"), endMap(), endDoc()) scalar("key"), scalar("value"), scalar("key2"), scalar("value2"),
endMap(), endDoc())
test "Parsing: Explicit Map":
ensure("? key\n: value\n? key2\n: value2", startDoc(), startMap(),
scalar("key"), scalar("value"), scalar("key2"), scalar("value2"),
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(),