-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.