added lazy to parser

This commit is contained in:
Ruediger Ludwig 2022-12-09 18:32:36 +01:00
parent 4ca3d7d51a
commit 5abefd8dbe
2 changed files with 62 additions and 0 deletions

View file

@ -114,6 +114,10 @@ class P(Generic[T]):
def surround(self, other: P[Any]) -> P[T]:
return P.map3(other, self, other, lambda _1, v, _2: v)
def some_lazy(self) -> P[list[T]]:
return P._fix(lambda p: self.bind(
lambda x: P.either(P.pure([]), p).fmap(lambda ys: [x] + ys)))
def some(self) -> P[list[T]]:
return P._fix(lambda p: self.bind(
lambda x: P.either(p, P.pure([])).fmap(lambda ys: [x] + ys)))
@ -121,12 +125,18 @@ class P(Generic[T]):
def many(self) -> P[list[T]]:
return P.either(self.some(), P.pure([]))
def many_lazy(self) -> P[list[T]]:
return P.either(P.pure([]), self.some_lazy())
def satisfies(self, pred: Callable[[T], bool]) -> P[T]:
return self.bind(lambda v: P.pure(v) if pred(v) else P.fail())
def optional(self) -> P[T | None]:
return P.either(self, P.pure(None))
def optional_lazy(self) -> P[T | None]:
return P.either(P.pure(None), self)
def times(self, *, max: int | None = None, min: int | None = None,
exact: int | None = None) -> P[list[T]]:
match (exact, min, max):
@ -139,6 +149,18 @@ class P(Generic[T]):
case _:
raise Exception("Choose exactly one of exact, min or max")
def times_lazy(self, *, max: int | None = None, min: int | None = None,
exact: int | None = None) -> P[list[T]]:
match (exact, min, max):
case (int(e), None, None):
return self.many_lazy().satisfies(lambda lst: len(lst) == e)
case (None, int(mn), None):
return self.many_lazy().satisfies(lambda lst: len(lst) >= mn)
case (None, None, int(mx)):
return self.many_lazy().satisfies(lambda lst: len(lst) <= mx)
case _:
raise Exception("Choose exactly one of exact, min or max")
def sep_by(self, sep: P[Any]) -> P[list[T]]:
return P.map2(self, P.snd(sep, self).many(), lambda f, r: [f] + r)