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 proc compose*(s: var YamlStream, tagLib: TagLibrary): YamlDocument
{.raises: [YamlStreamError, YamlConstructionError].} = {.raises: [YamlStreamError, YamlConstructionError].} =
var context = newConstructionContext() var context = newConstructionContext()
yAssert s.next().kind == yamlStartDoc var n = s.next()
yAssert n.kind == yamlStartDoc
result.root = composeNode(s, tagLib, context) result.root = composeNode(s, tagLib, context)
yAssert s.next().kind == yamlEndDoc n = s.next()
yAssert n.kind == yamlEndDoc
proc loadDOM*(s: Stream): YamlDocument proc loadDOM*(s: Stream): YamlDocument
{.raises: [IOError, YamlParserError, YamlConstructionError].} = {.raises: [IOError, YamlParserError, YamlConstructionError].} =

View File

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

View File

@ -99,7 +99,7 @@ type
of yamlAlias: of yamlAlias:
aliasTarget* : AnchorId aliasTarget* : AnchorId
YamlStream* = object ## \ YamlStream* = ref object of RootObj ## \
## A ``YamlStream`` is an iterator-like object that yields a ## A ``YamlStream`` is an iterator-like object that yields a
## well-formed stream of ``YamlStreamEvents``. Well-formed means that ## well-formed stream of ``YamlStreamEvents``. Well-formed means that
## every ``yamlStartMap`` is terminated by a ``yamlEndMap``, every ## 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 ## 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 ## always yield a well-formed ``YamlStream`` and expect it to be
## well-formed if they take it as input parameter. ## well-formed if they take it as input parameter.
## nextImpl: proc(s: YamlStream, e: var YamlStreamEvent): bool
## isFinished: bool
backend: iterator(): YamlStreamEvent
peeked: bool peeked: bool
cached: YamlStreamEvent cached: YamlStreamEvent
@ -457,42 +456,25 @@ proc hash*(id: AnchorId): Hash {.borrow.}
proc initYamlStream*(backend: iterator(): YamlStreamEvent): proc initYamlStream*(backend: iterator(): YamlStreamEvent):
YamlStream {.raises: [].} YamlStream {.raises: [].}
## Creates a new ``YamlStream`` that uses the given iterator as backend. ## 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``. ## Get the next item of the stream. Requires ``finished(s) == true``.
## If the backend yields an exception, that exception will be encapsulated ## If the backend yields an exception, that exception will be encapsulated
## into a ``YamlStreamError``, which will be raised. ## 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. ## Get the next item of the stream without advancing the stream.
## Requires ``finished(s) == true``. Handles exceptions of the backend like ## Requires ``finished(s) == true``. Handles exceptions of the backend like
## ``next()``. ## ``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, ## Set the next item of the stream. Will replace a previously peeked item,
## if one exists. ## 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 ## ``true`` if no more items are available in the stream. Handles exceptions
## of the backend like ``next()``. ## of the backend like ``next()``.
iterator items*(s: var YamlStream): YamlStreamEvent iterator items*(s: YamlStream): YamlStreamEvent
{.raises: [YamlStreamError].} = {.raises: [YamlStreamError].} =
## Iterate over all items of the stream. You may not use ``peek()`` on the ## Iterate over all items of the stream. You may not use ``peek()`` on the
## stream while iterating. ## stream while iterating.
if s.peeked: while not s.finished(): yield s.next()
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
proc initTagLibrary*(): TagLibrary {.raises: [].} proc initTagLibrary*(): TagLibrary {.raises: [].}
## initializes the ``tags`` table and sets ``nextCustomTagId`` to ## initializes the ``tags`` table and sets ``nextCustomTagId`` to