Current section

Files

Jump to
caffeine_lang src caffeine_lang@parsing_utils.erl
Raw

src/caffeine_lang@parsing_utils.erl

-module(caffeine_lang@parsing_utils).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/caffeine_lang/parsing_utils.gleam").
-export([extract_paren_content/1, paren_innerds_trimmed/1, split_at_top_level_comma/1, paren_innerds_split_and_trimmed/1]).
-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.
-file("src/caffeine_lang/parsing_utils.gleam", 39).
?DOC(
" Finds the matching closing parenthesis, tracking nesting depth.\n"
" Returns the content before the matching close and the rest after it.\n"
).
-spec find_matching_close_paren(binary(), integer(), list(binary())) -> {ok,
{binary(), binary()}} |
{error, nil}.
find_matching_close_paren(S, Depth, Acc) ->
case gleam_stdlib:string_pop_grapheme(S) of
{error, _} ->
{error, nil};
{ok, {<<"("/utf8>>, Rest}} ->
find_matching_close_paren(Rest, Depth + 1, [<<"("/utf8>> | Acc]);
{ok, {<<")"/utf8>>, Rest@1}} ->
case Depth of
1 ->
{ok, {erlang:list_to_binary(lists:reverse(Acc)), Rest@1}};
_ ->
find_matching_close_paren(
Rest@1,
Depth - 1,
[<<")"/utf8>> | Acc]
)
end;
{ok, {Char, Rest@2}} ->
find_matching_close_paren(Rest@2, Depth, [Char | Acc])
end.
-file("src/caffeine_lang/parsing_utils.gleam", 17).
?DOC(false).
-spec extract_paren_content(binary()) -> {ok, binary()} | {error, nil}.
extract_paren_content(Raw) ->
case gleam@string:split_once(Raw, <<"("/utf8>>) of
{error, _} ->
{error, nil};
{ok, {_, After_open}} ->
gleam@result:'try'(
find_matching_close_paren(After_open, 1, []),
fun(_use0) ->
{Content, Rest} = _use0,
case gleam@string:trim(Rest) of
<<""/utf8>> ->
{ok, gleam@string:trim(Content)};
_ ->
{error, nil}
end
end
)
end.
-file("src/caffeine_lang/parsing_utils.gleam", 61).
?DOC(false).
-spec paren_innerds_trimmed(binary()) -> binary().
paren_innerds_trimmed(Raw) ->
case extract_paren_content(Raw) of
{ok, Content} ->
Content;
{error, _} ->
gleam@string:trim(Raw)
end.
-file("src/caffeine_lang/parsing_utils.gleam", 79).
-spec do_split_at_top_level_comma(
list(binary()),
integer(),
integer(),
list(binary()),
list(binary())
) -> list(binary()).
do_split_at_top_level_comma(Chars, Paren_depth, Brace_depth, Current, Acc) ->
case Chars of
[] ->
Trimmed = gleam@string:trim(
erlang:list_to_binary(lists:reverse(Current))
),
case Trimmed of
<<""/utf8>> ->
lists:reverse(Acc);
_ ->
lists:reverse([Trimmed | Acc])
end;
[<<"("/utf8>> | Rest] ->
do_split_at_top_level_comma(
Rest,
Paren_depth + 1,
Brace_depth,
[<<"("/utf8>> | Current],
Acc
);
[<<")"/utf8>> | Rest@1] ->
do_split_at_top_level_comma(
Rest@1,
Paren_depth - 1,
Brace_depth,
[<<")"/utf8>> | Current],
Acc
);
[<<"{"/utf8>> | Rest@2] ->
do_split_at_top_level_comma(
Rest@2,
Paren_depth,
Brace_depth + 1,
[<<"{"/utf8>> | Current],
Acc
);
[<<"}"/utf8>> | Rest@3] ->
do_split_at_top_level_comma(
Rest@3,
Paren_depth,
Brace_depth - 1,
[<<"}"/utf8>> | Current],
Acc
);
[<<","/utf8>> | Rest@4] when (Paren_depth =:= 0) andalso (Brace_depth =:= 0) ->
Trimmed@1 = gleam@string:trim(
erlang:list_to_binary(lists:reverse(Current))
),
do_split_at_top_level_comma(
Rest@4,
Paren_depth,
Brace_depth,
[],
[Trimmed@1 | Acc]
);
[Char | Rest@5] ->
do_split_at_top_level_comma(
Rest@5,
Paren_depth,
Brace_depth,
[Char | Current],
Acc
)
end.
-file("src/caffeine_lang/parsing_utils.gleam", 8).
?DOC(false).
-spec split_at_top_level_comma(binary()) -> list(binary()).
split_at_top_level_comma(S) ->
Chars = gleam@string:to_graphemes(S),
do_split_at_top_level_comma(Chars, 0, 0, [], []).
-file("src/caffeine_lang/parsing_utils.gleam", 72).
?DOC(false).
-spec paren_innerds_split_and_trimmed(binary()) -> list(binary()).
paren_innerds_split_and_trimmed(Raw) ->
case extract_paren_content(Raw) of
{ok, Content} ->
split_at_top_level_comma(Content);
{error, _} ->
[]
end.