lib.bend checks
raw source on the hub · import 0xd395e827d4f2e55365bfb5173c04c4ee/lib.bend as Lib
Parse — tiny String parser combinators for Bend. Publish entry for this package. Depends only on Base.
Encoding: a Parser for A is String → Maybe (A & remainder).
One-shot combinators (bind/or/optional/map) take ordinary Parser functions
(affine closures are fine — each is used at most once). Predicates for
satisfy/take_while are templates (~) so they may fire on many chars.
Tradeoff: a Parser closure is not reusable; rebuild with top-level defs or
lambdas at each site. String is Data, so or/optional take +s to retry.
1 import
import Base
Laws
law Parser provedsource · line 13 · raw
@-A:Type -> Type
Parser(A) ≅ String → Maybe<&1, A & String> (&1 keeps A : Type).
Definitions
def Parse.pure source · line 21 · raw
@-A:Type -> @x:A -> @s:String -> Maybe<&1, Pair(A, String)>
Always succeed with x, consuming nothing.
def Parse.fail source · line 25 · raw
@-A:Type -> @s:String -> Maybe<&1, Pair(A, String)>
Always fail.
def Parse.map source · line 29 · raw
@-A:Type -> @-B:Type -> @f:(@_:A -> B) -> @m:Maybe<&1, Pair(A, String)> -> Maybe<&1, Pair(B, String)>
Map over a successful parse payload (value only; remainder unchanged).
def Parse.bind.cont source · line 39 · raw
@-A:Type -> @-B:Type -> @f:(@_:A -> @_:String -> Maybe<&1, Pair(B, String)>) -> @m:Maybe<&1, Pair(A, String)> -> Maybe<&1, Pair(B, String)>
Run p, then continue with f(value, remainder). Helpers avoid matching on p(s).
def Parse.bind source · line 49 · raw
@-A:Type -> @-B:Type -> @p:Parser(A) -> @f:(@_:A -> @_:String -> Maybe<&1, Pair(B, String)>) -> @s:String -> Maybe<&1, Pair(B, String)>
def Parse.and_then source · line 56 · raw
@-A:Type -> @-B:Type -> @p:Parser(A) -> @f:(@_:A -> @_:String -> Maybe<&1, Pair(B, String)>) -> @s:String -> Maybe<&1, Pair(B, String)>
Alias: and_then = bind.
def Parse.or.cont source · line 63 · raw
@-A:Type -> @q:Parser(A) -> @+s:String -> @m:Maybe<&1, Pair(A, String)> -> Maybe<&1, Pair(A, String)>
Prefer p; on failure try q on the same input (+s copies; String is Data).
def Parse.or source · line 72 · raw
@-A:Type -> @p:Parser(A) -> @q:Parser(A) -> @+s:String -> Maybe<&1, Pair(A, String)>
def Parse.satisfy.go source · line 78 · raw
@+h:Char -> @t:String -> @ok:Bool -> Maybe<&1, Pair(Char, String)>
Next char if pred holds. ~pred is a template (reusable, closed).
def Parse.char.go source · line 95 · raw
@+expected:Char -> @+h:Char -> @t:String -> @ok:Bool -> Maybe<&1, Pair(Char, String)>
Exact character.
def Parse.char source · line 104 · raw
@+expected:Char -> @s:String -> Maybe<&1, Pair(Char, String)>
def Parse.string.go source · line 112 · raw
@+p:String -> @+s:String -> @ok:Bool -> Maybe<&1, Pair(String, String)>
Exact string prefix; value is the matched prefix, rest is the suffix.
def Parse.string source · line 121 · raw
@+p:String -> @+s:String -> Maybe<&1, Pair(String, String)>
def Parse.optional.cont source · line 155 · raw
@-A:Type -> @+s:String -> @m:Maybe<&1, Pair(A, String)> -> Maybe<&1, Pair(Maybe<&1, A>, String)>
Optional: always succeeds; value is Maybe A.
def Parse.optional source · line 164 · raw
@-A:Type -> @p:Parser(A) -> @+s:String -> Maybe<&1, Pair(Maybe<&1, A>, String)>
def Parse.run source · line 170 · raw
@-A:Type -> @p:Parser(A) -> @s:String -> Maybe<&1, Pair(A, String)>
Run parser (identity application).
def Parse.run_full.rest source · line 174 · raw
@-A:Type -> @x:A -> @rest:String -> Maybe<&1, A>
Succeed only if the whole input is consumed.
def Parse.run_full.go source · line 181 · raw
@-A:Type -> @m:Maybe<&1, Pair(A, String)> -> Maybe<&1, A>
def Parse.run_full source · line 188 · raw
@-A:Type -> @p:Parser(A) -> @s:String -> Maybe<&1, A>
Templates
template Parse.satisfy source · line 87 · raw
@-pred:(@_:Char -> Bool) -> @s:String -> Maybe<&1, Pair(Char, String)>
template Parse.take_while.go source · line 127 · raw
@-pred:(@_:Char -> Bool) -> @n:Nat -> @s:String -> @acc:String -> @step:Bool -> @+h:Char -> @ok:Bool -> Pair(String, String)
take_while: one self-recursive template with Nat fuel (2 steps per char). step=False → inspect s; step=True → inspect ok (h is the candidate char). Avoids mutual template recursion (Bend: templates may only call those above).
template Parse.take_while source · line 146 · raw
@-pred:(@_:Char -> Bool) -> @+s:String -> Maybe<&1, Pair(String, String)>
Longest prefix whose chars all satisfy pred. Always succeeds (may be empty).