defmodule Rollex do # NOTE: Order Matters! If an item matches in Rollex.Lexer._do_tokenize/0, the lexer will skip the rest of the tokens # This is why number is after dice tokens, since number will very frequently match on what should be dice input @default_operations [%Rollex.Tokens.Subtraction{}, %Rollex.Tokens.Addition{}, %Rollex.Tokens.Number{}, %Rollex.Tokens.LeftParenthesis{}, %Rollex.Tokens.RightParenthesis{}] @default_dice [%Rollex.Tokens.ParanoiaDice{}, %Rollex.Tokens.FudgeDice{}, %Rollex.Tokens.RegularDice{}] # Use built-in defaults def roll(roll_expr, dice \\ @default_dice) def roll(roll_expr, dice) do roll_expr |> Rollex.Lexer.tokenize(dice ++ @default_operations) |> Rollex.Validator.validate |> Rollex.Evaluator.evaluate |> _build_final_output end defp _build_final_output({:ok, %{} = result, full_tokenized_input}) do %{status: :ok, totals: result, tokenized_input: full_tokenized_input} end defp _build_final_output({:error, msg}) when is_binary(msg) do %{status: :error, error_msg: msg} end end