Skip to main content

src/gg_cn@internal@parse.erl

-module(gg_cn@internal@parse).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/gg_cn/internal/parse.gleam").
-export([parse_class_name/1]).
-export_type([parsed/0, scan/0]).

-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.

?MODULEDOC(false).

-type parsed() :: {parsed,
        list(binary()),
        boolean(),
        binary(),
        gleam@option:option(integer())}.

-type scan() :: {scan,
        integer(),
        integer(),
        integer(),
        integer(),
        list(binary()),
        gleam@option:option(integer())}.

-file("src/gg_cn/internal/parse.gleam", 113).
?DOC(false).
-spec resolve_important(binary()) -> {binary(), boolean()}.
resolve_important(Base_with_important) ->
    case gleam_stdlib:string_ends_with(Base_with_important, <<"!"/utf8>>) of
        true ->
            {gleam@string:drop_end(Base_with_important, 1), true};

        false ->
            case gleam_stdlib:string_starts_with(
                Base_with_important,
                <<"!"/utf8>>
            ) of
                true ->
                    {gleam@string:drop_start(Base_with_important, 1), true};

                false ->
                    {Base_with_important, false}
            end
    end.

-file("src/gg_cn/internal/parse.gleam", 85).
?DOC(false).
-spec step(binary(), scan(), binary()) -> scan().
step(Class_name, State, Char) ->
    Index = erlang:element(2, State),
    Top_level = (erlang:element(3, State) =:= 0) andalso (erlang:element(
        4,
        State
    )
    =:= 0),
    case {Top_level, Char} of
        {true, <<":"/utf8>>} ->
            {scan,
                Index + 1,
                erlang:element(3, State),
                erlang:element(4, State),
                Index + 1,
                [gleam@string:slice(
                        Class_name,
                        erlang:element(5, State),
                        Index - erlang:element(5, State)
                    ) |
                    erlang:element(6, State)],
                erlang:element(7, State)};

        {true, <<"/"/utf8>>} ->
            {scan,
                Index + 1,
                erlang:element(3, State),
                erlang:element(4, State),
                erlang:element(5, State),
                erlang:element(6, State),
                {some, Index}};

        {_, <<"["/utf8>>} ->
            {scan,
                Index + 1,
                erlang:element(3, State) + 1,
                erlang:element(4, State),
                erlang:element(5, State),
                erlang:element(6, State),
                erlang:element(7, State)};

        {_, <<"]"/utf8>>} ->
            {scan,
                Index + 1,
                erlang:element(3, State) - 1,
                erlang:element(4, State),
                erlang:element(5, State),
                erlang:element(6, State),
                erlang:element(7, State)};

        {_, <<"("/utf8>>} ->
            {scan,
                Index + 1,
                erlang:element(3, State),
                erlang:element(4, State) + 1,
                erlang:element(5, State),
                erlang:element(6, State),
                erlang:element(7, State)};

        {_, <<")"/utf8>>} ->
            {scan,
                Index + 1,
                erlang:element(3, State),
                erlang:element(4, State) - 1,
                erlang:element(5, State),
                erlang:element(6, State),
                erlang:element(7, State)};

        {_, _} ->
            {scan,
                Index + 1,
                erlang:element(3, State),
                erlang:element(4, State),
                erlang:element(5, State),
                erlang:element(6, State),
                erlang:element(7, State)}
    end.

-file("src/gg_cn/internal/parse.gleam", 36).
?DOC(false).
-spec parse_class_name(binary()) -> parsed().
parse_class_name(Class_name) ->
    Chars = gleam@string:to_graphemes(Class_name),
    Final = gleam@list:fold(
        Chars,
        {scan, 0, 0, 0, 0, [], none},
        fun(State, Char) -> step(Class_name, State, Char) end
    ),
    Total = erlang:length(Chars),
    Modifiers = lists:reverse(erlang:element(6, Final)),
    Base_with_important = case Modifiers of
        [] ->
            Class_name;

        _ ->
            gleam@string:slice(
                Class_name,
                erlang:element(5, Final),
                Total - erlang:element(5, Final)
            )
    end,
    {Base_class_name, Has_important_modifier} = resolve_important(
        Base_with_important
    ),
    Maybe_postfix = case erlang:element(7, Final) of
        {some, Position} ->
            case Position > erlang:element(5, Final) of
                true ->
                    {some, Position - erlang:element(5, Final)};

                false ->
                    none
            end;

        none ->
            none
    end,
    {parsed, Modifiers, Has_important_modifier, Base_class_name, Maybe_postfix}.