Current section
Files
Jump to
Current section
Files
src/diced.erl
-module(diced).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]).
-export([parse/1]).
-export_type([modifier/0, dice/0, dice_error/0]).
-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.
-type modifier() :: {keep_highest, integer()} |
{keep_lowest, integer()} |
{drop_highest, integer()} |
{drop_lowest, integer()} |
{reroll, integer()} |
{recursive_reroll, integer()} |
{explode, integer()} |
{minimum, integer()} |
{maximum, integer()}.
-type dice() :: {basic, integer(), integer(), list(modifier())} |
{fate, integer(), list(modifier())} |
{number, integer(), list(modifier())}.
-type dice_error() :: invalid_amount |
invalid_string |
invalid_value |
invalid_modifier.
-file("src/diced.gleam", 96).
-spec parse_amount(binary()) -> {ok, integer()} | {error, dice_error()}.
parse_amount(Amount) ->
_pipe = gleam_stdlib:parse_int(Amount),
gleam@result:replace_error(_pipe, invalid_amount).
-file("src/diced.gleam", 148).
-spec do_with_modifier_value(binary(), integer()) -> {binary(), integer()}.
do_with_modifier_value(String, Value) ->
case String of
<<"0"/utf8, Rest/binary>> ->
do_with_modifier_value(Rest, Value * 10);
<<"1"/utf8, Rest@1/binary>> ->
do_with_modifier_value(Rest@1, (Value * 10) + 1);
<<"2"/utf8, Rest@2/binary>> ->
do_with_modifier_value(Rest@2, (Value * 10) + 2);
<<"3"/utf8, Rest@3/binary>> ->
do_with_modifier_value(Rest@3, (Value * 10) + 3);
<<"4"/utf8, Rest@4/binary>> ->
do_with_modifier_value(Rest@4, (Value * 10) + 4);
<<"5"/utf8, Rest@5/binary>> ->
do_with_modifier_value(Rest@5, (Value * 10) + 5);
<<"6"/utf8, Rest@6/binary>> ->
do_with_modifier_value(Rest@6, (Value * 10) + 6);
<<"7"/utf8, Rest@7/binary>> ->
do_with_modifier_value(Rest@7, (Value * 10) + 7);
<<"8"/utf8, Rest@8/binary>> ->
do_with_modifier_value(Rest@8, (Value * 10) + 8);
<<"9"/utf8, Rest@9/binary>> ->
do_with_modifier_value(Rest@9, (Value * 10) + 9);
_ ->
{String, Value}
end.
-file("src/diced.gleam", 141).
-spec with_modifier_value(binary()) -> {binary(), integer()}.
with_modifier_value(String) ->
case do_with_modifier_value(String, 0) of
{A, V} when V =:= 0 ->
{A, 1};
{A@1, V@1} ->
{A@1, V@1}
end.
-file("src/diced.gleam", 101).
-spec parse_value(binary()) -> {ok, {integer(), binary()}} |
{error, dice_error()}.
parse_value(Value) ->
Modifier_splitter = splitter:new(
[<<"kh"/utf8>>,
<<"kl"/utf8>>,
<<"dh"/utf8>>,
<<"dl"/utf8>>,
<<"r"/utf8>>,
<<"R"/utf8>>,
<<"!"/utf8>>,
<<"m"/utf8>>,
<<"M"/utf8>>]
),
{Value@1, A, B} = splitter_ffi:split(Modifier_splitter, Value),
gleam@result:'try'(
gleam@result:replace_error(
gleam_stdlib:parse_int(Value@1),
invalid_value
),
fun(Value@2) -> {ok, {Value@2, <<A/binary, B/binary>>}} end
).
-file("src/diced.gleam", 112).
-spec do_parse_modifiers(
binary(),
{ok, list(modifier())} | {error, dice_error()}
) -> {ok, list(modifier())} | {error, dice_error()}.
do_parse_modifiers(Modifiers, Found) ->
gleam@result:'try'(
Found,
fun(Found@1) ->
Splitter = splitter:new(
[<<"kh"/utf8>>,
<<"kl"/utf8>>,
<<"dh"/utf8>>,
<<"dl"/utf8>>,
<<"r"/utf8>>,
<<"R"/utf8>>,
<<"!"/utf8>>,
<<"m"/utf8>>,
<<"M"/utf8>>]
),
case splitter_ffi:split(Splitter, Modifiers) of
{<<""/utf8>>, <<""/utf8>>, <<""/utf8>>} ->
{ok, lists:reverse(Found@1)};
{<<""/utf8>>, Mod, Rest} ->
{Rest@1, Value} = with_modifier_value(Rest),
Modifier = case Mod of
<<"kh"/utf8>> ->
{keep_highest, Value};
<<"kl"/utf8>> ->
{keep_lowest, Value};
<<"dh"/utf8>> ->
{drop_highest, Value};
<<"dl"/utf8>> ->
{drop_lowest, Value};
<<"r"/utf8>> ->
{reroll, Value};
<<"R"/utf8>> ->
{recursive_reroll, Value};
<<"!"/utf8>> ->
{explode, Value};
<<"m"/utf8>> ->
{minimum, Value};
<<"M"/utf8>> ->
{maximum, Value};
_ ->
erlang:error(#{gleam_error => panic,
message => <<"unreachable"/utf8>>,
module => <<"diced"/utf8>>,
function => <<"do_parse_modifiers"/utf8>>,
line => 133})
end,
do_parse_modifiers(Rest@1, {ok, [Modifier | Found@1]});
_ ->
{error, invalid_modifier}
end
end
).
-file("src/diced.gleam", 108).
-spec parse_modifiers(binary()) -> {ok, list(modifier())} |
{error, dice_error()}.
parse_modifiers(Modifiers) ->
do_parse_modifiers(Modifiers, {ok, []}).
-file("src/diced.gleam", 62).
?DOC(
" Convert a string containing algebraic dice notation into a type describing how the dice should behave when rolled.\n"
"\n"
" ```gleam\n"
" diced.parse(\"2d20kh\")\n"
" // Ok(diced.Basic(2, 20, [KeepHighest(1)]))\n"
" ```\n"
).
-spec parse(binary()) -> {ok, dice()} | {error, dice_error()}.
parse(String) ->
Dice_splitter = splitter:new([<<"d"/utf8>>, <<"dF"/utf8>>]),
case splitter_ffi:split(Dice_splitter, String) of
{Value, <<""/utf8>>, Mods} ->
gleam@result:'try'(
begin
_pipe = gleam_stdlib:parse_int(Value),
gleam@result:replace_error(_pipe, invalid_value)
end,
fun(Value@1) ->
gleam@result:'try'(
parse_modifiers(Mods),
fun(Modifiers) -> {ok, {number, Value@1, Modifiers}} end
)
end
);
{Amount, <<"d"/utf8>>, <<""/utf8>>} ->
gleam@result:'try'(
parse_amount(Amount),
fun(Amount@1) -> {ok, {basic, Amount@1, 6, []}} end
);
{<<""/utf8>>, <<"d"/utf8>>, Mods@1} ->
gleam@result:'try'(
parse_value(Mods@1),
fun(_use0) ->
{Value@2, Rest} = _use0,
gleam@result:'try'(
parse_modifiers(Rest),
fun(Modifiers@1) ->
{ok, {basic, 1, Value@2, Modifiers@1}}
end
)
end
);
{Amount@2, <<"d"/utf8>>, Mods@2} ->
gleam@result:'try'(
parse_amount(Amount@2),
fun(Amount@3) ->
gleam@result:'try'(
parse_value(Mods@2),
fun(_use0@1) ->
{Value@3, Rest@1} = _use0@1,
gleam@result:'try'(
parse_modifiers(Rest@1),
fun(Modifiers@2) ->
{ok,
{basic, Amount@3, Value@3, Modifiers@2}}
end
)
end
)
end
);
{Amount@4, <<"dF"/utf8>>, Mods@3} ->
gleam@result:'try'(
parse_amount(Amount@4),
fun(Amount@5) ->
gleam@result:'try'(
parse_modifiers(Mods@3),
fun(Modifiers@3) ->
{ok, {fate, Amount@5, Modifiers@3}}
end
)
end
);
{_, _, _} ->
{error, invalid_string}
end.