Source code for parsemon.coroutine
from functools import wraps
from parsemon.extensions import trampoline
from .extensions import result
[docs]def do(f):
"""Use this as a decorator
Do allows you to combine parsers in a more pythonic way.
It expects a generator that returns something in the end and takes
no arguments.
It lets you write parsers like the following::
@do
def three_letters():
first = yield character()
second = yield character()
third = yield character()
return first + second + third
"""
@wraps(f)
def decorator(*args, **kwargs):
def _do_parser(stream, original_continuation):
generator = f(*args, **kwargs)
def do_continuation(progressed_stream, previous_parsing_result):
if previous_parsing_result.is_failure():
return trampoline.Call(
original_continuation,
progressed_stream,
previous_parsing_result,
)
try:
next_parser = generator.send(previous_parsing_result.value)
return trampoline.Call(
next_parser,
progressed_stream,
do_continuation,
)
except StopIteration as stop:
return trampoline.Call(
original_continuation,
progressed_stream,
result.success(getattr(stop, "value", None)),
)
initial_parser = generator.send(None)
return trampoline.Call(
initial_parser,
stream,
do_continuation,
)
return _do_parser
return decorator