Source code for parsemon.basic
"""Implement basic parsers that should be generally useful"""
from typing import Tuple
from .coroutine import do
from .internals import fmap, literal, try_parser
from .parser import chain, choice, choices, many, many1, one_of, unit
[docs]def concat(chars):
"""Concatenate a list of chars to a string"""
return "".join(chars)
DIGITS = "0123456789"
DIGIT = one_of(DIGITS)
PARSE_DIGITS = fmap(concat, many1(DIGIT))
[docs]@do
def integer():
"""Parse an integer."""
first = yield one_of("+-" + DIGITS)
if first == "-":
sign = -1
first = yield DIGIT
elif first == "+":
sign = 1
first = yield DIGIT
else:
sign = 1
rest = yield fmap(concat, many(DIGIT))
return sign * int(first + rest)
[docs]@do
def floating_point(delimiter: str = "."):
"""Parse a floating point number.
:param delimiter: defaults to ., is expected token to seperate integer part
from rational part
"""
@do
def without_integer_part():
yield literal(delimiter)
after_point = yield PARSE_DIGITS
return "", after_point
@do
def without_rational_part():
before_point = yield PARSE_DIGITS
yield literal(delimiter)
return before_point, ""
@do
def both_parts():
before_point = yield PARSE_DIGITS
yield literal(delimiter)
after_point = yield PARSE_DIGITS
return before_point, after_point
def sign():
return choices(
literal("+"),
literal("-"),
unit("+"), # default to + when no sign is detected
)
@do
def float_without_e():
signum = yield sign()
before_point, after_point = yield choices(
without_integer_part(),
try_parser(both_parts()),
without_rational_part(),
)
return signum, before_point, after_point
def parse_exponent():
return choice(chain(one_of("eE"), fmap(str, integer())), unit("0"))
def int_to_signum(n: int) -> Tuple[str, str, str]:
return ("+" if n >= 0 else "-", str(n), "")
signum, before_point, after_point = yield choice(
try_parser(float_without_e()), fmap(int_to_signum, integer())
)
exponent = yield parse_exponent()
return float(
"{signum}{before_point}.{after_point}E{exponent}".format(
signum=signum,
before_point=before_point,
after_point=after_point,
exponent=exponent,
)
)