Got tags working

This commit is contained in:
Felix Krause 2015-12-21 23:10:42 +01:00
parent 32f36515e7
commit f320449a2d
3 changed files with 106 additions and 11 deletions

View File

@ -514,6 +514,11 @@ iterator tokens*(my: var YamlLexer): YamlLexerToken {.closure.} =
yieldToken(yamlDash) yieldToken(yamlDash)
of ',': of ',':
yieldToken(yamlComma) yieldToken(yamlComma)
of '!':
my.content = "!"
yieldToken(yamlTagHandle)
my.content = ""
yieldToken(yamlTagSuffix)
else: else:
yieldError("Unexpected special char: \"" & yieldError("Unexpected special char: \"" &
lastSpecialChar & "\"") lastSpecialChar & "\"")

View File

@ -33,6 +33,7 @@ type
ylBlockAfterAnchor, ylBlockAfterAnchorAndTag, ylBlockAfterScalar, ylBlockAfterAnchor, ylBlockAfterAnchorAndTag, ylBlockAfterScalar,
ylBlockAfterColon, ylBlockMultilineScalar, ylBlockLineEnd, ylBlockAfterColon, ylBlockMultilineScalar, ylBlockLineEnd,
ylBlockScalarHeader, ylBlockScalar, ylFlow, ylFlowAfterObject, ylBlockScalarHeader, ylBlockScalar, ylFlow, ylFlowAfterObject,
ylFlowAfterTag, ylFlowAfterAnchor, ylFlowAfterAnchorAndTag,
ylExpectingDocumentEnd ylExpectingDocumentEnd
DocumentLevelMode = enum DocumentLevelMode = enum
@ -154,6 +155,12 @@ template yieldStart(k: YamlParserEventKind) {.dirty.} =
anchor = nil anchor = nil
tag = nil tag = nil
template yieldDocumentEnd() {.dirty.} =
yield YamlParserEvent(kind: yamlEndDocument)
tagShorthands = initTable[string, string]()
tagShorthands["!"] = "!"
tagShorthands["!!"] = "tag:yaml.org,2002:"
template closeLevel(lvl: DocumentLevel) {.dirty.} = template closeLevel(lvl: DocumentLevel) {.dirty.} =
case lvl.mode case lvl.mode
of mExplicitBlockMapKey, mFlowMapKey: of mExplicitBlockMapKey, mFlowMapKey:
@ -239,7 +246,6 @@ template handleTagHandle() {.dirty.} =
yieldError("Missing tag suffix") yieldError("Missing tag suffix")
continue continue
tag = tagShorthands[handle] & lex.content tag = tagShorthands[handle] & lex.content
level.indentationColumn = lex.column
else: else:
yieldError("Unknown tag shorthand: " & handle) yieldError("Unknown tag shorthand: " & handle)
@ -273,6 +279,8 @@ iterator events*(parser: var YamlSequentialParser,
scalarCacheIsQuoted: bool = false scalarCacheIsQuoted: bool = false
lex.open(input) lex.open(input)
tagShorthands["!"] = "!"
tagShorthands["!!"] = "tag:yaml.org,2002:"
var nextToken = tokens var nextToken = tokens
var token = nextToken(lex) var token = nextToken(lex)
@ -326,7 +334,7 @@ iterator events*(parser: var YamlSequentialParser,
state = ylBlockLineStart state = ylBlockLineStart
of yamlDocumentEnd, yamlStreamEnd: of yamlDocumentEnd, yamlStreamEnd:
yield YamlParserEvent(kind: yamlStartDocument) yield YamlParserEvent(kind: yamlStartDocument)
yield YamlParserEvent(kind: yamlEndDocument) yieldDocumentEnd()
else: else:
yield YamlParserEvent(kind: yamlStartDocument) yield YamlParserEvent(kind: yamlStartDocument)
state = ylBlockLineStart state = ylBlockLineStart
@ -358,6 +366,7 @@ iterator events*(parser: var YamlSequentialParser,
level.mode = mScalar level.mode = mScalar
of yamlTagHandle: of yamlTagHandle:
handleTagHandle() handleTagHandle()
level.indentationColumn = lex.column
state = ylBlockAfterTag state = ylBlockAfterTag
of yamlVerbatimTag: of yamlVerbatimTag:
tag = lex.content tag = lex.content
@ -404,7 +413,7 @@ iterator events*(parser: var YamlSequentialParser,
break break
of yamlDocumentEnd: of yamlDocumentEnd:
closeAllLevels() closeAllLevels()
yield YamlParserEvent(kind: yamlEndDocument) yieldDocumentEnd()
state = ylInitial state = ylInitial
of yamlOpeningBrace: of yamlOpeningBrace:
state = ylFlow state = ylFlow
@ -559,6 +568,12 @@ iterator events*(parser: var YamlSequentialParser,
state = ylBlockScalarHeader state = ylBlockScalarHeader
scalarCache = "" scalarCache = ""
level.mode = mScalar level.mode = mScalar
of yamlTagHandle:
handleTagHandle()
state = ylBlockAfterTag
of yamlAnchor:
anchor = lex.content
state = ylBlockAfterAnchor
else: else:
yieldError("Unexpected token (expected scalar or line end): " & yieldError("Unexpected token (expected scalar or line end): " &
$token) $token)
@ -733,8 +748,43 @@ iterator events*(parser: var YamlSequentialParser,
state = ylBlockLineEnd state = ylBlockLineEnd
else: else:
state = ylExpectingDocumentEnd state = ylExpectingDocumentEnd
of yamlTagHandle:
handleTagHandle()
state = ylFlowAfterTag
of yamlAnchor:
anchor = lex.content
state = ylFlowAfterAnchor
else: else:
yieldError("Unexpected token: " & $token) yieldError("Unexpected token: " & $token)
of ylFlowAfterTag:
case token
of yamlTagHandle:
yieldError("Multiple tags on same node!")
of yamlAnchor:
anchor = lex.content
state = ylFlowAfterAnchorAndTag
else:
state = ylFlow
continue
of ylFlowAfterAnchor:
case token
of yamlAnchor:
yieldError("Multiple anchors on same node!")
of yamlTagHandle:
handleTagHandle()
state = ylFlowAfterAnchorAndTag
else:
state = ylFlow
continue
of ylFlowAfterAnchorAndTag:
case token
of yamlAnchor:
yieldError("Multiple anchors on same node!")
of yamlTagHandle:
yieldError("Multiple tags on same node!")
else:
state = ylFlow
continue
of ylFlowAfterObject: of ylFlowAfterObject:
case token case token
of yamlLineStart: of yamlLineStart:
@ -798,10 +848,10 @@ iterator events*(parser: var YamlSequentialParser,
of yamlComment, yamlLineStart: of yamlComment, yamlLineStart:
discard discard
of yamlStreamEnd, yamlDocumentEnd: of yamlStreamEnd, yamlDocumentEnd:
yield YamlParserEvent(kind: yamlEndDocument) yieldDocumentEnd()
state = ylInitial state = ylInitial
of yamlDirectivesEnd: of yamlDirectivesEnd:
yield YamlParserEvent(kind: yamlEndDocument) yieldDocumentEnd()
state = ylInitial state = ylInitial
continue continue
else: else:

View File

@ -19,7 +19,7 @@ proc scalar(content: string, tag: TagId = tagNonSpecificQmark,
result.scalarTag = tag result.scalarTag = tag
result.scalarContent = content result.scalarContent = content
proc startSequence(anchor: string = nil, tag: TagId = tagNonSpecificQmark): proc startSequence(tag: TagId = tagNonSpecificQmark, anchor: string = nil):
YamlParserEvent = YamlParserEvent =
new(result) new(result)
result.kind = yamlStartSequence result.kind = yamlStartSequence
@ -30,7 +30,7 @@ proc endSequence(): YamlParserEvent =
new(result) new(result)
result.kind = yamlEndSequence result.kind = yamlEndSequence
proc startMap(anchor: string = nil, tag: TagId = tagNonSpecificQmark): proc startMap(tag: TagId = tagNonSpecificQmark, anchor: string = nil):
YamlParserEvent = YamlParserEvent =
new(result) new(result)
result.kind = yamlStartMap result.kind = yamlStartMap
@ -83,9 +83,7 @@ proc printDifference(expected, actual: YamlParserEvent) =
echo "Unknown difference in event kind " & $expected.kind echo "Unknown difference in event kind " & $expected.kind
template ensure(input: string, expected: varargs[YamlParserEvent]) {.dirty.} = template ensure(input: string, expected: varargs[YamlParserEvent]) {.dirty.} =
var var i = 0
i = 0
parser = initParser()
for token in parser.events(newStringStream(input)): for token in parser.events(newStringStream(input)):
if i >= expected.len: if i >= expected.len:
@ -101,6 +99,9 @@ template ensure(input: string, expected: varargs[YamlParserEvent]) {.dirty.} =
i.inc() i.inc()
suite "Parsing": suite "Parsing":
setup:
var parser = initParser()
test "Parsing: Simple Scalar": test "Parsing: Simple Scalar":
ensure("Scalar", startDoc(), scalar("Scalar"), endDoc()) ensure("Scalar", startDoc(), scalar("Scalar"), endDoc())
test "Parsing: Simple Sequence": test "Parsing: Simple Sequence":
@ -168,3 +169,42 @@ suite "Parsing":
scalar("a"), scalar("ab"), endMap(), endDoc()) scalar("a"), scalar("ab"), endMap(), endDoc())
test "Parsing: non-specific tags of quoted strings": test "Parsing: non-specific tags of quoted strings":
ensure("\"a\"", startDoc(), scalar("a", tagNonSpecificEmark), endDoc()) ensure("\"a\"", startDoc(), scalar("a", tagNonSpecificEmark), endDoc())
test "Parsing: explicit non-specific tag":
ensure("! a", startDoc(), scalar("a", tagNonSpecificEmark), endDoc())
test "Parsing: secondary tag handle resolution":
let id = parser.registerUri("tag:yaml.org,2002:str")
ensure("!!str a", startDoc(), scalar("a", id), endDoc())
test "Parsing: resolving custom tag handles":
let id = parser.registerUri("tag:example.com,2015:foo")
ensure("%TAG !t! tag:example.com,2015:\n---\n!t!foo a", startDoc(),
scalar("a", id), endDoc())
test "Parsing: tags in sequence":
let
idStr = parser.registerUri("tag:yaml.org,2002:str")
idInt = parser.registerUri("tag:yaml.org,2002:int")
ensure(" - !!str a\n - b\n - !!int c\n - d", startDoc(),
startSequence(), scalar("a", idStr), scalar("b"),
scalar("c", idInt), scalar("d"), endSequence(), endDoc())
test "Parsing: tags in implicit map":
let
idStr = parser.registerUri("tag:yaml.org,2002:str")
idInt = parser.registerUri("tag:yaml.org,2002:int")
ensure("!!str a: b\nc: !!int d\ne: !!str f\ng: h", startDoc(), startMap(),
scalar("a", idStr), scalar("b"), scalar("c"), scalar("d", idInt),
scalar("e"), scalar("f", idStr), scalar("g"), scalar("h"),
endMap(), endDoc())
test "Parsing: tags in explicit map":
let
idStr = parser.registerUri("tag:yaml.org,2002:str")
idInt = parser.registerUri("tag:yaml.org,2002:int")
ensure("? !!str a\n: !!int b\n? c\n: !!str d", startDoc(), startMap(),
scalar("a", idStr), scalar("b", idInt), scalar("c"),
scalar("d", idStr), endMap(), endDoc())
test "Parsing: tags for flow objects":
let
idStr = parser.registerUri("tag:yaml.org,2002:str")
idMap = parser.registerUri("tag:yaml.org,2002:map")
idSeq = parser.registerUri("tag:yaml.org,2002:seq")
ensure("!!map { k: !!seq [ a, !!str b] }", startDoc(), startMap(idMap),
scalar("k"), startSequence(idSeq), scalar("a"),
scalar("b", idStr), endSequence(), endMap(), endDoc())