Current section

Files

Jump to
pears src pears@combinators.erl
Raw

src/pears@combinators.erl

-module(pears@combinators).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]).
-export([map/2, to/2, alt/2, any/0, eof/0, satisfying/1, just/1, pair/2, seq/1, left/2, right/2, many0/1, many1/1, lazy/1, one_of/1, none_of/1, between/3, choice/1, sep_by0/2, sep_by1/2, maybe/1, unwrap/2, recognize/1]).
-spec map(
fun((list(FLZ)) -> {ok, pears:parsed(FLZ, FMA)} |
{error, pears:parse_error(FLZ)}),
fun((FMA) -> FMD)
) -> fun((list(FLZ)) -> {ok, pears:parsed(FLZ, FMD)} |
{error, pears:parse_error(FLZ)}).
map(P, Fun) ->
fun(Input) -> _pipe = P(Input),
gleam@result:map(
_pipe,
fun(Parsed) ->
{parsed,
erlang:element(2, Parsed),
Fun(erlang:element(3, Parsed))}
end
) end.
-spec to(
fun((list(FMG)) -> {ok, pears:parsed(FMG, any())} |
{error, pears:parse_error(FMG)}),
FMK
) -> fun((list(FMG)) -> {ok, pears:parsed(FMG, FMK)} |
{error, pears:parse_error(FMG)}).
to(Parser, Value) ->
map(Parser, fun(_) -> Value end).
-spec alt(
fun((list(FMN)) -> {ok, pears:parsed(FMN, FMO)} |
{error, pears:parse_error(FMN)}),
fun((list(FMN)) -> {ok, pears:parsed(FMN, FMO)} |
{error, pears:parse_error(FMN)})
) -> fun((list(FMN)) -> {ok, pears:parsed(FMN, FMO)} |
{error, pears:parse_error(FMN)}).
alt(Parser_1, Parser_2) ->
fun(Input) -> case Parser_1(Input) of
{ok, Result} ->
{ok, Result};
{error, _} ->
Parser_2(Input)
end end.
-spec any() -> fun((list(FMV)) -> {ok, pears:parsed(FMV, FMV)} |
{error, pears:parse_error(FMV)}).
any() ->
fun(In) -> case pears@input:get(In) of
none ->
{error, {parse_error, In, [<<"any"/utf8>>]}};
{some, {Value, Next}} ->
pears:ok(Next, Value)
end end.
-spec eof() -> fun((list(FMY)) -> {ok, pears:parsed(FMY, nil)} |
{error, pears:parse_error(FMY)}).
eof() ->
fun(In) -> case pears@input:at_end(In) of
true ->
pears:ok(In, nil);
false ->
{error, {parse_error, In, [<<"EOF"/utf8>>]}}
end end.
-spec satisfying(fun((FNB) -> boolean())) -> fun((list(FNB)) -> {ok,
pears:parsed(FNB, FNB)} |
{error, pears:parse_error(FNB)}).
satisfying(F) ->
fun(In) -> case pears@input:get(In) of
none ->
{error, {parse_error, In, [<<"satisfying"/utf8>>]}};
{some, {Value, Next}} ->
case F(Value) of
true ->
pears:ok(Next, Value);
false ->
{error, {parse_error, In, [<<"satisfying"/utf8>>]}}
end
end end.
-spec just(FNF) -> fun((list(FNF)) -> {ok, pears:parsed(FNF, FNF)} |
{error, pears:parse_error(FNF)}).
just(Item) ->
fun(Input) -> case Input of
[Head | Next] when Head =:= Item ->
pears:ok(Next, Head);
_ ->
{error, {parse_error, Input, [gleam@string:inspect(Item)]}}
end end.
-spec pair(
fun((list(FNI)) -> {ok, pears:parsed(FNI, FNJ)} |
{error, pears:parse_error(FNI)}),
fun((list(FNI)) -> {ok, pears:parsed(FNI, FNM)} |
{error, pears:parse_error(FNI)})
) -> fun((list(FNI)) -> {ok, pears:parsed(FNI, {FNJ, FNM})} |
{error, pears:parse_error(FNI)}).
pair(P1, P2) ->
fun(In) ->
gleam@result:'try'(
P1(In),
fun(Parsed_1) ->
gleam@result:'try'(
P2(erlang:element(2, Parsed_1)),
fun(Parsed_2) ->
pears:ok(
erlang:element(2, Parsed_2),
{erlang:element(3, Parsed_1),
erlang:element(3, Parsed_2)}
)
end
)
end
)
end.
-spec do_sequence(
list(fun((list(FNZ)) -> {ok, pears:parsed(FNZ, FOA)} |
{error, pears:parse_error(FNZ)})),
list(FNZ),
list(FOA)
) -> {ok, pears:parsed(FNZ, list(FOA))} | {error, pears:parse_error(FNZ)}.
do_sequence(Parsers, Input, Acc) ->
case Parsers of
[] ->
pears:ok(Input, gleam@list:reverse(Acc));
[Parser | Rest] ->
gleam@result:'try'(
Parser(Input),
fun(Parsed) ->
do_sequence(
Rest,
erlang:element(2, Parsed),
[erlang:element(3, Parsed) | Acc]
)
end
)
end.
-spec seq(
list(fun((list(FNR)) -> {ok, pears:parsed(FNR, FNS)} |
{error, pears:parse_error(FNR)}))
) -> fun((list(FNR)) -> {ok, pears:parsed(FNR, list(FNS))} |
{error, pears:parse_error(FNR)}).
seq(Parsers) ->
fun(Input) -> do_sequence(Parsers, Input, []) end.
-spec left(
fun((list(FOJ)) -> {ok, pears:parsed(FOJ, FOK)} |
{error, pears:parse_error(FOJ)}),
fun((list(FOJ)) -> {ok, pears:parsed(FOJ, any())} |
{error, pears:parse_error(FOJ)})
) -> fun((list(FOJ)) -> {ok, pears:parsed(FOJ, FOK)} |
{error, pears:parse_error(FOJ)}).
left(P1, P2) ->
fun(In) ->
gleam@result:'try'(
P1(In),
fun(Parsed_1) ->
gleam@result:'try'(
P2(erlang:element(2, Parsed_1)),
fun(Parsed_2) ->
pears:ok(
erlang:element(2, Parsed_2),
erlang:element(3, Parsed_1)
)
end
)
end
)
end.
-spec right(
fun((list(FOS)) -> {ok, pears:parsed(FOS, any())} |
{error, pears:parse_error(FOS)}),
fun((list(FOS)) -> {ok, pears:parsed(FOS, FOW)} |
{error, pears:parse_error(FOS)})
) -> fun((list(FOS)) -> {ok, pears:parsed(FOS, FOW)} |
{error, pears:parse_error(FOS)}).
right(P1, P2) ->
fun(In) ->
gleam@result:'try'(
P1(In),
fun(Parsed_1) ->
gleam@result:'try'(
P2(erlang:element(2, Parsed_1)),
fun(Parsed_2) ->
pears:ok(
erlang:element(2, Parsed_2),
erlang:element(3, Parsed_2)
)
end
)
end
)
end.
-spec many0(
fun((list(FPB)) -> {ok, pears:parsed(FPB, FPC)} |
{error, pears:parse_error(FPB)})
) -> fun((list(FPB)) -> {ok, pears:parsed(FPB, list(FPC))} |
{error, pears:parse_error(FPB)}).
many0(Parser) ->
fun(In) -> case Parser(In) of
{ok, Parsed} ->
gleam@result:'try'(
(many0(Parser))(erlang:element(2, Parsed)),
fun(Next) ->
pears:ok(
erlang:element(2, Next),
[erlang:element(3, Parsed) |
erlang:element(3, Next)]
)
end
);
{error, _} ->
pears:ok(In, [])
end end.
-spec many1(
fun((list(FPI)) -> {ok, pears:parsed(FPI, FPJ)} |
{error, pears:parse_error(FPI)})
) -> fun((list(FPI)) -> {ok, pears:parsed(FPI, list(FPJ))} |
{error, pears:parse_error(FPI)}).
many1(Parser) ->
fun(In) ->
gleam@result:'try'(
Parser(In),
fun(Parsed) ->
gleam@result:'try'(
(many0(Parser))(erlang:element(2, Parsed)),
fun(Rest) ->
pears:ok(
erlang:element(2, Rest),
[erlang:element(3, Parsed) |
erlang:element(3, Rest)]
)
end
)
end
)
end.
-spec lazy(
fun(() -> fun((list(FPP)) -> {ok, pears:parsed(FPP, FPQ)} |
{error, pears:parse_error(FPP)}))
) -> fun((list(FPP)) -> {ok, pears:parsed(FPP, FPQ)} |
{error, pears:parse_error(FPP)}).
lazy(F) ->
fun(Input) -> (F())(Input) end.
-spec one_of(list(FPV)) -> fun((list(FPV)) -> {ok, pears:parsed(FPV, FPV)} |
{error, pears:parse_error(FPV)}).
one_of(Items) ->
satisfying(fun(C) -> gleam@list:contains(Items, C) end).
-spec none_of(list(FPZ)) -> fun((list(FPZ)) -> {ok, pears:parsed(FPZ, FPZ)} |
{error, pears:parse_error(FPZ)}).
none_of(Items) ->
satisfying(fun(C) -> not gleam@list:contains(Items, C) end).
-spec between(
fun((list(FQD)) -> {ok, pears:parsed(FQD, FQE)} |
{error, pears:parse_error(FQD)}),
fun((list(FQD)) -> {ok, pears:parsed(FQD, any())} |
{error, pears:parse_error(FQD)}),
fun((list(FQD)) -> {ok, pears:parsed(FQD, any())} |
{error, pears:parse_error(FQD)})
) -> fun((list(FQD)) -> {ok, pears:parsed(FQD, FQE)} |
{error, pears:parse_error(FQD)}).
between(Parser, Open, Close) ->
_pipe = Open,
_pipe@1 = right(_pipe, Parser),
left(_pipe@1, Close).
-spec choice(
list(fun((list(FQP)) -> {ok, pears:parsed(FQP, FQQ)} |
{error, pears:parse_error(FQP)}))
) -> fun((list(FQP)) -> {ok, pears:parsed(FQP, FQQ)} |
{error, pears:parse_error(FQP)}).
choice(Parsers) ->
fun(Input) -> case Parsers of
[] ->
{error, {parse_error, Input, [<<"choice"/utf8>>]}};
[Parser | Rest] ->
case Parser(Input) of
{ok, Parsed} ->
{ok, Parsed};
{error, _} ->
(choice(Rest))(Input)
end
end end.
-spec sep_by0(
fun((list(FQW)) -> {ok, pears:parsed(FQW, FQX)} |
{error, pears:parse_error(FQW)}),
fun((list(FQW)) -> {ok, pears:parsed(FQW, any())} |
{error, pears:parse_error(FQW)})
) -> fun((list(FQW)) -> {ok, pears:parsed(FQW, list(FQX))} |
{error, pears:parse_error(FQW)}).
sep_by0(Parser, Separator) ->
fun(In) -> case Parser(In) of
{ok, Parsed} ->
gleam@result:'try'(
(many0(right(Separator, Parser)))(erlang:element(2, Parsed)),
fun(Rest) ->
pears:ok(
erlang:element(2, Rest),
[erlang:element(3, Parsed) |
erlang:element(3, Rest)]
)
end
);
{error, _} ->
pears:ok(In, [])
end end.
-spec sep_by1(
fun((list(FRG)) -> {ok, pears:parsed(FRG, FRH)} |
{error, pears:parse_error(FRG)}),
fun((list(FRG)) -> {ok, pears:parsed(FRG, any())} |
{error, pears:parse_error(FRG)})
) -> fun((list(FRG)) -> {ok, pears:parsed(FRG, list(FRH))} |
{error, pears:parse_error(FRG)}).
sep_by1(Parser, Separator) ->
fun(Input) ->
gleam@result:'try'(
Parser(Input),
fun(Parsed) ->
gleam@result:'try'(
(many0(
begin
_pipe = Separator,
right(_pipe, Parser)
end
))(erlang:element(2, Parsed)),
fun(Rest) ->
pears:ok(
erlang:element(2, Rest),
[erlang:element(3, Parsed) |
erlang:element(3, Rest)]
)
end
)
end
)
end.
-spec maybe(
fun((list(FRQ)) -> {ok, pears:parsed(FRQ, FRR)} |
{error, pears:parse_error(FRQ)})
) -> fun((list(FRQ)) -> {ok, pears:parsed(FRQ, gleam@option:option(FRR))} |
{error, pears:parse_error(FRQ)}).
maybe(Parser) ->
fun(In) -> case Parser(In) of
{ok, Parsed} ->
pears:ok(
erlang:element(2, Parsed),
{some, erlang:element(3, Parsed)}
);
{error, _} ->
pears:ok(In, none)
end end.
-spec unwrap(
fun((list(FRX)) -> {ok, pears:parsed(FRX, gleam@option:option(FRY))} |
{error, pears:parse_error(FRX)}),
FRY
) -> fun((list(FRX)) -> {ok, pears:parsed(FRX, FRY)} |
{error, pears:parse_error(FRX)}).
unwrap(Parser, Default) ->
_pipe = Parser,
map(_pipe, fun(Maybe_value) -> case Maybe_value of
none ->
Default;
{some, Value} ->
Value
end end).
-spec recognize(
fun((list(FSE)) -> {ok, pears:parsed(FSE, any())} |
{error, pears:parse_error(FSE)})
) -> fun((list(FSE)) -> {ok, pears:parsed(FSE, list(FSE))} |
{error, pears:parse_error(FSE)}).
recognize(Parser) ->
fun(In) ->
gleam@result:'try'(
Parser(In),
fun(Parsed) ->
Original_length = gleam@list:length(In),
Parsed_length = gleam@list:length(erlang:element(2, Parsed)),
Consumed = gleam@list:take(In, Original_length - Parsed_length),
pears:ok(erlang:element(2, Parsed), Consumed)
end
)
end.