-module(rexen@nfa@machine). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). -export([new/0, set_initial_state/2, set_ending_states/2, add_state/2, declare_states/2, add_transition/4, evaluate/2]). -export_type([nfa/0, stack_value/0]). -type nfa() :: {nfa, gleam@dict:dict(binary(), rexen@nfa@state:state()), binary(), list(binary())}. -type stack_value() :: {stack_value, integer(), rexen@nfa@state:state()}. -file("src/rexen/nfa/machine.gleam", 14). -spec new() -> nfa(). new() -> {nfa, maps:new(), <<""/utf8>>, []}. -file("src/rexen/nfa/machine.gleam", 18). -spec set_initial_state(nfa(), binary()) -> nfa(). set_initial_state(Nfa, State) -> {nfa, erlang:element(2, Nfa), State, erlang:element(4, Nfa)}. -file("src/rexen/nfa/machine.gleam", 26). -spec set_ending_states(nfa(), list(binary())) -> nfa(). set_ending_states(Nfa, Values) -> {nfa, erlang:element(2, Nfa), erlang:element(3, Nfa), Values}. -file("src/rexen/nfa/machine.gleam", 34). -spec add_state(nfa(), binary()) -> nfa(). add_state(Nfa, Name) -> {nfa, gleam@dict:insert( erlang:element(2, Nfa), Name, rexen@nfa@state:new(Name) ), erlang:element(3, Nfa), erlang:element(4, Nfa)}. -file("src/rexen/nfa/machine.gleam", 42). -spec declare_states(nfa(), list(binary())) -> nfa(). declare_states(Nfa, Names) -> case Names of [] -> Nfa; [Name | Rest] -> declare_states(add_state(Nfa, Name), Rest) end. -file("src/rexen/nfa/machine.gleam", 49). -spec add_transition(nfa(), binary(), binary(), rexen@nfa@state:matcher()) -> nfa(). add_transition(Nfa, From, To, Matcher) -> _assert_subject = gleam_stdlib:map_get(erlang:element(2, Nfa), From), {ok, From_state} = case _assert_subject of {ok, _} -> _assert_subject; _assert_fail -> erlang:error(#{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, value => _assert_fail, module => <<"rexen/nfa/machine"/utf8>>, function => <<"add_transition"/utf8>>, line => 55}) end, _assert_subject@1 = gleam_stdlib:map_get(erlang:element(2, Nfa), To), {ok, _} = case _assert_subject@1 of {ok, _} -> _assert_subject@1; _assert_fail@1 -> erlang:error(#{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, value => _assert_fail@1, module => <<"rexen/nfa/machine"/utf8>>, function => <<"add_transition"/utf8>>, line => 56}) end, Transitions = rexen@nfa@state:add_transition( erlang:element(3, From_state), {Matcher, To} ), New_state = {state, erlang:element(2, From_state), Transitions}, {nfa, gleam@dict:insert(erlang:element(2, Nfa), From, New_state), erlang:element(3, Nfa), erlang:element(4, Nfa)}. -file("src/rexen/nfa/machine.gleam", 110). -spec process_transitions( nfa(), list({rexen@nfa@state:matcher(), binary()}), list(stack_value()), stack_value(), binary() ) -> list(stack_value()). process_transitions(Nfa, Transitions, Stack, Stkv, Char) -> case Transitions of [] -> Stack; [{Matcher, Name} | Rest] -> case rexen@nfa@state:matches(Matcher, Char) of false -> process_transitions(Nfa, Rest, Stack, Stkv, Char); true -> Index = case rexen@nfa@state:is_epsilon(Matcher) of true -> erlang:element(2, Stkv); false -> erlang:element(2, Stkv) + 1 end, _assert_subject = gleam_stdlib:map_get( erlang:element(2, Nfa), Name ), {ok, To} = case _assert_subject of {ok, _} -> _assert_subject; _assert_fail -> erlang:error(#{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, value => _assert_fail, module => <<"rexen/nfa/machine"/utf8>>, function => <<"process_transitions"/utf8>>, line => 129}) end, New_stack = lists:append(Stack, [{stack_value, Index, To}]), process_transitions(Nfa, Rest, New_stack, Stkv, Char) end end. -file("src/rexen/nfa/machine.gleam", 78). -spec evaluate_loop(nfa(), binary(), list(stack_value())) -> boolean(). evaluate_loop(Nfa, Input, Stack) -> case Stack of [] -> false; [Value | Rest] -> case gleam@list:contains( erlang:element(4, Nfa), erlang:element(2, erlang:element(3, Value)) ) of true -> case string:length(Input) =:= erlang:element(2, Value) of true -> true; false -> Char = gleam@string:slice( Input, erlang:element(2, Value), 1 ), New_stack = process_transitions( Nfa, erlang:element(3, erlang:element(3, Value)), Rest, Value, Char ), evaluate_loop(Nfa, Input, New_stack) end; false -> Char@1 = gleam@string:slice( Input, erlang:element(2, Value), 1 ), New_stack@1 = process_transitions( Nfa, erlang:element(3, erlang:element(3, Value)), Rest, Value, Char@1 ), evaluate_loop(Nfa, Input, New_stack@1) end end. -file("src/rexen/nfa/machine.gleam", 72). -spec evaluate(nfa(), binary()) -> boolean(). evaluate(Nfa, Input) -> _assert_subject = gleam_stdlib:map_get( erlang:element(2, Nfa), erlang:element(3, Nfa) ), {ok, S} = case _assert_subject of {ok, _} -> _assert_subject; _assert_fail -> erlang:error(#{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, value => _assert_fail, module => <<"rexen/nfa/machine"/utf8>>, function => <<"evaluate"/utf8>>, line => 73}) end, Stack = [{stack_value, 0, S}], evaluate_loop(Nfa, Input, Stack).