Current section
Files
Jump to
Current section
Files
src/rexen@grammar.erl
-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, [], []).