Current section
Files
Jump to
Current section
Files
src/pears@combinators.erl
-module(pears@combinators).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]).
-export([map/2, map_error/2, labelled/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, do_choice/2, choice/1, sep_by0/2, sep_by1/2, 'maybe'/1, unwrap/2, recognize/1]).
-spec consume_token(
pears@input:input(FZQ),
fun((FZQ) -> {ok, pears:parsed(FZQ, FZS)} | {error, pears:parse_error(FZQ)})
) -> {ok, pears:parsed(FZQ, FZS)} | {error, pears:parse_error(FZQ)}.
consume_token(In, F) ->
case pears@input:get(In) of
none ->
{error, {unexpected_end_of_input, In, [<<"any token"/utf8>>]}};
{some, Value} ->
F(Value)
end.
-spec map(
fun((pears@input:input(FZX)) -> {ok, pears:parsed(FZX, FZY)} |
{error, pears:parse_error(FZX)}),
fun((FZY) -> GAB)
) -> fun((pears@input:input(FZX)) -> {ok, pears:parsed(FZX, GAB)} |
{error, pears:parse_error(FZX)}).
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 map_error(
fun((pears@input:input(GAE)) -> {ok, pears:parsed(GAE, GAF)} |
{error, pears:parse_error(GAE)}),
fun((pears:parse_error(GAE)) -> pears:parse_error(GAE))
) -> fun((pears@input:input(GAE)) -> {ok, pears:parsed(GAE, GAF)} |
{error, pears:parse_error(GAE)}).
map_error(P, Fun) ->
fun(Input) -> _pipe = P(Input),
gleam@result:map_error(_pipe, Fun) end.
-spec labelled(
fun((pears@input:input(GAM)) -> {ok, pears:parsed(GAM, GAN)} |
{error, pears:parse_error(GAM)}),
binary()
) -> fun((pears@input:input(GAM)) -> {ok, pears:parsed(GAM, GAN)} |
{error, pears:parse_error(GAM)}).
labelled(Parser, Label) ->
fun(Input) -> _pipe = Parser(Input),
gleam@result:map_error(_pipe, fun(Err) -> case Err of
{unexpected_end_of_input, _, _} ->
Err;
{unexpected_token, In, _, Error} ->
{unexpected_token, In, [Label], Error}
end end) end.
-spec to(
fun((pears@input:input(GAS)) -> {ok, pears:parsed(GAS, any())} |
{error, pears:parse_error(GAS)}),
GAW
) -> fun((pears@input:input(GAS)) -> {ok, pears:parsed(GAS, GAW)} |
{error, pears:parse_error(GAS)}).
to(Parser, Value) ->
map(Parser, fun(_) -> Value end).
-spec alt(
fun((pears@input:input(GAZ)) -> {ok, pears:parsed(GAZ, GBA)} |
{error, pears:parse_error(GAZ)}),
fun((pears@input:input(GAZ)) -> {ok, pears:parsed(GAZ, GBA)} |
{error, pears:parse_error(GAZ)})
) -> fun((pears@input:input(GAZ)) -> {ok, pears:parsed(GAZ, GBA)} |
{error, pears:parse_error(GAZ)}).
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((pears@input:input(GBH)) -> {ok, pears:parsed(GBH, GBH)} |
{error, pears:parse_error(GBH)}).
any() ->
fun(In) ->
consume_token(
In,
fun(Token) -> pears:ok(pears@input:next(In), Token) end
)
end.
-spec eof() -> fun((pears@input:input(GBK)) -> {ok, pears:parsed(GBK, nil)} |
{error, pears:parse_error(GBK)}).
eof() ->
fun(In) -> case pears@input:get(In) of
none ->
pears:ok(In, nil);
{some, Token} ->
{error, {unexpected_token, In, [<<"EOF"/utf8>>], Token}}
end end.
-spec satisfying(fun((GBN) -> boolean())) -> fun((pears@input:input(GBN)) -> {ok,
pears:parsed(GBN, GBN)} |
{error, pears:parse_error(GBN)}).
satisfying(F) ->
fun(In) -> case pears@input:get(In) of
none ->
{error,
{unexpected_end_of_input,
In,
[<<"satifying predicate"/utf8>>]}};
{some, Value} ->
case F(Value) of
true ->
pears:ok(pears@input:next(In), Value);
false ->
{error,
{unexpected_token,
In,
[<<"satisfying predicate"/utf8>>],
Value}}
end
end end.
-spec just(GBR) -> fun((pears@input:input(GBR)) -> {ok, pears:parsed(GBR, GBR)} |
{error, pears:parse_error(GBR)}).
just(Item) ->
fun(In) -> case pears@input:get(In) of
none ->
{error,
{unexpected_end_of_input, In, [gleam@string:inspect(Item)]}};
{some, Head} when Head =:= Item ->
{ok, {parsed, pears@input:next(In), Item}};
{some, Head@1} ->
{error,
{unexpected_token, In, [gleam@string:inspect(Item)], Head@1}}
end end.
-spec pair(
fun((pears@input:input(GBU)) -> {ok, pears:parsed(GBU, GBV)} |
{error, pears:parse_error(GBU)}),
fun((pears@input:input(GBU)) -> {ok, pears:parsed(GBU, GBY)} |
{error, pears:parse_error(GBU)})
) -> fun((pears@input:input(GBU)) -> {ok, pears:parsed(GBU, {GBV, GBY})} |
{error, pears:parse_error(GBU)}).
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((pears@input:input(GCL)) -> {ok, pears:parsed(GCL, GCM)} |
{error, pears:parse_error(GCL)})),
pears@input:input(GCL),
list(GCM)
) -> {ok, pears:parsed(GCL, list(GCM))} | {error, pears:parse_error(GCL)}.
do_sequence(Parsers, Input, Acc) ->
case Parsers of
[] ->
pears:ok(Input, lists: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((pears@input:input(GCD)) -> {ok, pears:parsed(GCD, GCE)} |
{error, pears:parse_error(GCD)}))
) -> fun((pears@input:input(GCD)) -> {ok, pears:parsed(GCD, list(GCE))} |
{error, pears:parse_error(GCD)}).
seq(Parsers) ->
fun(Input) -> do_sequence(Parsers, Input, []) end.
-spec left(
fun((pears@input:input(GCV)) -> {ok, pears:parsed(GCV, GCW)} |
{error, pears:parse_error(GCV)}),
fun((pears@input:input(GCV)) -> {ok, pears:parsed(GCV, any())} |
{error, pears:parse_error(GCV)})
) -> fun((pears@input:input(GCV)) -> {ok, pears:parsed(GCV, GCW)} |
{error, pears:parse_error(GCV)}).
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((pears@input:input(GDE)) -> {ok, pears:parsed(GDE, any())} |
{error, pears:parse_error(GDE)}),
fun((pears@input:input(GDE)) -> {ok, pears:parsed(GDE, GDI)} |
{error, pears:parse_error(GDE)})
) -> fun((pears@input:input(GDE)) -> {ok, pears:parsed(GDE, GDI)} |
{error, pears:parse_error(GDE)}).
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((pears@input:input(GDN)) -> {ok, pears:parsed(GDN, GDO)} |
{error, pears:parse_error(GDN)})
) -> fun((pears@input:input(GDN)) -> {ok, pears:parsed(GDN, list(GDO))} |
{error, pears:parse_error(GDN)}).
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((pears@input:input(GDU)) -> {ok, pears:parsed(GDU, GDV)} |
{error, pears:parse_error(GDU)})
) -> fun((pears@input:input(GDU)) -> {ok, pears:parsed(GDU, list(GDV))} |
{error, pears:parse_error(GDU)}).
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((pears@input:input(GEB)) -> {ok, pears:parsed(GEB, GEC)} |
{error, pears:parse_error(GEB)}))
) -> fun((pears@input:input(GEB)) -> {ok, pears:parsed(GEB, GEC)} |
{error, pears:parse_error(GEB)}).
lazy(F) ->
fun(Input) -> (F())(Input) end.
-spec one_of(list(GEH)) -> fun((pears@input:input(GEH)) -> {ok,
pears:parsed(GEH, GEH)} |
{error, pears:parse_error(GEH)}).
one_of(Items) ->
_pipe = satisfying(fun(C) -> gleam@list:contains(Items, C) end),
map_error(
_pipe,
fun(Err) ->
Expected = gleam@list:map(Items, fun gleam@string:inspect/1),
case Err of
{unexpected_token, In, _, Token} ->
{unexpected_token, In, Expected, Token};
{unexpected_end_of_input, In@1, _} ->
{unexpected_end_of_input, In@1, Expected}
end
end
).
-spec none_of(list(GEL)) -> fun((pears@input:input(GEL)) -> {ok,
pears:parsed(GEL, GEL)} |
{error, pears:parse_error(GEL)}).
none_of(Items) ->
satisfying(fun(C) -> not gleam@list:contains(Items, C) end).
-spec between(
fun((pears@input:input(GEP)) -> {ok, pears:parsed(GEP, GEQ)} |
{error, pears:parse_error(GEP)}),
fun((pears@input:input(GEP)) -> {ok, pears:parsed(GEP, any())} |
{error, pears:parse_error(GEP)}),
fun((pears@input:input(GEP)) -> {ok, pears:parsed(GEP, any())} |
{error, pears:parse_error(GEP)})
) -> fun((pears@input:input(GEP)) -> {ok, pears:parsed(GEP, GEQ)} |
{error, pears:parse_error(GEP)}).
between(Parser, Open, Close) ->
_pipe = Open,
_pipe@1 = right(_pipe, Parser),
left(_pipe@1, Close).
-spec do_choice(
list(fun((pears@input:input(GFI)) -> {ok, pears:parsed(GFI, GFJ)} |
{error, pears:parse_error(GFI)})),
list(binary())
) -> fun((pears@input:input(GFI)) -> {ok, pears:parsed(GFI, GFJ)} |
{error, pears:parse_error(GFI)}).
do_choice(Parsers, Expected) ->
fun(In) -> case Parsers of
[] ->
case pears@input:get(In) of
none ->
{error, {unexpected_end_of_input, In, Expected}};
{some, Token} ->
{error, {unexpected_token, In, Expected, Token}}
end;
[Parser | Rest] ->
case Parser(In) of
{ok, Parsed} ->
{ok, Parsed};
{error, Err} ->
New_expected = case Err of
{unexpected_token, _, Expected@1, _} ->
Expected@1;
{unexpected_end_of_input, _, Expected@2} ->
Expected@2
end,
(do_choice(
Rest,
gleam@list:concat([Expected, New_expected])
))(In)
end
end end.
-spec choice(
list(fun((pears@input:input(GFB)) -> {ok, pears:parsed(GFB, GFC)} |
{error, pears:parse_error(GFB)}))
) -> fun((pears@input:input(GFB)) -> {ok, pears:parsed(GFB, GFC)} |
{error, pears:parse_error(GFB)}).
choice(Parsers) ->
do_choice(Parsers, []).
-spec sep_by0(
fun((pears@input:input(GFQ)) -> {ok, pears:parsed(GFQ, GFR)} |
{error, pears:parse_error(GFQ)}),
fun((pears@input:input(GFQ)) -> {ok, pears:parsed(GFQ, any())} |
{error, pears:parse_error(GFQ)})
) -> fun((pears@input:input(GFQ)) -> {ok, pears:parsed(GFQ, list(GFR))} |
{error, pears:parse_error(GFQ)}).
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((pears@input:input(GGA)) -> {ok, pears:parsed(GGA, GGB)} |
{error, pears:parse_error(GGA)}),
fun((pears@input:input(GGA)) -> {ok, pears:parsed(GGA, any())} |
{error, pears:parse_error(GGA)})
) -> fun((pears@input:input(GGA)) -> {ok, pears:parsed(GGA, list(GGB))} |
{error, pears:parse_error(GGA)}).
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((pears@input:input(GGK)) -> {ok, pears:parsed(GGK, GGL)} |
{error, pears:parse_error(GGK)})
) -> fun((pears@input:input(GGK)) -> {ok,
pears:parsed(GGK, gleam@option:option(GGL))} |
{error, pears:parse_error(GGK)}).
'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((pears@input:input(GGR)) -> {ok,
pears:parsed(GGR, gleam@option:option(GGS))} |
{error, pears:parse_error(GGR)}),
GGS
) -> fun((pears@input:input(GGR)) -> {ok, pears:parsed(GGR, GGS)} |
{error, pears:parse_error(GGR)}).
unwrap(Parser, Default) ->
_pipe = Parser,
map(_pipe, fun(Maybe_value) -> case Maybe_value of
none ->
Default;
{some, Value} ->
Value
end end).
-spec recognize(
fun((pears@input:input(GGY)) -> {ok, pears:parsed(GGY, any())} |
{error, pears:parse_error(GGY)})
) -> fun((pears@input:input(GGY)) -> {ok, pears:parsed(GGY, list(GGY))} |
{error, pears:parse_error(GGY)}).
recognize(Parser) ->
fun(In) ->
gleam@result:'try'(
Parser(In),
fun(Parsed) ->
Start = erlang:element(3, In),
Parsed_length = erlang:element(3, erlang:element(2, Parsed)) - Start,
Consumed = begin
_pipe = erlang:element(2, In),
_pipe@1 = gleam@list:drop(_pipe, Start),
gleam@list:take(_pipe@1, Parsed_length)
end,
pears:ok(erlang:element(2, Parsed), Consumed)
end
)
end.