-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} | {bar, EZK} | {dot, EZK} | {q_mark, EZK} | {plus, EZK}. -type token() :: c_paren | {letter, binary()} | {operator, operator_variant(integer())}. -file("src/rexen/grammar.gleam", 19). -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, 3}}; <<"+"/utf8>> -> {operator, {plus, 3}}; <<"|"/utf8>> -> {operator, {bar, 1}}; <<"("/utf8>> -> {operator, o_paren}; <<")"/utf8>> -> c_paren; _ -> {letter, Char} end, tokenize(Rest, lists:append(Tokens, [Tok])) end. -file("src/rexen/grammar.gleam", 37). -spec add_concat(list(token()), list(token())) -> list(token()). add_concat(Tokens, Output) -> case Tokens of [] -> Output; [Curr | Rest] -> case gleam@list:last(Output) of {error, _} -> add_concat(Rest, lists:append(Output, [Curr])); {ok, Prev} -> case Prev of {letter, _} -> case Curr of {letter, _} -> add_concat( Rest, lists:append( Output, [{operator, {dot, 2}}, Curr] ) ); c_paren -> add_concat( Rest, lists:append(Output, [Curr]) ); {operator, Variant} -> case Variant of o_paren -> add_concat( Rest, lists:append( Output, [{operator, {dot, 2}}, Curr] ) ); _ -> add_concat( Rest, lists:append(Output, [Curr]) ) end end; c_paren -> case Curr of {letter, _} -> add_concat( Rest, lists:append( Output, [{operator, {dot, 2}}, Curr] ) ); c_paren -> add_concat( Rest, lists:append(Output, [Curr]) ); {operator, Variant@1} -> case Variant@1 of o_paren -> add_concat( Rest, lists:append( Output, [{operator, {dot, 2}}, Curr] ) ); _ -> add_concat( Rest, lists:append(Output, [Curr]) ) end end; {operator, Variant@2} -> case Variant@2 of {asterix, _} -> case Curr of {letter, _} -> add_concat( Rest, lists:append( Output, [{operator, {dot, 2}}, Curr] ) ); c_paren -> add_concat( Rest, lists:append(Output, [Curr]) ); {operator, Variant@3} -> case Variant@3 of o_paren -> add_concat( Rest, lists:append( Output, [{operator, {dot, 2}}, Curr] ) ); _ -> add_concat( Rest, lists:append( Output, [Curr] ) ) end end; _ -> add_concat( Rest, lists:append(Output, [Curr]) ) end end end end. -file("src/rexen/grammar.gleam", 117). -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>>) ); {bar, _} -> to_string( Rest, gleam@string:append(Output, <<"|"/utf8>>) ); {dot, _} -> to_string(Rest, Output); {q_mark, _} -> to_string( Rest, gleam@string:append(Output, <<"?"/utf8>>) ); {plus, _} -> to_string( Rest, gleam@string:append(Output, <<"+"/utf8>>) ) end end end. -file("src/rexen/grammar.gleam", 185). -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", 195). -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; {bar, 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; {dot, 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; {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 end end. -file("src/rexen/grammar.gleam", 225). -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", 151). -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); {bar, P} -> {O@1, S@1} = handle_operator( Output, Stack, Opvar, P ), shunt_loop(Rest, O@1, S@1); {dot, 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); {plus, 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", 144). -spec shunt(binary()) -> {ok, list(token())} | {error, binary()}. shunt(Input) -> In = gleam@string:to_graphemes(Input), _pipe = tokenize(In, []), _pipe@1 = add_concat(_pipe, []), shunt_loop(_pipe@1, [], []).