Support anchors on empty nodes

This commit is contained in:
Felix Krause 2015-12-22 23:35:03 +01:00
parent 545bff673a
commit a9a1a67bc6
2 changed files with 54 additions and 5 deletions

View File

@ -207,6 +207,15 @@ template closeLevel(lvl: DocumentLevel) {.dirty.} =
else:
yieldScalar()
proc mustLeaveLevel(curCol: int, ancestry: seq[DocumentLevel]): bool =
if ancestry.len == 0:
result = false
else:
let parent = ancestry[ancestry.high]
result = parent.indicatorColumn >= curCol or
(parent.indicatorColumn == -1 and
parent.indentationColumn >= curCol)
template leaveMoreIndentedLevels() {.dirty.} =
while ancestry.len > 0:
let parent = ancestry[ancestry.high]
@ -258,9 +267,19 @@ template handleBlockIndicator(expected, possible: openarray[DocumentLevelMode],
else:
level.mode = next
level.indicatorColumn = lex.column
yieldStart(entering)
if emptyScalarOnOpening:
# do not consume anchor and tag; they are on the scalar
var
cachedAnchor = anchor
cachedTag = tag
anchor = ""
tag = ""
yieldStart(entering)
anchor = cachedAnchor
tag = cachedTag
yieldScalar("")
else:
yieldStart(entering)
ancestry.add(level)
level = DocumentLevel(mode: mUnknown, indicatorColumn: -1,
indentationColumn: -1)
@ -281,6 +300,8 @@ template handleTagHandle() {.dirty.} =
yieldError("Missing tag suffix")
continue
tag = tagShorthands[handle] & lex.content
if level.indentationColumn == -1 and level.indicatorColumn == -1:
level.indentationColumn = lex.column
else:
yieldError("Unknown tag shorthand: " & handle)
@ -414,6 +435,7 @@ iterator events*(parser: var YamlSequentialParser,
scalarCache = ""
level.mode = mScalar
of yamlTagHandle:
leaveMoreIndentedLevels()
handleTagHandle()
level.indentationColumn = lex.column
state = ylBlockAfterTag
@ -422,6 +444,7 @@ iterator events*(parser: var YamlSequentialParser,
state = ylBlockAfterTag
level.indentationColumn = lex.column
of yamlAnchor:
leaveMoreIndentedLevels()
anchor = lex.content
level.indentationColumn = lex.column
state = ylBlockAfterAnchor
@ -591,11 +614,15 @@ iterator events*(parser: var YamlSequentialParser,
else:
yieldUnexpectedToken()
of ylBlockAfterTag:
if mustLeaveLevel(lex.column, ancestry):
leaveMoreIndentedLevels()
state = ylBlockLineStart
continue
case token
of yamlAnchor:
anchor = lex.content
state = ylBlockAfterAnchorAndTag
of lexer.yamlScalar:
of lexer.yamlScalar, yamlColon, yamlStreamEnd:
state = ylBlockLineStart
continue
of yamlScalarPart:
@ -608,8 +635,12 @@ iterator events*(parser: var YamlSequentialParser,
else:
yieldUnexpectedToken()
of ylBlockAfterAnchor:
if mustLeaveLevel(lex.column, ancestry):
leaveMoreIndentedLevels()
state = ylBlockLineStart
continue
case token
of lexer.yamlScalar:
of lexer.yamlScalar, yamlColon, yamlStreamEnd:
state = ylBlockLineStart
continue
of lexer.yamlScalarPart:
@ -629,8 +660,12 @@ iterator events*(parser: var YamlSequentialParser,
else:
yieldUnexpectedToken()
of ylBlockAfterAnchorAndTag:
if mustLeaveLevel(lex.column, ancestry):
leaveMoreIndentedLevels()
state = ylBlockLineStart
continue
case token
of lexer.yamlScalar:
of lexer.yamlScalar, yamlColon, yamlStreamEnd:
state = ylBlockLineStart
continue
of yamlScalarPart:
@ -672,6 +707,7 @@ iterator events*(parser: var YamlSequentialParser,
handleTagHandle()
state = ylBlockAfterTag
of yamlAnchor:
level.indentationColumn = lex.column
anchor = lex.content
state = ylBlockAfterAnchor
of lexer.yamlAlias:

View File

@ -285,3 +285,16 @@ suite "Parsing":
alias(1.AnchorId), alias(0.AnchorId), startSequence(),
scalar("c"), alias(1.AnchorId), scalar("d"), endSequence(),
endMap(), endDoc())
test "Parsing: tags on empty scalars":
let
idStr = parser.registerUri("tag:yaml.org,2002:str")
idInt = parser.registerUri("tag:yaml.org,2002:int")
ensure("!!str : a\nb: !!int\n!!str : !!str", startDoc(), startMap(),
scalar("", idStr), scalar("a"), scalar("b"), scalar("", idInt),
scalar("", idStr), scalar("", idStr), endMap(), endDoc())
test "Parsing: anchors on empty scalars":
ensure("&a : a\nb: &b\n&c : &a", startDoc(), startMap(),
scalar("", tagQuestionMark, 0.AnchorId), scalar("a"),
scalar("b"), scalar("", tagQuestionMark, 1.AnchorId),
scalar("", tagQuestionMark, 2.AnchorId),
scalar("", tagQuestionMark, 0.AnchorId), endMap(), endDoc())