Various code style and naming fixes

* Renamed some symbols for consistency, fixes #6:
   - yamlStartSequence -> yamlStartSeq
   - yamlEndSequence   -> yamlEndSeq
   - yamlStartDocument -> yamlStartDoc
   - yamlEndDocument   -> yamlEndDoc
   - yTagMap           -> yTagMapping
 * Improved code formatting at some places
 * Fixed code documentation at some places
 * Added generic objects to TODO list
 * Removed obsolete parsing tests, these are superseeded
   by yaml-dev-kit test suite integration
This commit is contained in:
Felix Krause 2016-03-14 18:10:34 +01:00
parent 2e8d7b39ab
commit 16d1a1bceb
13 changed files with 89 additions and 353 deletions

View File

@ -12,6 +12,7 @@ an overview of already available features.
- Support for more standard library types
- Support polymorphism
- Support variant objects
- Support generic objects
- Support transient fields (i.e. fields that will not be (de-)serialized on
objects and tuples)
- Check for and avoid name clashes when generating local tags for custom
@ -20,8 +21,8 @@ an overview of already available features.
## Developers
```bash
nim tests # runs all tests
nim parserTests # runs parser tests
nim tests # runs unit tests (serialization, dom, json)
# for parser tests, see yamlTestSuite
nim serializationTests # runs serialization tests
nim documentation # builds documentation to folder docout
nim server # builds the REST server used for the testing ground

View File

@ -13,11 +13,6 @@ task yamlTestSuite, "Run YAML 1.2 test suite":
--verbosity:0
setCommand "c", "test/yamlTestSuite"
task parserTests, "Run parser tests":
--r
--verbosity:0
setCommand "c", "test/parsing"
task serializationTests, "Run serialization tests":
--r
--verbosity:0

View File

@ -47,11 +47,11 @@ proc composeNode(s: var YamlStream, tagLib: TagLibrary,
if start.mapAnchor != yAnchorNone:
assert(not c.refs.hasKey(start.mapAnchor))
c.refs[start.mapAnchor] = cast[pointer](result)
of yamlStartSequence:
of yamlStartSeq:
result.tag = tagLib.uri(start.seqTag)
result.kind = ySequence
result.children = newSeq[YamlNode]()
while s.peek().kind != yamlEndSequence:
while s.peek().kind != yamlEndSeq:
result.children.add(composeNode(s, tagLib, c))
if start.seqAnchor != yAnchorNone:
assert(not c.refs.hasKey(start.seqAnchor))
@ -74,9 +74,9 @@ proc composeNode(s: var YamlStream, tagLib: TagLibrary,
proc compose*(s: var YamlStream, tagLib: TagLibrary): YamlDocument
{.raises: [YamlStreamError, YamlConstructionError].} =
var context = newConstructionContext()
assert s.next().kind == yamlStartDocument
assert s.next().kind == yamlStartDoc, "Malformed YamlStream"
result.root = composeNode(s, tagLib, context)
assert s.next().kind == yamlEndDocument
assert s.next().kind == yamlEndDoc, "Malformed YamlStream"
proc loadDOM*(s: Stream): YamlDocument
{.raises: [IOError, YamlParserError, YamlConstructionError].} =
@ -126,8 +126,7 @@ proc serializeNode(n: YamlNode, c: SerializationContext, a: AnchorStyle,
except KeyError: assert false, "Can never happen"
result = iterator(): YamlStreamEvent =
case n.kind
of yScalar:
yield scalarEvent(n.content, tagId, anchor)
of yScalar: yield scalarEvent(n.content, tagId, anchor)
of ySequence:
yield startSeqEvent(tagId, anchor)
for item in n.children:
@ -155,8 +154,7 @@ proc serializeNode(n: YamlNode, c: SerializationContext, a: AnchorStyle,
template processAnchoredEvent(target: expr, c: SerializationContext): stmt =
try:
let anchorId = c.refs[cast[pointer](target)]
if anchorId != yAnchorNone:
target = anchorId
if anchorId != yAnchorNone: target = anchorId
else: target = yAnchorNone
except KeyError: assert false, "Can never happen"
yield event
@ -179,7 +177,7 @@ proc serialize*(doc: YamlDocument, tagLib: TagLibrary, a: AnchorStyle = asTidy):
of yamlScalar:
processAnchoredEvent(event.scalarAnchor, context)
of yamlStartMap: processAnchoredEvent(event.mapAnchor, context)
of yamlStartSequence:
of yamlStartSeq:
processAnchoredEvent(event.seqAnchor, context)
else: yield event
yield endDocEvent()

View File

@ -8,12 +8,12 @@ proc `==`*(left: YamlStreamEvent, right: YamlStreamEvent): bool =
if left.kind != right.kind:
return false
case left.kind
of yamlStartDocument, yamlEndDocument, yamlEndMap, yamlEndSequence:
of yamlStartDoc, yamlEndDoc, yamlEndMap, yamlEndSeq:
result = true
of yamlStartMap:
result = left.mapAnchor == right.mapAnchor and
left.mapTag == right.mapTag
of yamlStartSequence:
of yamlStartSeq:
result = left.seqAnchor == right.seqAnchor and
left.seqTag == right.seqTag
of yamlScalar:
@ -26,13 +26,13 @@ proc `==`*(left: YamlStreamEvent, right: YamlStreamEvent): bool =
proc `$`*(event: YamlStreamEvent): string =
result = $event.kind & '('
case event.kind
of yamlEndMap, yamlEndSequence, yamlStartDocument, yamlEndDocument:
of yamlEndMap, yamlEndSeq, yamlStartDoc, yamlEndDoc:
discard
of yamlStartMap:
result &= "tag=" & $event.mapTag
if event.mapAnchor != yAnchorNone:
result &= ", anchor=" & $event.mapAnchor
of yamlStartSequence:
of yamlStartSeq:
result &= "tag=" & $event.seqTag
if event.seqAnchor != yAnchorNone:
result &= ", anchor=" & $event.seqAnchor
@ -46,10 +46,10 @@ proc `$`*(event: YamlStreamEvent): string =
result &= ")"
proc startDocEvent*(): YamlStreamEvent =
result = YamlStreamEvent(kind: yamlStartDocument)
result = YamlStreamEvent(kind: yamlStartDoc)
proc endDocEvent*(): YamlStreamEvent =
result = YamlStreamEvent(kind: yamlEndDocument)
result = YamlStreamEvent(kind: yamlEndDoc)
proc startMapEvent*(tag: TagId = yTagQuestionMark,
anchor: AnchorId = yAnchorNone): YamlStreamEvent =
@ -60,11 +60,11 @@ proc endMapEvent*(): YamlStreamEvent =
proc startSeqEvent*(tag: TagId = yTagQuestionMark,
anchor: AnchorId = yAnchorNone): YamlStreamEvent =
result = YamlStreamEvent(kind: yamlStartSequence, seqTag: tag,
result = YamlStreamEvent(kind: yamlStartSeq, seqTag: tag,
seqAnchor: anchor)
proc endSeqEvent*(): YamlStreamEvent =
result = YamlStreamEvent(kind: yamlEndSequence)
result = YamlStreamEvent(kind: yamlEndSeq)
proc scalarEvent*(content: string = "", tag: TagId = yTagQuestionMark,
anchor: AnchorId = yAnchorNone): YamlStreamEvent =

View File

@ -169,7 +169,7 @@ template handleBlockSequenceIndicator() {.dirty.} =
startToken()
case level.kind
of fplUnknown:
handleObjectStart(yamlStartSequence)
handleObjectStart(yamlStartSeq)
of fplSequence:
if level.indentation != indentation:
parserError("Invalid indentation of block sequence indicator")
@ -1443,7 +1443,7 @@ proc parse*(p: YamlParser, s: Stream): YamlStream =
p.lexer.bufpos.inc()
explicitFlowKey = false
of '[':
handleObjectStart(yamlStartSequence)
handleObjectStart(yamlStartSeq)
flowdepth.inc()
p.lexer.bufpos.inc()
of '}':

View File

@ -86,14 +86,14 @@ proc constructJson*(s: var YamlStream): seq[JsonNode] =
anchors = initTable[AnchorId, JsonNode]()
for event in s:
case event.kind
of yamlStartDocument:
of yamlStartDoc:
# we don't need to do anything here; root node will be created
# by first scalar, sequence or map event
discard
of yamlEndDocument:
of yamlEndDoc:
# we can savely assume that levels has e length of exactly 1.
result.add(levels.pop().node)
of yamlStartSequence:
of yamlStartSeq:
levels.add(initLevel(newJArray()))
if event.seqAnchor != yAnchorNone:
anchors[event.seqAnchor] = levels[levels.high].node
@ -130,9 +130,8 @@ proc constructJson*(s: var YamlStream): seq[JsonNode] =
levels[levels.high].key = nil
if event.scalarAnchor != yAnchorNone:
anchors[event.scalarAnchor] = jsonScalar
else:
discard # will never happen
of yamlEndSequence, yamlEndMap:
else: discard # will never happen
of yamlEndSeq, yamlEndMap:
if levels.len > 1:
let level = levels.pop()
case levels[levels.high].node.kind
@ -146,10 +145,8 @@ proc constructJson*(s: var YamlStream): seq[JsonNode] =
levels[levels.high].node[
levels[levels.high].key] = level.node
levels[levels.high].key = nil
else:
discard # will never happen
else:
discard # wait for yamlEndDocument
else: discard # will never happen
else: discard # wait for yamlEndDocument
of yamlAlias:
# we can savely assume that the alias exists in anchors
# (else the parser would have already thrown an exception)
@ -176,8 +173,7 @@ proc constructJson*(s: var YamlStream): seq[JsonNode] =
# have resulted in a parser error earlier.
assert(false)
levels[levels.high].key = nil
else:
discard # will never happen
else: discard # will never happen
proc loadToJson*(s: Stream): seq[JsonNode] =
var

View File

@ -345,7 +345,7 @@ proc present*(s: var YamlStream, target: Stream, tagLib: TagLibrary,
while cached.len > 0 or not s.finished():
let item = if cached.len > 0: cached.dequeue else: s.next()
case item.kind
of yamlStartDocument:
of yamlStartDoc:
if options.style != psJson:
# TODO: tag directives
try:
@ -390,8 +390,7 @@ proc present*(s: var YamlStream, target: Stream, tagLib: TagLibrary,
elif item.scalarTag in [yTagQuestionMark, yTagFloat] and
hint == yTypeFloat:
safeWrite(item.scalarContent)
else:
writeDoubleQuotedJson(item.scalarContent, target)
else: writeDoubleQuotedJson(item.scalarContent, target)
elif options.style == psCanonical:
writeDoubleQuoted(item.scalarContent, target,
indentation + options.indentationStep,
@ -421,7 +420,7 @@ proc present*(s: var YamlStream, target: Stream, tagLib: TagLibrary,
var e = newException(YamlPresenterOutputError, "")
e.parent = getCurrentException()
raise e
of yamlStartSequence:
of yamlStartSeq:
var nextState: DumperState
case options.style
of psDefault:
@ -431,12 +430,9 @@ proc present*(s: var YamlStream, target: Stream, tagLib: TagLibrary,
let next = s.next()
cached.enqueue(next)
case next.kind
of yamlScalar:
length += 2 + next.scalarContent.len
of yamlAlias:
length += 6
of yamlEndSequence:
break
of yamlScalar: length += 2 + next.scalarContent.len
of yamlAlias: length += 6
of yamlEndSeq: break
else:
length = high(int)
break
@ -472,8 +468,7 @@ proc present*(s: var YamlStream, target: Stream, tagLib: TagLibrary,
item.seqTag, tagLib, item.seqAnchor)
indentation += options.indentationStep
if nextState == dFlowSequenceStart:
safeWrite('[')
if nextState == dFlowSequenceStart: safeWrite('[')
if levels.len > 0 and options.style in [psJson, psCanonical] and
levels[levels.high] in
[dBlockExplicitMapKey, dBlockMapValue,
@ -500,18 +495,15 @@ proc present*(s: var YamlStream, target: Stream, tagLib: TagLibrary,
mps = mpNeedBlock
nextState = if mps == mpNeedBlock: dBlockMapValue else:
dBlockInlineMap
of psMinimal:
nextState = dFlowMapStart
of psCanonical:
nextState = dFlowMapStart
of psMinimal: nextState = dFlowMapStart
of psCanonical: nextState = dFlowMapStart
of psJson:
if levels.len > 0 and levels[levels.high] in
[dFlowMapStart, dFlowMapValue]:
raise newException(YamlPresenterJsonError,
"Cannot have map as map key in JSON output!")
nextState = dFlowMapStart
of psBlockOnly:
nextState = dBlockMapValue
of psBlockOnly: nextState = dBlockMapValue
if levels.len == 0:
if nextState == dBlockMapValue:
if options.style != psJson:
@ -538,8 +530,7 @@ proc present*(s: var YamlStream, target: Stream, tagLib: TagLibrary,
item.mapTag, tagLib, item.mapAnchor)
indentation += options.indentationStep
if nextState == dFlowMapStart:
safeWrite('{')
if nextState == dFlowMapStart: safeWrite('{')
if levels.len > 0 and options.style in [psJson, psCanonical] and
levels[levels.high] in
[dBlockExplicitMapKey, dBlockMapValue,
@ -547,13 +538,12 @@ proc present*(s: var YamlStream, target: Stream, tagLib: TagLibrary,
indentation += options.indentationStep
levels.add(nextState)
of yamlEndSequence:
of yamlEndSeq:
assert levels.len > 0
case levels.pop()
of dFlowSequenceItem:
case options.style
of psDefault, psMinimal, psBlockOnly:
safeWrite(']')
of psDefault, psMinimal, psBlockOnly: safeWrite(']')
of psJson, psCanonical:
indentation -= options.indentationStep
try:
@ -575,10 +565,8 @@ proc present*(s: var YamlStream, target: Stream, tagLib: TagLibrary,
dBlockImplicitMapKey, dBlockSequenceItem]:
indentation -= options.indentationStep
safeWrite(']')
of dBlockSequenceItem:
discard
else:
assert false
of dBlockSequenceItem: discard
else: assert false
indentation -= options.indentationStep
of yamlEndMap:
assert levels.len > 0
@ -586,8 +574,7 @@ proc present*(s: var YamlStream, target: Stream, tagLib: TagLibrary,
case level
of dFlowMapValue:
case options.style
of psDefault, psMinimal, psBlockOnly:
safeWrite('}')
of psDefault, psMinimal, psBlockOnly: safeWrite('}')
of psJson, psCanonical:
indentation -= options.indentationStep
try:
@ -609,12 +596,10 @@ proc present*(s: var YamlStream, target: Stream, tagLib: TagLibrary,
dBlockImplicitMapKey, dBlockSequenceItem]:
indentation -= options.indentationStep
safeWrite('}')
of dBlockMapValue, dBlockInlineMap:
discard
else:
assert false
of dBlockMapValue, dBlockInlineMap: discard
else: assert false
indentation -= options.indentationStep
of yamlEndDocument:
of yamlEndDoc:
if finished(s): break
safeWrite("..." & newline)
@ -630,14 +615,14 @@ proc transform*(input: Stream, output: Stream,
for e in events:
var event = e
case event.kind
of yamlStartDocument, yamlEndDocument, yamlEndMap,
yamlAlias, yamlEndSequence:
of yamlStartDoc, yamlEndDoc, yamlEndMap, yamlAlias,
yamlEndSeq:
discard
of yamlStartMap:
if event.mapTag in [yTagQuestionMark,
yTagExclamationMark]:
event.mapTag = yTagMap
of yamlStartSequence:
event.mapTag = yTagMapping
of yamlStartSeq:
if event.seqTag in [yTagQuestionMark,
yTagExclamationMark]:
event.seqTag = yTagSequence

View File

@ -285,10 +285,10 @@ proc constructObject*[T](s: var YamlStream, c: ConstructionContext,
{.raises: [YamlConstructionError, YamlStreamError].} =
## constructs a Nim seq from a YAML sequence
let event = s.next()
if event.kind != yamlStartSequence:
if event.kind != yamlStartSeq:
raise newException(YamlConstructionError, "Expected sequence start")
result = newSeq[T]()
while s.peek().kind != yamlEndSequence:
while s.peek().kind != yamlEndSeq:
var item: T
constructChild(s, c, item)
result.add(item)
@ -299,7 +299,7 @@ proc representObject*[T](value: seq[T], ts: TagStyle,
## represents a Nim seq as YAML sequence
result = iterator(): YamlStreamEvent =
let childTagStyle = if ts == tsRootOnly: tsNone else: ts
yield YamlStreamEvent(kind: yamlStartSequence,
yield YamlStreamEvent(kind: yamlStartSeq,
seqTag: presentTag(seq[T], ts),
seqAnchor: yAnchorNone)
for item in value:
@ -308,7 +308,7 @@ proc representObject*[T](value: seq[T], ts: TagStyle,
let event = events()
if finished(events): break
yield event
yield YamlStreamEvent(kind: yamlEndSequence)
yield YamlStreamEvent(kind: yamlEndSeq)
proc yamlTag*[K, V](T: typedesc[Table[K, V]]): TagId {.inline, raises: [].} =
try:
@ -456,7 +456,7 @@ proc constructChild*[T](s: var YamlStream, c: ConstructionContext,
typetraits.name(T))
elif item.mapAnchor != yAnchorNone:
raise newException(YamlConstructionError, "Anchor on non-ref type")
of yamlStartSequence:
of yamlStartSeq:
if item.seqTag notin [yTagQuestionMark, yamlTag(T)]:
raise newException(YamlConstructionError, "Wrong tag for " &
typetraits.name(T))
@ -492,7 +492,7 @@ proc constructChild*[O](s: var YamlStream, c: ConstructionContext,
case e.kind
of yamlScalar: removeAnchor(e.scalarAnchor)
of yamlStartMap: removeAnchor(e.mapAnchor)
of yamlStartSequence: removeAnchor(e.seqAnchor)
of yamlStartSeq: removeAnchor(e.seqAnchor)
else: assert(false)
s.peek = e
try:
@ -542,7 +542,7 @@ proc representObject*[O](value: ref O, ts: TagStyle, c: SerializationContext):
of yamlStartMap:
first.mapAnchor = a
if ts == tsNone: first.mapTag = yTagQuestionMark
of yamlStartSequence:
of yamlStartSeq:
first.seqAnchor = a
if ts == tsNone: first.seqTag = yTagQuestionMark
of yamlScalar:
@ -562,11 +562,11 @@ proc construct*[T](s: var YamlStream, target: var T) =
context = newConstructionContext()
try:
var e = s.next()
assert(e.kind == yamlStartDocument)
assert(e.kind == yamlStartDoc)
constructChild(s, context, target)
e = s.next()
assert(e.kind == yamlEndDocument)
assert(e.kind == yamlEndDoc)
except YamlConstructionError:
raise (ref YamlConstructionError)(getCurrentException())
except YamlStreamError:
@ -611,13 +611,13 @@ proc represent*[T](value: T, ts: TagStyle = tsRootOnly,
var
context = newSerializationContext(a)
objStream = iterator(): YamlStreamEvent =
yield YamlStreamEvent(kind: yamlStartDocument)
yield YamlStreamEvent(kind: yamlStartDoc)
var events = representObject(value, ts, context)
while true:
let e = events()
if finished(events): break
yield e
yield YamlStreamEvent(kind: yamlEndDocument)
yield YamlStreamEvent(kind: yamlEndDoc)
if a == asTidy:
var objQueue = newSeq[YamlStreamEvent]()
try:
@ -631,7 +631,7 @@ proc represent*[T](value: T, ts: TagStyle = tsRootOnly,
case event.kind
of yamlStartMap:
event.mapAnchor.setAnchor(context.refs)
of yamlStartSequence:
of yamlStartSeq:
event.seqAnchor.setAnchor(context.refs)
of yamlScalar:
event.scalarAnchor.setAnchor(context.refs)

View File

@ -10,7 +10,7 @@ proc `$`*(id: TagId): string =
of yTagExclamationMark: "!"
of yTagString: "!!str"
of yTagSequence: "!!seq"
of yTagMap: "!!map"
of yTagMapping: "!!map"
of yTagNull: "!!null"
of yTagBoolean: "!!bool"
of yTagInteger: "!!int"
@ -49,7 +49,7 @@ proc initFailsafeTagLibrary(): TagLibrary =
result.tags["?"] = yTagQuestionMark
result.tags["tag:yaml.org,2002:str"] = yTagString
result.tags["tag:yaml.org,2002:seq"] = yTagSequence
result.tags["tag:yaml.org,2002:map"] = yTagMap
result.tags["tag:yaml.org,2002:map"] = yTagMapping
proc initCoreTagLibrary(): TagLibrary =
result = initFailsafeTagLibrary()

View File

@ -33,8 +33,7 @@ proc printDifference*(expected, actual: YamlStreamEvent) =
", got ",
cast[int](actual.scalarContent[i]), ")"
break
else:
echo "[scalarEvent] Unknown difference"
else: echo "[scalarEvent] Unknown difference"
of yamlStartMap:
if expected.mapTag != actual.mapTag:
echo "[map.tag] expected ", expected.mapTag, ", got ",
@ -42,25 +41,21 @@ proc printDifference*(expected, actual: YamlStreamEvent) =
elif expected.mapAnchor != actual.mapAnchor:
echo "[map.anchor] expected ", expected.mapAnchor, ", got ",
actual.mapAnchor
else:
echo "[map.tag] Unknown difference"
of yamlStartSequence:
else: echo "[map.tag] Unknown difference"
of yamlStartSeq:
if expected.seqTag != actual.seqTag:
echo "[seq.tag] expected ", expected.seqTag, ", got ",
actual.seqTag
elif expected.seqAnchor != actual.seqAnchor:
echo "[seq.anchor] expected ", expected.seqAnchor, ", got ",
actual.seqAnchor
else:
echo "[seq] Unknown difference"
else: echo "[seq] Unknown difference"
of yamlAlias:
if expected.aliasTarget != actual.aliasTarget:
echo "[alias] expected ", expected.aliasTarget, ", got ",
actual.aliasTarget
else:
echo "[alias] Unknown difference"
else:
echo "Unknown difference in event kind " & $expected.kind
else: echo "[alias] Unknown difference"
else: echo "Unknown difference in event kind " & $expected.kind
template ensure*(input: var YamlStream,
expected: varargs[YamlStreamEvent]) {.dirty.} =

View File

@ -1,232 +0,0 @@
# NimYAML - YAML implementation in Nim
# (c) Copyright 2015 Felix Krause
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
import "../yaml"
import unittest, common
template ensure(input: string, expected: varargs[YamlStreamEvent]) {.dirty.} =
var
parser = newYamlParser(tagLib)
events = parser.parse(newStringStream(input))
try: ensure(events, expected)
except YamlParserError:
let e = cast[ref YamlParserError](getCurrentException())
echo "Parser error:", getCurrentExceptionMsg()
echo e.lineContent
fail()
suite "Parsing":
setup:
var tagLib = initCoreTagLibrary()
teardown:
discard
test "Parsing: Simple scalarEvent":
ensure("scalarEvent", startDocEvent(), scalarEvent("scalarEvent"), endDocEvent())
test "Parsing: Simple Sequence":
ensure("- off", startDocEvent(), startSeqEvent(),
scalarEvent("off"), endSeqEvent(), endDocEvent())
test "Parsing: Simple Map":
ensure("42: value\nkey2: -7.5", startDocEvent(), startMapEvent(),
scalarEvent("42"), scalarEvent("value"), scalarEvent("key2"),
scalarEvent("-7.5"), endMapEvent(), endDocEvent())
test "Parsing: Explicit Map":
ensure("? null\n: value\n? ON\n: value2", startDocEvent(), startMapEvent(),
scalarEvent("null"), scalarEvent("value"),
scalarEvent("ON"), scalarEvent("value2"),
endMapEvent(), endDocEvent())
test "Parsing: Mixed Map (explicit to implicit)":
ensure("? a\n: 13\n1.5: d", startDocEvent(), startMapEvent(), scalarEvent("a"),
scalarEvent("13"), scalarEvent("1.5"),
scalarEvent("d"), endMapEvent(), endDocEvent())
test "Parsing: Mixed Map (implicit to explicit)":
ensure("a: 4.2\n? 23\n: d", startDocEvent(), startMapEvent(), scalarEvent("a"),
scalarEvent("4.2"), scalarEvent("23"),
scalarEvent("d"), endMapEvent(), endDocEvent())
test "Parsing: Missing values in map":
ensure("? a\n? b\nc:", startDocEvent(), startMapEvent(), scalarEvent("a"), scalarEvent(""),
scalarEvent("b"), scalarEvent(""), scalarEvent("c"), scalarEvent(""), endMapEvent(),
endDocEvent())
test "Parsing: Missing keys in map":
ensure(": a\n: b", startDocEvent(), startMapEvent(), scalarEvent(""), scalarEvent("a"),
scalarEvent(""), scalarEvent("b"), endMapEvent(), endDocEvent())
test "Parsing: Multiline scalarEvents in explicit map":
ensure("? a\n true\n: null\n d\n? e\n 42", startDocEvent(), startMapEvent(),
scalarEvent("a true"), scalarEvent("null d"), scalarEvent("e 42"), scalarEvent(""),
endMapEvent(), endDocEvent())
test "Parsing: Map in Sequence":
ensure(" - key: value\n key2: value2\n -\n key3: value3",
startDocEvent(), startSeqEvent(), startMapEvent(), scalarEvent("key"),
scalarEvent("value"), scalarEvent("key2"), scalarEvent("value2"), endMapEvent(),
startMapEvent(), scalarEvent("key3"), scalarEvent("value3"), endMapEvent(),
endSeqEvent(), endDocEvent())
test "Parsing: Sequence in Map":
ensure("key:\n - item1\n - item2", startDocEvent(), startMapEvent(),
scalarEvent("key"), startSeqEvent(), scalarEvent("item1"), scalarEvent("item2"),
endSeqEvent(), endMapEvent(), endDocEvent())
test "Parsing: Sequence in Sequence":
ensure("- - l1_i1\n - l1_i2\n- l2_i1", startDocEvent(), startSeqEvent(),
startSeqEvent(), scalarEvent("l1_i1"), scalarEvent("l1_i2"), endSeqEvent(),
scalarEvent("l2_i1"), endSeqEvent(), endDocEvent())
test "Parsing: Flow Sequence":
ensure("[2, b]", startDocEvent(), startSeqEvent(), scalarEvent("2"),
scalarEvent("b"), endSeqEvent(), endDocEvent())
test "Parsing: Flow Map":
ensure("{a: Y, 1.337: d}", startDocEvent(), startMapEvent(), scalarEvent("a"),
scalarEvent("Y"), scalarEvent("1.337"),
scalarEvent("d"), endMapEvent(), endDocEvent())
test "Parsing: Flow Sequence in Flow Sequence":
ensure("[a, [b, c]]", startDocEvent(), startSeqEvent(), scalarEvent("a"),
startSeqEvent(), scalarEvent("b"), scalarEvent("c"), endSeqEvent(),
endSeqEvent(), endDocEvent())
test "Parsing: Flow Sequence in Flow Map":
ensure("{a: [b, c], [d, e]: f}", startDocEvent(), startMapEvent(), scalarEvent("a"),
startSeqEvent(), scalarEvent("b"), scalarEvent("c"), endSeqEvent(),
startSeqEvent(), scalarEvent("d"), scalarEvent("e"), endSeqEvent(),
scalarEvent("f"), endMapEvent(), endDocEvent())
test "Parsing: Flow Sequence in Map":
ensure("a: [b, c]", startDocEvent(), startMapEvent(), scalarEvent("a"),
startSeqEvent(), scalarEvent("b"), scalarEvent("c"), endSeqEvent(),
endMapEvent(), endDocEvent())
test "Parsing: Flow Map in Sequence":
ensure("- {a: b}", startDocEvent(), startSeqEvent(), startMapEvent(), scalarEvent("a"),
scalarEvent("b"), endMapEvent(), endSeqEvent(), endDocEvent())
test "Parsing: Multiline scalar (top level)":
ensure("a\nb \n c\nd", startDocEvent(), scalarEvent("a b c d"), endDocEvent())
test "Parsing: Multiline scalar (in map)":
ensure("a: b\n c\nd:\n e\n f", startDocEvent(), startMapEvent(), scalarEvent("a"),
scalarEvent("b c"), scalarEvent("d"), scalarEvent("e f"), endMapEvent(), endDocEvent())
test "Parsing: Block scalar (literal)":
ensure("a: |\x0A ab\x0A \x0A cd\x0A ef\x0A \x0A", startDocEvent(),
startMapEvent(), scalarEvent("a"), scalarEvent("ab\x0A\x0Acd\x0Aef\x0A", yTagExclamationmark),
endMapEvent(), endDocEvent())
test "Parsing: Block scalar (folded)":
ensure("a: >\x0A ab\x0A cd\x0A \x0A ef\x0A\x0A\x0A gh\x0A", startDocEvent(),
startMapEvent(), scalarEvent("a"), scalarEvent("ab cd\x0Aef\x0A\x0Agh\x0A", yTagExclamationmark),
endMapEvent(), endDocEvent())
test "Parsing: Block scalar (keep)":
ensure("a: |+\x0A ab\x0A \x0A \x0A", startDocEvent(), startMapEvent(),
scalarEvent("a"), scalarEvent("ab\x0A\x0A \x0A", yTagExclamationmark), endMapEvent(), endDocEvent())
test "Parsing: Block scalar (strip)":
ensure("a: |-\x0A ab\x0A \x0A \x0A", startDocEvent(), startMapEvent(),
scalarEvent("a"), scalarEvent("ab", yTagExclamationmark), endMapEvent(), endDocEvent())
test "Parsing: non-specific tags of quoted strings":
ensure("\"a\"", startDocEvent(),
scalarEvent("a", yTagExclamationMark), endDocEvent())
test "Parsing: explicit non-specific tag":
ensure("! a", startDocEvent(), scalarEvent("a", yTagExclamationMark), endDocEvent())
test "Parsing: secondary tag handle resolution":
ensure("!!str a", startDocEvent(), scalarEvent("a", yTagString), endDocEvent())
test "Parsing: resolving custom tag handles":
let fooId = tagLib.registerUri("tag:example.com,2015:foo")
ensure("%TAG !t! tag:example.com,2015:\n---\n!t!foo a", startDocEvent(),
scalarEvent("a", fooId), endDocEvent())
test "Parsing: tags in sequence":
ensure(" - !!str a\n - b\n - !!int c\n - d", startDocEvent(),
startSeqEvent(), scalarEvent("a", yTagString), scalarEvent("b"),
scalarEvent("c", yTagInteger), scalarEvent("d"), endSeqEvent(), endDocEvent())
test "Parsing: tags in implicit map":
ensure("!!str a: b\nc: !!int d\ne: !!str f\ng: h", startDocEvent(), startMapEvent(),
scalarEvent("a", yTagString), scalarEvent("b"), scalarEvent("c"),
scalarEvent("d", yTagInteger), scalarEvent("e"), scalarEvent("f", yTagString),
scalarEvent("g"), scalarEvent("h"), endMapEvent(), endDocEvent())
test "Parsing: tags in explicit map":
ensure("? !!str a\n: !!int b\n? c\n: !!str d", startDocEvent(), startMapEvent(),
scalarEvent("a", yTagString), scalarEvent("b", yTagInteger), scalarEvent("c"),
scalarEvent("d", yTagString), endMapEvent(), endDocEvent())
test "Parsing: tags for block objects":
ensure("--- !!map\nfoo: !!seq\n - a\n - !!str b\n!!str bar: !!str baz",
startDocEvent(), startMapEvent(yTagMap), scalarEvent("foo"),
startSeqEvent(yTagSequence), scalarEvent("a"), scalarEvent("b", yTagString),
endSeqEvent(), scalarEvent("bar", yTagString),
scalarEvent("baz", yTagString), endMapEvent(), endDocEvent())
test "Parsing: root tag for block sequence":
ensure("--- !!seq\n- a", startDocEvent(), startSeqEvent(yTagSequence),
scalarEvent("a"), endSeqEvent(), endDocEvent())
test "Parsing: root tag for explicit block map":
ensure("--- !!map\n? a\n: b", startDocEvent(), startMapEvent(yTagMap),
scalarEvent("a"), scalarEvent("b"), endMapEvent(), endDocEvent())
test "Parsing: tags for flow objects":
ensure("!!map { k: !!seq [ a, !!str b] }", startDocEvent(), startMapEvent(yTagMap),
scalarEvent("k"), startSeqEvent(yTagSequence), scalarEvent("a"),
scalarEvent("b", yTagString), endSeqEvent(), endMapEvent(), endDocEvent())
test "Parsing: Tag after directives end":
ensure("--- !!str\nfoo", startDocEvent(), scalarEvent("foo", yTagString), endDocEvent())
test "Parsing: Simple Anchor":
ensure("&a str", startDocEvent(), scalarEvent("str", yTagQuestionMark,
0.AnchorId), endDocEvent())
test "Parsing: Anchors in sequence":
ensure(" - &a a\n - b\n - &c c\n - &a d", startDocEvent(), startSeqEvent(),
scalarEvent("a", yTagQuestionMark, 0.AnchorId), scalarEvent("b"),
scalarEvent("c", yTagQuestionMark, 1.AnchorId),
scalarEvent("d", yTagQuestionMark, 2.AnchorId), endSeqEvent(),
endDocEvent())
test "Parsing: Anchors in map":
ensure("&a a: b\nc: &d d", startDocEvent(), startMapEvent(),
scalarEvent("a", yTagQuestionMark, 0.AnchorId),
scalarEvent("b"), scalarEvent("c"),
scalarEvent("d", yTagQuestionMark, 1.AnchorId),
endMapEvent(), endDocEvent())
test "Parsing: Anchors and tags":
ensure(" - &a !!str a\n - !!int b\n - &c !!int c\n - &d d", startDocEvent(),
startSeqEvent(), scalarEvent("a", yTagString, 0.AnchorId),
scalarEvent("b", yTagInteger), scalarEvent("c", yTagInteger, 1.AnchorId),
scalarEvent("d", yTagQuestionMark, 2.AnchorId), endSeqEvent(),
endDocEvent())
test "Parsing: Aliases in sequence":
ensure(" - &a a\n - &b b\n - *a\n - *b", startDocEvent(), startSeqEvent(),
scalarEvent("a", yTagQuestionMark, 0.AnchorId),
scalarEvent("b", yTagQuestionMark, 1.AnchorId), aliasEvent(0.AnchorId),
aliasEvent(1.AnchorId), endSeqEvent(), endDocEvent())
test "Parsing: Aliases in map":
ensure("&a a: &b b\n*a : *b", startDocEvent(), startMapEvent(),
scalarEvent("a", yTagQuestionMark, 0.AnchorId),
scalarEvent("b", yTagQuestionMark, 1.AnchorId), aliasEvent(0.AnchorId),
aliasEvent(1.AnchorId), endMapEvent(), endDocEvent())
test "Parsing: Aliases in flow":
ensure("{ &a [a, &b b]: *b, *a : [c, *b, d]}", startDocEvent(), startMapEvent(),
startSeqEvent(yTagQuestionMark, 0.AnchorId), scalarEvent("a"),
scalarEvent("b", yTagQuestionMark, 1.AnchorId), endSeqEvent(),
aliasEvent(1.AnchorId), aliasEvent(0.AnchorId), startSeqEvent(),
scalarEvent("c"), aliasEvent(1.AnchorId), scalarEvent("d"), endSeqEvent(),
endMapEvent(), endDocEvent())
test "Parsing: Tags on empty scalars":
ensure("!!str : a\nb: !!int\n!!str : !!str", startDocEvent(), startMapEvent(),
scalarEvent("", yTagString), scalarEvent("a"), scalarEvent("b"),
scalarEvent("", yTagInteger), scalarEvent("", yTagString),
scalarEvent("", yTagString), endMapEvent(), endDocEvent())
test "Parsing: Anchors on empty scalars":
ensure("&a : a\nb: &b\n&c : &a", startDocEvent(), startMapEvent(),
scalarEvent("", yTagQuestionMark, 0.AnchorId), scalarEvent("a"),
scalarEvent("b"), scalarEvent("", yTagQuestionMark, 1.AnchorId),
scalarEvent("", yTagQuestionMark, 2.AnchorId),
scalarEvent("", yTagQuestionMark, 3.AnchorId), endMapEvent(), endDocEvent())
test "Parsing: Whitespace before end of flow content":
ensure("- [a, b, c ]", startDocEvent(), startSeqEvent(),
startSeqEvent(), scalarEvent("a"), scalarEvent("b"),
scalarEvent("c"), endSeqEvent(), endSeqEvent(), endDocEvent())
test "Parsing: Empty lines after document":
ensure(":\n\n", startDocEvent(), startMapEvent(), scalarEvent(""),
scalarEvent(""), endMapEvent(), endDocEvent())
test "Parsing: Empty lines between map elements":
ensure("1: 2\n\n\n3: 4", startDocEvent(), startMapEvent(),
scalarEvent("1"), scalarEvent("2"), scalarEvent("3"),
scalarEvent("4"), endMapEvent(), endDocEvent())
test "Parsing: Sequence beginning at same line as map key":
ensure("1:\n- 2\n- 3\n4: 5", startDocEvent(), startMapEvent(),
scalarEvent("1"), startSeqEvent(), scalarEvent("2"),
scalarEvent("3"), endSeqEvent(), scalarEvent("4"),
scalarEvent("5"), endMapEvent(), endDocEvent())
test "Parsing: Sequence beginning at same line as map key with > 0 indent":
ensure(" foo:\n - bar\n baz:", startDocEvent(), startMapEvent(),
scalarEvent("foo"), startSeqEvent(), scalarEvent("bar"),
endSeqEvent(), scalarEvent("baz"), scalarEvent(""),
endMapEvent(), endDocEvent())
test "Parsing: Colon in double quoted string":
ensure("\"foo: bar\\\": baz\"", startDocEvent(),
scalarEvent("foo: bar\": baz", yTagExclamationMark),
endDocEvent())

View File

@ -4,4 +4,4 @@
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
import parsing, constructingJson, serializing, dom
import constructingJson, serializing, dom

View File

@ -20,8 +20,7 @@ import streams, unicode, lexbase, tables, strutils, json, hashes, queues,
macros, typetraits, parseutils
export streams, tables, json
when defined(yamlDebug):
import terminal
when defined(yamlDebug): import terminal
type
TypeHint* = enum
@ -50,9 +49,9 @@ type
YamlStreamEventKind* = enum
## Kinds of YAML events that may occur in an ``YamlStream``. Event kinds
## are discussed in ``YamlStreamEvent``.
yamlStartDocument, yamlEndDocument, yamlStartMap, yamlEndMap,
yamlStartSequence, yamlEndSequence, yamlScalar, yamlAlias
## are discussed in `YamlStreamEvent <#YamlStreamEvent>`_.
yamlStartDoc, yamlEndDoc, yamlStartMap, yamlEndMap,
yamlStartSeq, yamlEndSeq, yamlScalar, yamlAlias
TagId* = distinct int ## \
## A ``TagId`` identifies a tag URI, like for example
@ -76,7 +75,7 @@ type
YamlStreamEvent* = object
## An element from a `YamlStream <#YamlStream>`_. Events that start an
## object (``yamlStartMap``, ``yamlStartSequence``, ``yamlScalar``) have
## object (``yamlStartMap``, ``yamlStartSeq``, ``yamlScalar``) have
## an optional anchor and a tag associated with them. The anchor will be
## set to ``yAnchorNone`` if it doesn't exist.
##
@ -89,32 +88,31 @@ type
of yamlStartMap:
mapAnchor* : AnchorId
mapTag* : TagId
of yamlStartSequence:
of yamlStartSeq:
seqAnchor* : AnchorId
seqTag* : TagId
of yamlScalar:
scalarAnchor* : AnchorId
scalarTag* : TagId
scalarContent*: string # may not be nil (but empty)
of yamlEndMap, yamlEndSequence, yamlStartDocument, yamlEndDocument:
of yamlEndMap, yamlEndSeq, yamlStartDoc, yamlEndDoc:
discard
of yamlAlias:
aliasTarget* : AnchorId
YamlStream* = object ## \
## A ``YamlStream`` is an iterator-like object that yields a
## well-formed stream of
## ``YamlStreamEvents``. Well-formed means that every ``yamlStartMap``
## is terminated by a ``yamlEndMap``, every ``yamlStartSequence`` is
## terminated by a ``yamlEndSequence`` and every ``yamlStartDocument``
## is terminated by a ``yamlEndDocument``. Moreover, every emitted map
## has an even number of children.
## well-formed stream of ``YamlStreamEvents``. Well-formed means that
## every ``yamlStartMap`` is terminated by a ``yamlEndMap``, every
## ``yamlStartSeq`` is terminated by a ``yamlEndSeq`` and every
## ``yamlStartDoc`` is terminated by a ``yamlEndDoc``. Moreover, every
## emitted mapping has an even number of children.
##
## The creator of a ``YamlStream`` is responsible for it being
## well-formed. A user of the stream may assume that it is well-formed
## and is not required to check for it. The procs in this module will
## always yield a well-formed ``YamlStream`` and expect it to be
## well-formed if it's an input.
## well-formed if they take it as input parameter.
##
##
backend: iterator(): YamlStreamEvent
@ -168,9 +166,9 @@ type
## for the non-specific tags ``?`` and ``!``, uses flow style, quotes
## all string scalars.
## - ``ypsDefault``: Tries to be as human-readable as possible. Uses
## block style by default, but tries to condense maps and sequences
## which only contain scalar nodes into a single line using flow
## style.
## block style by default, but tries to condense mappings and
## sequences which only contain scalar nodes into a single line using
## flow style.
## - ``ypsJson``: Omits the ``%YAML`` directive and the ``---``
## marker. Uses flow style. Flattens anchors and aliases, omits tags.
## Output will be parseable as JSON. ``YamlStream`` to dump may only
@ -333,7 +331,7 @@ const
## `!!str <http://yaml.org/type/str.html >`_ tag
yTagSequence* : TagId = 3.TagId ## \
## `!!seq <http://yaml.org/type/seq.html>`_ tag
yTagMap* : TagId = 4.TagId ## \
yTagMapping* : TagId = 4.TagId ## \
## `!!map <http://yaml.org/type/map.html>`_ tag
# json & core schema