Current section

Files

Jump to
caffeine_lang src deps@cql@parser.erl
Raw

src/deps@cql@parser.erl

-module(deps@cql@parser).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/deps/cql/parser.gleam").
-export([is_last_char/2, is_balanced_parens/3, find_rightmost_operator_at_level/5, do_parse_expr/1, parse_expr/1]).
-export_type(['query'/0, exp_container/0, operator/0, exp/0, primary/0, word/0]).
-type 'query'() :: {'query', exp()}.
-type exp_container() :: {exp_container, exp()}.
-type operator() :: add | sub | mul | 'div'.
-type exp() :: {operator_expr, exp(), exp(), operator()} | {primary, primary()}.
-type primary() :: {primary_word, word()} | {primary_exp, exp()}.
-type word() :: {word, binary()}.
-file("src/deps/cql/parser.gleam", 105).
-spec is_last_char(binary(), integer()) -> boolean().
is_last_char(Input, Pos) ->
Is_empty = gleam@string:is_empty(Input),
Is_last = Pos =:= (string:length(Input) - 1),
Is_empty orelse Is_last.
-file("src/deps/cql/parser.gleam", 156).
-spec count_parens(integer(), binary(), integer()) -> integer().
count_parens(Cur_count, Input, Pos) ->
Char = gleam@string:slice(Input, Pos, 1),
case Char of
<<"("/utf8>> ->
Cur_count + 1;
<<")"/utf8>> ->
Cur_count - 1;
_ ->
Cur_count
end.
-file("src/deps/cql/parser.gleam", 92).
-spec is_balanced_parens(binary(), integer(), integer()) -> boolean().
is_balanced_parens(Input, Pos, Count) ->
case Pos >= string:length(Input) of
true ->
Count =:= 0;
false ->
New_count = count_parens(Count, Input, Pos),
Does_not_close_too_early = not ((New_count =:= 0) andalso not is_last_char(
Input,
Pos
)),
Does_not_close_too_early andalso is_balanced_parens(
Input,
Pos + 1,
New_count
)
end.
-file("src/deps/cql/parser.gleam", 57).
-spec is_fully_parenthesized(binary()) -> boolean().
is_fully_parenthesized(Input) ->
(gleam_stdlib:string_starts_with(Input, <<"("/utf8>>) andalso gleam_stdlib:string_ends_with(
Input,
<<")"/utf8>>
))
andalso ((string:length(Input) >= 2) andalso is_balanced_parens(Input, 1, 1)).
-file("src/deps/cql/parser.gleam", 112).
-spec find_rightmost_operator_at_level(
binary(),
binary(),
integer(),
integer(),
integer()
) -> {ok, {binary(), binary()}} | {error, binary()}.
find_rightmost_operator_at_level(
Input,
Operator,
Start_pos,
Paren_level,
Rightmost_pos
) ->
Operator_length = string:length(Operator),
case Start_pos >= string:length(Input) of
true ->
case Rightmost_pos of
-1 ->
{error, <<"Operator not found"/utf8>>};
Pos ->
Left = gleam@string:trim(gleam@string:slice(Input, 0, Pos)),
Right_start = Pos + Operator_length,
Right_length = string:length(Input) - Right_start,
Right = gleam@string:trim(
gleam@string:slice(Input, Right_start, Right_length)
),
{ok, {Left, Right}}
end;
false ->
New_paren_level = count_parens(Paren_level, Input, Start_pos),
New_rightmost_pos = case (New_paren_level =:= 0) andalso (gleam@string:slice(
Input,
Start_pos,
Operator_length
)
=:= Operator) of
true ->
Start_pos;
false ->
Rightmost_pos
end,
find_rightmost_operator_at_level(
Input,
Operator,
Start_pos + 1,
New_paren_level,
New_rightmost_pos
)
end.
-file("src/deps/cql/parser.gleam", 85).
-spec find_operator(binary(), binary()) -> {ok, {binary(), binary()}} |
{error, binary()}.
find_operator(Input, Operator) ->
find_rightmost_operator_at_level(Input, Operator, 0, 0, -1).
-file("src/deps/cql/parser.gleam", 63).
-spec try_operators(binary(), list({binary(), operator()})) -> {ok, exp()} |
{error, binary()}.
try_operators(Input, Operators) ->
case Operators of
[] ->
Word = {word, Input},
{ok, {primary, {primary_word, Word}}};
[{Op_str, Op} | Rest] ->
case find_operator(Input, Op_str) of
{ok, {Left, Right}} ->
gleam@result:'try'(
do_parse_expr(Left),
fun(Left_exp) ->
gleam@result:'try'(
do_parse_expr(Right),
fun(Right_exp) ->
{ok,
{operator_expr, Left_exp, Right_exp, Op}}
end
)
end
);
{error, _} ->
try_operators(Input, Rest)
end
end.
-file("src/deps/cql/parser.gleam", 41).
-spec do_parse_expr(binary()) -> {ok, exp()} | {error, binary()}.
do_parse_expr(Input) ->
Trimmed = gleam@string:trim(Input),
case is_fully_parenthesized(Trimmed) of
true ->
Inner = gleam@string:slice(Trimmed, 1, string:length(Trimmed) - 2),
gleam@result:'try'(
do_parse_expr(Inner),
fun(Inner_exp) -> {ok, {primary, {primary_exp, Inner_exp}}} end
);
false ->
Operators = [{<<"+"/utf8>>, add},
{<<"-"/utf8>>, sub},
{<<"*"/utf8>>, mul},
{<<"/"/utf8>>, 'div'}],
try_operators(Trimmed, Operators)
end.
-file("src/deps/cql/parser.gleam", 36).
-spec parse_expr(binary()) -> {ok, exp_container()} | {error, binary()}.
parse_expr(Input) ->
gleam@result:'try'(
do_parse_expr(Input),
fun(Exp) -> {ok, {exp_container, Exp}} end
).