-module(rexen@grammar). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). -export([to_string/2, shunt/1]). -export_type([operator_variant/1, token/0]). -type operator_variant(EZK) :: o_paren | {asterix, EZK} | {plus, EZK} | {q_mark, EZK}. -type token() :: c_paren | {letter, binary()} | {operator, operator_variant(integer())}. -file("src/rexen/grammar.gleam", 17). -spec tokenize(list(binary()), list(token())) -> list(token()). tokenize(Input, Tokens) -> case Input of [] -> Tokens; [Char | Rest] -> Tok = case Char of <<"*"/utf8>> -> {operator, {asterix, 3}}; <<"?"/utf8>> -> {operator, {q_mark, 2}}; <<"+"/utf8>> -> {operator, {plus, 1}}; <<"("/utf8>> -> {operator, o_paren}; <<")"/utf8>> -> c_paren; _ -> {letter, Char} end, tokenize(Rest, lists:append(Tokens, [Tok])) end. -file("src/rexen/grammar.gleam", 34). -spec to_string(list(token()), binary()) -> binary(). to_string(Tokens, Output) -> case Tokens of [] -> Output; [Tok | Rest] -> case Tok of c_paren -> to_string(Rest, gleam@string:append(Output, <<")"/utf8>>)); {letter, Char} -> to_string(Rest, gleam@string:append(Output, Char)); {operator, Variant} -> case Variant of o_paren -> to_string( Rest, gleam@string:append(Output, <<"("/utf8>>) ); {asterix, _} -> to_string( Rest, gleam@string:append(Output, <<"*"/utf8>>) ); {plus, _} -> to_string( Rest, gleam@string:append(Output, <<"+"/utf8>>) ); {q_mark, _} -> to_string( Rest, gleam@string:append(Output, <<"?"/utf8>>) ) end end end. -file("src/rexen/grammar.gleam", 99). -spec emptystack(list(token()), list(operator_variant(integer()))) -> list(token()). emptystack(Output, Stack) -> case Stack of [] -> Output; [Opvar | Rest] -> O = lists:append(Output, [{operator, Opvar}]), emptystack(O, Rest) end. -file("src/rexen/grammar.gleam", 109). -spec handle_operator( list(token()), list(operator_variant(integer())), operator_variant(integer()), integer() ) -> {list(token()), list(operator_variant(integer()))}. handle_operator(Output, Stack, Variant, Precedence) -> case Stack of [] -> {Output, gleam@list:prepend(Stack, Variant)}; [Opvar | Rest] -> case Opvar of o_paren -> {Output, gleam@list:prepend(Stack, Variant)}; {asterix, P} -> case Precedence > P of true -> {Output, gleam@list:prepend(Stack, Variant)}; false -> O = lists:append(Output, [{operator, Opvar}]), handle_operator(O, Rest, Variant, Precedence) end; {plus, P} -> case Precedence > P of true -> {Output, gleam@list:prepend(Stack, Variant)}; false -> O = lists:append(Output, [{operator, Opvar}]), handle_operator(O, Rest, Variant, Precedence) end; {q_mark, P} -> case Precedence > P of true -> {Output, gleam@list:prepend(Stack, Variant)}; false -> O = lists:append(Output, [{operator, Opvar}]), handle_operator(O, Rest, Variant, Precedence) end end end. -file("src/rexen/grammar.gleam", 139). -spec find_oparen(list(token()), list(operator_variant(integer()))) -> {ok, {list(token()), list(operator_variant(integer()))}} | {error, binary()}. find_oparen(Output, Stack) -> case Stack of [] -> {error, <<"Trailing closing bracket found in the regular expression."/utf8>>}; [Opval | Rest] -> case Opval of o_paren -> {ok, {Output, Rest}}; _ -> Out = lists:append(Output, [{operator, Opval}]), find_oparen(Out, Rest) end end. -file("src/rexen/grammar.gleam", 65). -spec shunt_loop( list(token()), list(token()), list(operator_variant(integer())) ) -> {ok, list(token())} | {error, binary()}. shunt_loop(Input, Output, Stack) -> case Input of [] -> {ok, emptystack(Output, Stack)}; [Tok | Rest] -> case Tok of {letter, _} -> shunt_loop(Rest, lists:append(Output, [Tok]), Stack); c_paren -> case find_oparen(Output, Stack) of {ok, {O, S}} -> shunt_loop(Rest, O, S); {error, Err} -> {error, Err} end; {operator, Opvar} -> case Opvar of o_paren -> shunt_loop( Rest, Output, gleam@list:prepend(Stack, Opvar) ); {asterix, P} -> {O@1, S@1} = handle_operator( Output, Stack, Opvar, P ), shunt_loop(Rest, O@1, S@1); {plus, P} -> {O@1, S@1} = handle_operator( Output, Stack, Opvar, P ), shunt_loop(Rest, O@1, S@1); {q_mark, P} -> {O@1, S@1} = handle_operator( Output, Stack, Opvar, P ), shunt_loop(Rest, O@1, S@1) end end end. -file("src/rexen/grammar.gleam", 59). -spec shunt(binary()) -> {ok, list(token())} | {error, binary()}. shunt(Input) -> In = gleam@string:to_graphemes(Input), _pipe = tokenize(In, []), shunt_loop(_pipe, [], []).