Internal changes to YamlStream (no API change)

* Prepared YamlStream for major parser refactoring
This commit is contained in:
Felix Krause 2016-08-10 20:42:44 +02:00
parent 404aece2fd
commit 4ddc094cfd
3 changed files with 40 additions and 43 deletions

View File

@ -64,9 +64,11 @@ proc composeNode(s: var YamlStream, tagLib: TagLibrary,
proc compose*(s: var YamlStream, tagLib: TagLibrary): YamlDocument
{.raises: [YamlStreamError, YamlConstructionError].} =
var context = newConstructionContext()
yAssert s.next().kind == yamlStartDoc
var n = s.next()
yAssert n.kind == yamlStartDoc
result.root = composeNode(s, tagLib, context)
yAssert s.next().kind == yamlEndDoc
n = s.next()
yAssert n.kind == yamlEndDoc
proc loadDOM*(s: Stream): YamlDocument
{.raises: [IOError, YamlParserError, YamlConstructionError].} =

View File

@ -4,18 +4,31 @@
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
proc initYamlStream*(backend: iterator(): YamlStreamEvent): YamlStream =
result.peeked = false
result.backend = backend
type IteratorYamlStream = ref object of YamlStream
backend: iterator(): YamlStreamEvent
proc next*(s: var YamlStream): YamlStreamEvent =
proc initYamlStream*(backend: iterator(): YamlStreamEvent): YamlStream =
result = new(IteratorYamlStream)
result.peeked = false
result.isFinished = false
IteratorYamlStream(result).backend = backend
result.nextImpl = proc(s: YamlStream, e: var YamlStreamEvent): bool =
e = IteratorYamlStream(s).backend()
if finished(IteratorYamlStream(s).backend):
s.isFinished = true
result = false
else: result = true
proc next*(s: YamlStream): YamlStreamEvent =
yAssert(not s.isFinished)
if s.peeked:
s.peeked = false
shallowCopy(result, s.cached)
else:
try:
shallowCopy(result, s.backend())
yAssert(not finished(s.backend))
while true:
if s.nextImpl(s, result): break
yAssert(not s.isFinished)
except YamlStreamError:
let cur = getCurrentException()
var e = newException(YamlStreamError, cur.msg)
@ -27,25 +40,25 @@ proc next*(s: var YamlStream): YamlStreamEvent =
e.parent = cur
raise e
proc peek*(s: var YamlStream): YamlStreamEvent =
proc peek*(s: YamlStream): YamlStreamEvent =
if not s.peeked:
s.cached = s.next()
s.peeked = true
shallowCopy(result, s.cached)
proc `peek=`*(s: var YamlStream, value: YamlStreamEvent) =
proc `peek=`*(s: YamlStream, value: YamlStreamEvent) =
s.cached = value
s.peeked = true
proc finished*(s: var YamlStream): bool =
proc finished*(s: YamlStream): bool =
if s.peeked: result = false
else:
try:
s.cached = s.backend()
if finished(s.backend): result = true
else:
s.peeked = true
result = false
while true:
if s.isFinished: return true
if s.nextImpl(s, s.cached):
s.peeked = true
return false
except YamlStreamError:
let cur = getCurrentException()
var e = newException(YamlStreamError, cur.msg)

View File

@ -99,7 +99,7 @@ type
of yamlAlias:
aliasTarget* : AnchorId
YamlStream* = object ## \
YamlStream* = ref object of RootObj ## \
## 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
@ -112,9 +112,8 @@ type
## 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 they take it as input parameter.
##
##
backend: iterator(): YamlStreamEvent
nextImpl: proc(s: YamlStream, e: var YamlStreamEvent): bool
isFinished: bool
peeked: bool
cached: YamlStreamEvent
@ -457,42 +456,25 @@ proc hash*(id: AnchorId): Hash {.borrow.}
proc initYamlStream*(backend: iterator(): YamlStreamEvent):
YamlStream {.raises: [].}
## Creates a new ``YamlStream`` that uses the given iterator as backend.
proc next*(s: var YamlStream): YamlStreamEvent {.raises: [YamlStreamError].}
proc next*(s: YamlStream): YamlStreamEvent {.raises: [YamlStreamError].}
## Get the next item of the stream. Requires ``finished(s) == true``.
## If the backend yields an exception, that exception will be encapsulated
## into a ``YamlStreamError``, which will be raised.
proc peek*(s: var YamlStream): YamlStreamEvent {.raises: [YamlStreamError].}
proc peek*(s: YamlStream): YamlStreamEvent {.raises: [YamlStreamError].}
## Get the next item of the stream without advancing the stream.
## Requires ``finished(s) == true``. Handles exceptions of the backend like
## ``next()``.
proc `peek=`*(s: var YamlStream, value: YamlStreamEvent) {.raises: [].}
proc `peek=`*(s: YamlStream, value: YamlStreamEvent) {.raises: [].}
## Set the next item of the stream. Will replace a previously peeked item,
## if one exists.
proc finished*(s: var YamlStream): bool {.raises: [YamlStreamError].}
proc finished*(s: YamlStream): bool {.raises: [YamlStreamError].}
## ``true`` if no more items are available in the stream. Handles exceptions
## of the backend like ``next()``.
iterator items*(s: var YamlStream): YamlStreamEvent
iterator items*(s: YamlStream): YamlStreamEvent
{.raises: [YamlStreamError].} =
## Iterate over all items of the stream. You may not use ``peek()`` on the
## stream while iterating.
if s.peeked:
s.peeked = false
yield s.cached
while true:
var event: YamlStreamEvent
try:
event = s.backend()
if finished(s.backend): break
except YamlStreamError:
let cur = getCurrentException()
var e = newException(YamlStreamError, cur.msg)
e.parent = cur.parent
raise e
except Exception:
var e = newException(YamlStreamError, getCurrentExceptionMsg())
e.parent = getCurrentException()
raise e
yield event
while not s.finished(): yield s.next()
proc initTagLibrary*(): TagLibrary {.raises: [].}
## initializes the ``tags`` table and sets ``nextCustomTagId`` to