Current section
Files
Jump to
Current section
Files
src/chomp@pratt.erl
-module(chomp@pratt).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]).
-export([sub_expression/2, expression/3, prefix/3, postfix/3, infix_left/3, infix_right/3]).
-export_type([config/4, operator/4]).
-opaque config(IHV, IHW, IHX, IHY) :: {config,
list(fun((config(IHV, IHW, IHX, IHY)) -> chomp:parser(IHV, IHW, IHX, IHY))),
IHW,
list(operator(IHV, IHW, IHX, IHY))}.
-opaque operator(IHZ, IIA, IIB, IIC) :: {operator,
fun((config(IHZ, IIA, IIB, IIC)) -> {integer(),
fun((IHZ) -> chomp:parser(IHZ, IIA, IIB, IIC))})}.
-spec operation(IJL, config(IJL, IJM, IJN, IJO), integer()) -> chomp:parser(IJL, IJM, IJN, IJO).
operation(Expr, Config, Current_precedence) ->
_pipe = erlang:element(4, Config),
_pipe@1 = gleam@list:filter_map(
_pipe,
fun(Operator) ->
{operator, Op} = Operator,
case Op(Config) of
{Precedence, Parser} when Precedence > Current_precedence ->
{ok, Parser(Expr)};
_ ->
{error, nil}
end
end
),
chomp:one_of(_pipe@1).
-spec sub_expression(config(IIZ, IJA, IJB, IJC), integer()) -> chomp:parser(IIZ, IJA, IJB, IJC).
sub_expression(Config, Precedence) ->
Expr = (chomp:lazy(fun() -> _pipe = erlang:element(2, Config),
_pipe@1 = gleam@list:map(_pipe, fun(P) -> P(Config) end),
_pipe@2 = chomp:one_of(_pipe@1),
chomp:or_error(_pipe@2, erlang:element(3, Config)) end)),
Go = fun(Expr@1) ->
chomp:one_of(
[begin
_pipe@3 = operation(Expr@1, Config, Precedence),
chomp:map(_pipe@3, fun(Field@0) -> {continue, Field@0} end)
end,
begin
_pipe@4 = chomp:return(Expr@1),
chomp:map(_pipe@4, fun(Field@0) -> {break, Field@0} end)
end]
)
end,
chomp:do(Expr, fun(E) -> chomp:loop(E, Go) end).
-spec expression(
list(fun((config(IID, IIE, IIF, IIG)) -> chomp:parser(IID, IIE, IIF, IIG))),
IIE,
list(operator(IID, IIE, IIF, IIG))
) -> chomp:parser(IID, IIE, IIF, IIG).
expression(First, Or_error, Then) ->
Config = {config, First, Or_error, Then},
sub_expression(Config, 0).
-spec prefix(integer(), chomp:parser(any(), IJY, IJZ, IKA), fun((IKF) -> IKF)) -> fun((config(IKF, IJY, IJZ, IKA)) -> chomp:parser(IKF, IJY, IJZ, IKA)).
prefix(Precedence, Operator, Apply) ->
fun(Config) ->
chomp:do(
Operator,
fun(_) ->
chomp:do(
sub_expression(Config, Precedence),
fun(Subexpr) -> chomp:return(Apply(Subexpr)) end
)
end
)
end.
-spec postfix(integer(), chomp:parser(any(), ILP, ILQ, ILR), fun((ILW) -> ILW)) -> operator(ILW, ILP, ILQ, ILR).
postfix(Precedence, Operator, Apply) ->
{operator,
fun(_) ->
{Precedence,
fun(Lhs) ->
chomp:do(Operator, fun(_) -> chomp:return(Apply(Lhs)) end)
end}
end}.
-spec make_infix(
{integer(), integer()},
chomp:parser(any(), IMC, IMD, IME),
fun((IMJ, IMJ) -> IMJ)
) -> operator(IMJ, IMC, IMD, IME).
make_infix(Precedence, Operator, Apply) ->
{Left_precedence, Right_precedence} = Precedence,
{operator,
fun(Config) ->
{Left_precedence,
fun(Lhs) ->
chomp:do(
Operator,
fun(_) ->
chomp:do(
sub_expression(Config, Right_precedence),
fun(Subexpr) ->
chomp:return(Apply(Lhs, Subexpr))
end
)
end
)
end}
end}.
-spec infix_left(
integer(),
chomp:parser(any(), IKP, IKQ, IKR),
fun((IKW, IKW) -> IKW)
) -> operator(IKW, IKP, IKQ, IKR).
infix_left(Precedence, Operator, Apply) ->
make_infix({Precedence, Precedence}, Operator, Apply).
-spec infix_right(
integer(),
chomp:parser(any(), ILC, ILD, ILE),
fun((ILJ, ILJ) -> ILJ)
) -> operator(ILJ, ILC, ILD, ILE).
infix_right(Precedence, Operator, Apply) ->
make_infix({Precedence, Precedence - 1}, Operator, Apply).