Skip to main content

src/molt@internal@parser.erl

-module(molt@internal@parser).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/molt/internal/parser.gleam").
-export([parse/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.

?MODULEDOC(false).

-file("src/molt/internal/parser.gleam", 1324).
?DOC(false).
-spec add_kv(
    molt@internal@parser@core:state(),
    greenwood:node_(molt@types:toml_kind())
) -> molt@internal@parser@core:state().
add_kv(State, Kv_node) ->
    case erlang:element(7, State) of
        no_table ->
            {state,
                erlang:element(2, State),
                erlang:element(3, State),
                erlang:element(4, State),
                erlang:element(5, State),
                [{node_element, Kv_node} | erlang:element(6, State)],
                erlang:element(7, State),
                erlang:element(8, State)};

        {building, K, C, T, Tr} ->
            {state,
                erlang:element(2, State),
                erlang:element(3, State),
                erlang:element(4, State),
                erlang:element(5, State),
                erlang:element(6, State),
                {building, K, [{node_element, Kv_node} | C], T, Tr},
                erlang:element(8, State)}
    end.

-file("src/molt/internal/parser.gleam", 1353).
?DOC(false).
-spec attach_pending_trivia(
    greenwood:node_(molt@types:toml_kind()),
    list(greenwood:token(molt@types:toml_kind()))
) -> greenwood:node_(molt@types:toml_kind()).
attach_pending_trivia(Node, Pending_rev) ->
    case Pending_rev of
        [] ->
            Node;

        _ ->
            {node,
                erlang:element(2, Node),
                erlang:element(3, Node),
                {trivia, Pending_rev, []}}
    end.

-file("src/molt/internal/parser.gleam", 1342).
?DOC(false).
-spec attach_line_trivia(
    greenwood:node_(molt@types:toml_kind()),
    list(greenwood:token(molt@types:toml_kind())),
    list(greenwood:token(molt@types:toml_kind()))
) -> greenwood:node_(molt@types:toml_kind()).
attach_line_trivia(Node, Leading, Trailing) ->
    case {Leading, Trailing} of
        {[], []} ->
            Node;

        {_, _} ->
            {node,
                erlang:element(2, Node),
                erlang:element(3, Node),
                {trivia, Leading, Trailing}}
    end.

-file("src/molt/internal/parser.gleam", 307).
?DOC(false).
-spec all_bare_keys_valid(list(greenwood:element(molt@types:toml_kind()))) -> boolean().
all_bare_keys_valid(Children) ->
    gleam@list:all(Children, fun(El) -> case El of
                {token_element, {token, bare_key, Text}} ->
                    molt@internal@utils:is_bare_key(Text);

                {node_element, Node} when erlang:element(2, Node) =:= key ->
                    all_bare_keys_valid(erlang:element(3, Node));

                _ ->
                    true
            end end).

-file("src/molt/internal/parser.gleam", 290).
?DOC(false).
-spec do_has_value_after_equals(
    list(greenwood:element(molt@types:toml_kind())),
    boolean()
) -> boolean().
do_has_value_after_equals(Children, Past_equals) ->
    case {Children, Past_equals} of
        {[], false} ->
            true;

        {[], true} ->
            false;

        {[{token_element, {token, equals, _}} | Rest], _} ->
            do_has_value_after_equals(Rest, true);

        {[{token_element, {token, whitespace, _}} | Rest@1], Pe} ->
            do_has_value_after_equals(Rest@1, Pe);

        {[{token_element, {token, newline, _}} | _], true} ->
            false;

        {[_ | _], true} ->
            true;

        {[_ | Rest@2], false} ->
            do_has_value_after_equals(Rest@2, false)
    end.

-file("src/molt/internal/parser.gleam", 286).
?DOC(false).
-spec has_value_after_equals(list(greenwood:element(molt@types:toml_kind()))) -> boolean().
has_value_after_equals(Children) ->
    do_has_value_after_equals(Children, false).

-file("src/molt/internal/parser.gleam", 277).
?DOC(false).
-spec has_equals(list(greenwood:element(molt@types:toml_kind()))) -> boolean().
has_equals(Children) ->
    gleam@list:any(Children, fun(El) -> case El of
                {token_element, {token, equals, _}} ->
                    true;

                _ ->
                    false
            end end).

-file("src/molt/internal/parser.gleam", 269).
?DOC(false).
-spec is_valid_kv(greenwood:node_(molt@types:toml_kind())) -> boolean().
is_valid_kv(Node) ->
    Children = lists:reverse(erlang:element(3, Node)),
    (has_equals(Children) andalso has_value_after_equals(Children)) andalso all_bare_keys_valid(
        Children
    ).

-file("src/molt/internal/parser.gleam", 204).
?DOC(false).
-spec head_split(molt@internal@parser@core:state()) -> {list(greenwood:token(molt@types:toml_kind())),
    molt@internal@parser@core:state()}.
head_split(State) ->
    case {erlang:element(7, State), erlang:element(6, State)} of
        {no_table, []} ->
            {Root_rev, Node_rev} = molt@internal@parser@core:peel_head_block(
                erlang:element(3, State)
            ),
            {Node_rev,
                {state,
                    erlang:element(2, State),
                    erlang:element(3, State),
                    Root_rev,
                    erlang:element(5, State),
                    erlang:element(6, State),
                    erlang:element(7, State),
                    erlang:element(8, State)}};

        {_, _} ->
            {erlang:element(3, State), State}
    end.

-file("src/molt/internal/parser.gleam", 1311).
?DOC(false).
-spec peel_leading_ws_from_acc(
    list(greenwood:element(molt@types:toml_kind())),
    list(greenwood:element(molt@types:toml_kind()))
) -> {list(greenwood:element(molt@types:toml_kind())),
    list(greenwood:element(molt@types:toml_kind()))}.
peel_leading_ws_from_acc(Acc, Ws_acc) ->
    case Acc of
        [{token_element, {token, whitespace, _}} = El | Rest] ->
            peel_leading_ws_from_acc(Rest, [El | Ws_acc]);

        _ ->
            {Acc, lists:reverse(Ws_acc)}
    end.

-file("src/molt/internal/parser.gleam", 1289).
?DOC(false).
-spec take_key_tokens(
    list(greenwood:element(molt@types:toml_kind())),
    list(greenwood:element(molt@types:toml_kind()))
) -> {list(greenwood:element(molt@types:toml_kind())),
    list(greenwood:element(molt@types:toml_kind()))}.
take_key_tokens(Items, Acc) ->
    case Items of
        [{token_element, {token, bare_key, _}} = El | Rest] ->
            take_key_tokens(Rest, [El | Acc]);

        [{token_element, {token, dot, _}} = El | Rest] ->
            take_key_tokens(Rest, [El | Acc]);

        [{token_element, {token, basic_string, _}} = El | Rest] ->
            take_key_tokens(Rest, [El | Acc]);

        [{token_element, {token, literal_string, _}} = El | Rest] ->
            take_key_tokens(Rest, [El | Acc]);

        [{token_element, {token, whitespace, _}} = El | Rest] ->
            take_key_tokens(Rest, [El | Acc]);

        _ ->
            {Stripped_acc, Ws_tail} = peel_leading_ws_from_acc(Acc, []),
            {lists:reverse(Stripped_acc), lists:append(Ws_tail, Items)}
    end.

-file("src/molt/internal/parser.gleam", 1270).
?DOC(false).
-spec take_trivia_prefix(
    list(greenwood:element(molt@types:toml_kind())),
    list(greenwood:element(molt@types:toml_kind()))
) -> {list(greenwood:element(molt@types:toml_kind())),
    list(greenwood:element(molt@types:toml_kind()))}.
take_trivia_prefix(Items, Acc) ->
    case Items of
        [{token_element, {token, whitespace, _}} = El | Rest] ->
            take_trivia_prefix(Rest, [El | Acc]);

        _ ->
            {lists:reverse(Acc), Items}
    end.

-file("src/molt/internal/parser.gleam", 1259).
?DOC(false).
-spec has_dot_token(list(greenwood:element(molt@types:toml_kind()))) -> boolean().
has_dot_token(Children) ->
    gleam@list:any(Children, fun(El) -> case El of
                {token_element, {token, dot, _}} ->
                    true;

                _ ->
                    false
            end end).

-file("src/molt/internal/parser.gleam", 1248).
?DOC(false).
-spec split_at_equals_rev(
    list(greenwood:element(molt@types:toml_kind())),
    list(greenwood:element(molt@types:toml_kind()))
) -> {list(greenwood:element(molt@types:toml_kind())),
    list(greenwood:element(molt@types:toml_kind()))}.
split_at_equals_rev(Children_rev, Acc) ->
    case Children_rev of
        [] ->
            {lists:reverse(Acc), []};

        [{token_element, {token, equals, _}} | _] = Tail ->
            {lists:reverse(Acc), Tail};

        [El | Rest] ->
            split_at_equals_rev(Rest, [El | Acc])
    end.

-file("src/molt/internal/parser.gleam", 1223).
?DOC(false).
-spec wrap_dotted_key(list(greenwood:element(molt@types:toml_kind()))) -> list(greenwood:element(molt@types:toml_kind())).
wrap_dotted_key(Children_rev) ->
    {After_eq_rev, Eq_and_key_rev} = split_at_equals_rev(Children_rev, []),
    case Eq_and_key_rev of
        [] ->
            Children_rev;

        [Eq_el | Key_rev] ->
            case has_dot_token(Key_rev) of
                false ->
                    Children_rev;

                true ->
                    {Trailing_ws_rev, After_ws_rev} = take_trivia_prefix(
                        Key_rev,
                        []
                    ),
                    {Key_inner_rev, Leading_rev} = take_key_tokens(
                        After_ws_rev,
                        []
                    ),
                    Key_node = greenwood:node(key, Key_inner_rev),
                    lists:append(
                        [After_eq_rev,
                            [Eq_el],
                            Trailing_ws_rev,
                            [{node_element, Key_node}],
                            Leading_rev]
                    )
            end
    end.

-file("src/molt/internal/parser.gleam", 789).
?DOC(false).
-spec flush_inline_entry(
    list(greenwood:token(molt@types:toml_kind())),
    list(greenwood:element(molt@types:toml_kind())),
    list(greenwood:element(molt@types:toml_kind()))
) -> list(greenwood:element(molt@types:toml_kind())).
flush_inline_entry(Trivia_acc, Entry_acc, Result) ->
    case Entry_acc of
        [] ->
            case Trivia_acc of
                [] ->
                    Result;

                _ ->
                    gleam@list:fold(
                        lists:reverse(Trivia_acc),
                        Result,
                        fun(Acc, Tok) -> [{token_element, Tok} | Acc] end
                    )
            end;

        _ ->
            {Children, Trailing} = molt@internal@parser@core:peel_trailing_comment_rev(
                Entry_acc
            ),
            Trivia = case {Trivia_acc, Trailing} of
                {[], []} ->
                    bare;

                {_, _} ->
                    {trivia, Trivia_acc, Trailing}
            end,
            Node = {node, key_value, Children, Trivia},
            [{node_element, Node} | Result]
    end.

-file("src/molt/internal/parser.gleam", 656).
?DOC(false).
-spec take_same_line(
    list(greenwood:element(molt@types:toml_kind())),
    list(greenwood:element(molt@types:toml_kind()))
) -> {list(greenwood:element(molt@types:toml_kind())),
    list(greenwood:element(molt@types:toml_kind()))}.
take_same_line(Children, Acc) ->
    case Children of
        [] ->
            {Acc, []};

        [{token_element, {token, newline, _} = Tok} | Rest] ->
            {[{token_element, Tok} | Acc], Rest};

        [{token_element, {token, whitespace, _}} = El | Rest@1] ->
            take_same_line(Rest@1, [El | Acc]);

        [{token_element, {token, comment, _}} = El@1 | Rest@2] ->
            take_same_line(Rest@2, [El@1 | Acc]);

        _ ->
            {Acc, Children}
    end.

-file("src/molt/internal/parser.gleam", 684).
?DOC(false).
-spec do_group_inline_forward(
    list(greenwood:element(molt@types:toml_kind())),
    list(greenwood:token(molt@types:toml_kind())),
    list(greenwood:element(molt@types:toml_kind())),
    list(greenwood:element(molt@types:toml_kind()))
) -> list(greenwood:element(molt@types:toml_kind())).
do_group_inline_forward(Children, Trivia_acc, Entry_acc, Result) ->
    case Children of
        [] ->
            flush_inline_entry(Trivia_acc, Entry_acc, Result);

        [{token_element, {token, left_brace, _}} | Rest] ->
            do_group_inline_forward(
                Rest,
                Trivia_acc,
                Entry_acc,
                [{token_element, {token, left_brace, <<""/utf8>>}} | Result]
            );

        [{token_element, {token, right_brace, _}} | Rest@1] ->
            Result@1 = flush_inline_entry(Trivia_acc, Entry_acc, Result),
            do_group_inline_forward(
                Rest@1,
                [],
                [],
                [{token_element, {token, right_brace, <<""/utf8>>}} | Result@1]
            );

        [{token_element, {token, comma, _} = Tok} | Rest@2] ->
            Entry_acc@1 = [{token_element, Tok} | Entry_acc],
            {Entry_acc@2, Rest@3} = take_same_line(Rest@2, Entry_acc@1),
            Result@2 = flush_inline_entry(Trivia_acc, Entry_acc@2, Result),
            do_group_inline_forward(Rest@3, [], [], Result@2);

        [{token_element, {token, comment, _} = Tok@1} | Rest@4] ->
            case Entry_acc of
                [] ->
                    do_group_inline_forward(
                        Rest@4,
                        [Tok@1 | Trivia_acc],
                        [],
                        Result
                    );

                _ ->
                    do_group_inline_forward(
                        Rest@4,
                        Trivia_acc,
                        [{token_element, Tok@1} | Entry_acc],
                        Result
                    )
            end;

        [{token_element, {token, newline, _} = Tok@2} | Rest@5] ->
            case Entry_acc of
                [] ->
                    do_group_inline_forward(
                        Rest@5,
                        [Tok@2 | Trivia_acc],
                        [],
                        Result
                    );

                _ ->
                    Entry_acc@3 = [{token_element, Tok@2} | Entry_acc],
                    Result@3 = flush_inline_entry(
                        Trivia_acc,
                        Entry_acc@3,
                        Result
                    ),
                    do_group_inline_forward(Rest@5, [], [], Result@3)
            end;

        [{token_element, {token, whitespace, _} = Tok@3} | Rest@6] ->
            case Entry_acc of
                [] ->
                    do_group_inline_forward(
                        Rest@6,
                        [Tok@3 | Trivia_acc],
                        [],
                        Result
                    );

                _ ->
                    do_group_inline_forward(
                        Rest@6,
                        Trivia_acc,
                        [{token_element, Tok@3} | Entry_acc],
                        Result
                    )
            end;

        [El | Rest@7] ->
            do_group_inline_forward(
                Rest@7,
                Trivia_acc,
                [El | Entry_acc],
                Result
            )
    end.

-file("src/molt/internal/parser.gleam", 677).
?DOC(false).
-spec group_inline_table_entries(
    list(greenwood:element(molt@types:toml_kind()))
) -> list(greenwood:element(molt@types:toml_kind())).
group_inline_table_entries(Children) ->
    _pipe = lists:reverse(Children),
    do_group_inline_forward(_pipe, [], [], []).

-file("src/molt/internal/parser.gleam", 624).
?DOC(false).
-spec flush_element(
    list(greenwood:token(molt@types:toml_kind())),
    list(greenwood:element(molt@types:toml_kind())),
    list(greenwood:element(molt@types:toml_kind()))
) -> list(greenwood:element(molt@types:toml_kind())).
flush_element(Trivia_acc, Element_acc, Result) ->
    case Element_acc of
        [] ->
            case Trivia_acc of
                [] ->
                    Result;

                _ ->
                    gleam@list:fold(
                        lists:reverse(Trivia_acc),
                        Result,
                        fun(Acc, Tok) -> [{token_element, Tok} | Acc] end
                    )
            end;

        _ ->
            {Children, Trailing} = molt@internal@parser@core:peel_trailing_comment_rev(
                Element_acc
            ),
            Trivia = case {Trivia_acc, Trailing} of
                {[], []} ->
                    bare;

                {_, _} ->
                    {trivia, Trivia_acc, Trailing}
            end,
            Node = {node, array_element, Children, Trivia},
            [{node_element, Node} | Result]
    end.

-file("src/molt/internal/parser.gleam", 514).
?DOC(false).
-spec do_group_array_forward(
    list(greenwood:element(molt@types:toml_kind())),
    list(greenwood:token(molt@types:toml_kind())),
    list(greenwood:element(molt@types:toml_kind())),
    list(greenwood:element(molt@types:toml_kind()))
) -> list(greenwood:element(molt@types:toml_kind())).
do_group_array_forward(Children, Trivia_acc, Element_acc, Result) ->
    case Children of
        [] ->
            flush_element(Trivia_acc, Element_acc, Result);

        [{token_element, {token, left_bracket, _}} | Rest] ->
            do_group_array_forward(
                Rest,
                Trivia_acc,
                Element_acc,
                [{token_element, {token, left_bracket, <<""/utf8>>}} | Result]
            );

        [{token_element, {token, right_bracket, _}} | Rest@1] ->
            Result@1 = flush_element(Trivia_acc, Element_acc, Result),
            do_group_array_forward(
                Rest@1,
                [],
                [],
                [{token_element, {token, right_bracket, <<""/utf8>>}} |
                    Result@1]
            );

        [{token_element, {token, comment, _} = Tok} | Rest@2] ->
            case Element_acc of
                [] ->
                    do_group_array_forward(
                        Rest@2,
                        [Tok | Trivia_acc],
                        [],
                        Result
                    );

                _ ->
                    do_group_array_forward(
                        Rest@2,
                        Trivia_acc,
                        [{token_element, Tok} | Element_acc],
                        Result
                    )
            end;

        [{token_element, {token, newline, _} = Tok@1} | Rest@3] ->
            case Element_acc of
                [] ->
                    do_group_array_forward(
                        Rest@3,
                        [Tok@1 | Trivia_acc],
                        [],
                        Result
                    );

                _ ->
                    Result@2 = flush_element(
                        Trivia_acc,
                        [{token_element, Tok@1} | Element_acc],
                        Result
                    ),
                    do_group_array_forward(Rest@3, [], [], Result@2)
            end;

        [{token_element, {token, whitespace, _} = Tok@2} | Rest@4] ->
            case Element_acc of
                [] ->
                    do_group_array_forward(
                        Rest@4,
                        [Tok@2 | Trivia_acc],
                        [],
                        Result
                    );

                _ ->
                    do_group_array_forward(
                        Rest@4,
                        Trivia_acc,
                        [{token_element, Tok@2} | Element_acc],
                        Result
                    )
            end;

        [{token_element, {token, comma, _} = Tok@3} | Rest@5] ->
            Element_acc@1 = [{token_element, Tok@3} | Element_acc],
            {Element_acc@2, Rest@6} = take_same_line(Rest@5, Element_acc@1),
            Result@3 = flush_element(Trivia_acc, Element_acc@2, Result),
            do_group_array_forward(Rest@6, [], [], Result@3);

        [El | Rest@7] ->
            do_group_array_forward(
                Rest@7,
                Trivia_acc,
                [El | Element_acc],
                Result
            )
    end.

-file("src/molt/internal/parser.gleam", 501).
?DOC(false).
-spec group_array_elements(list(greenwood:element(molt@types:toml_kind()))) -> list(greenwood:element(molt@types:toml_kind())).
group_array_elements(Children) ->
    _pipe = lists:reverse(Children),
    do_group_array_forward(_pipe, [], [], []).

-file("src/molt/internal/parser.gleam", 451).
?DOC(false).
-spec try_merge_datetime(
    list(greenwood:element(molt@types:toml_kind())),
    binary(),
    binary(),
    molt@internal@parser@core:splitters()
) -> {ok, {list(greenwood:element(molt@types:toml_kind())), binary()}} |
    {error, nil}.
try_merge_datetime(Acc, Ws, Rest, Sp) ->
    case {Ws, Acc} of
        {<<" "/utf8>>,
            [{token_element, {token, local_date, Date_text}} | Rest_acc]} ->
            {Prefix, _, _} = splitter_ffi:split(erlang:element(4, Sp), Rest),
            gleam@bool:guard(
                Prefix =:= <<""/utf8>>,
                {error, nil},
                fun() ->
                    Combined = <<<<Date_text/binary, " "/utf8>>/binary,
                        Prefix/binary>>,
                    case molt@internal@classifier:match_datetime(Combined) of
                        {some, K} ->
                            New_rest = gleam@string:drop_start(
                                Rest,
                                string:length(Prefix)
                            ),
                            {ok,
                                {[{token_element, {token, K, Combined}} |
                                        Rest_acc],
                                    New_rest}};

                        none ->
                            {error, nil}
                    end
                end
            );

        {_, _} ->
            {error, nil}
    end.

-file("src/molt/internal/parser.gleam", 436).
?DOC(false).
-spec emit_value_prefix(
    binary(),
    list(greenwood:element(molt@types:toml_kind()))
) -> list(greenwood:element(molt@types:toml_kind())).
emit_value_prefix(Prefix, Acc) ->
    case Prefix of
        <<""/utf8>> ->
            Acc;

        _ ->
            [{token_element, molt@internal@parser@core:tokenize_value(Prefix)} |
                Acc]
    end.

-file("src/molt/internal/parser.gleam", 1181).
?DOC(false).
-spec pull_next_line_inline_table(
    molt@internal@parser@core:splitters(),
    list(greenwood:element(molt@types:toml_kind())),
    binary(),
    binary(),
    boolean()
) -> {list(greenwood:element(molt@types:toml_kind())),
    binary(),
    binary(),
    binary()}.
pull_next_line_inline_table(Sp, Acc, Pending_nl, Source_rest, After_eq) ->
    Acc@1 = case Pending_nl of
        <<""/utf8>> ->
            Acc;

        _ ->
            [{token_element, {token, newline, Pending_nl}} | Acc]
    end,
    case Source_rest of
        <<""/utf8>> ->
            {Acc@1, <<""/utf8>>, <<""/utf8>>, <<""/utf8>>};

        _ ->
            {Next_line, Pending_nl@1, Source_rest@1} = splitter_ffi:split(
                erlang:element(2, Sp),
                Source_rest
            ),
            do_consume_inline_table(
                Sp,
                Next_line,
                Acc@1,
                Pending_nl@1,
                Source_rest@1,
                After_eq
            )
    end.

-file("src/molt/internal/parser.gleam", 984).
?DOC(false).
-spec pull_next_line_array(
    molt@internal@parser@core:splitters(),
    list(greenwood:element(molt@types:toml_kind())),
    binary(),
    binary()
) -> {list(greenwood:element(molt@types:toml_kind())),
    binary(),
    binary(),
    binary()}.
pull_next_line_array(Sp, Acc, Pending_nl, Source_rest) ->
    Acc@1 = case Pending_nl of
        <<""/utf8>> ->
            Acc;

        _ ->
            [{token_element, {token, newline, Pending_nl}} | Acc]
    end,
    case Source_rest of
        <<""/utf8>> ->
            {Acc@1, <<""/utf8>>, <<""/utf8>>, <<""/utf8>>};

        _ ->
            {Next_line, Next_nl, More_rest} = splitter_ffi:split(
                erlang:element(2, Sp),
                Source_rest
            ),
            do_consume_array(Sp, Next_line, Acc@1, Next_nl, More_rest)
    end.

-file("src/molt/internal/parser.gleam", 952).
?DOC(false).
-spec consume_array_after_whitespace(
    molt@internal@parser@core:splitters(),
    binary(),
    list(greenwood:element(molt@types:toml_kind())),
    binary(),
    binary(),
    binary()
) -> {list(greenwood:element(molt@types:toml_kind())),
    binary(),
    binary(),
    binary()}.
consume_array_after_whitespace(Sp, Input, Acc, Pending_nl, Source_rest, Delim) ->
    {Ws, Rest} = molt@internal@parser@core:scan_ws(Delim, Input),
    case try_merge_datetime(Acc, Ws, Rest, Sp) of
        {ok, {Merged_acc, Rest@1}} ->
            do_consume_array(Sp, Rest@1, Merged_acc, Pending_nl, Source_rest);

        {error, nil} ->
            do_consume_array(
                Sp,
                Rest,
                [{token_element, {token, whitespace, Ws}} | Acc],
                Pending_nl,
                Source_rest
            )
    end.

-file("src/molt/internal/parser.gleam", 815).
?DOC(false).
-spec do_consume_array(
    molt@internal@parser@core:splitters(),
    binary(),
    list(greenwood:element(molt@types:toml_kind())),
    binary(),
    binary()
) -> {list(greenwood:element(molt@types:toml_kind())),
    binary(),
    binary(),
    binary()}.
do_consume_array(Sp, Input, Acc, Pending_nl, Source_rest) ->
    case Input of
        <<""/utf8>> ->
            pull_next_line_array(Sp, Acc, Pending_nl, Source_rest);

        _ ->
            {Prefix, Delim, Rest} = splitter_ffi:split(
                erlang:element(4, Sp),
                Input
            ),
            Acc@1 = emit_value_prefix(Prefix, Acc),
            case Delim of
                <<""/utf8>> ->
                    pull_next_line_array(Sp, Acc@1, Pending_nl, Source_rest);

                <<"]"/utf8>> ->
                    {[{token_element, {token, right_bracket, <<""/utf8>>}} |
                            Acc@1],
                        Rest,
                        Pending_nl,
                        Source_rest};

                <<","/utf8>> ->
                    do_consume_array(
                        Sp,
                        Rest,
                        [{token_element, {token, comma, <<""/utf8>>}} | Acc@1],
                        Pending_nl,
                        Source_rest
                    );

                <<" "/utf8>> ->
                    consume_array_after_whitespace(
                        Sp,
                        Rest,
                        Acc@1,
                        Pending_nl,
                        Source_rest,
                        Delim
                    );

                <<"\t"/utf8>> ->
                    consume_array_after_whitespace(
                        Sp,
                        Rest,
                        Acc@1,
                        Pending_nl,
                        Source_rest,
                        Delim
                    );

                <<"["/utf8>> ->
                    {Nested, Rem, Rem_nl, Rem_rest} = consume_array(
                        Sp,
                        Rest,
                        Pending_nl,
                        Source_rest
                    ),
                    do_consume_array(
                        Sp,
                        Rem,
                        [{node_element, Nested} | Acc@1],
                        Rem_nl,
                        Rem_rest
                    );

                <<"{"/utf8>> ->
                    {Nested@1, Rem@1, Rem_nl@1, Rem_rest@1} = consume_inline_table(
                        Sp,
                        Rest,
                        Pending_nl,
                        Source_rest
                    ),
                    do_consume_array(
                        Sp,
                        Rem@1,
                        [{node_element, Nested@1} | Acc@1],
                        Rem_nl@1,
                        Rem_rest@1
                    );

                <<"\""/utf8>> ->
                    {Tok_, Rem@2, Rem_nl@2, Rem_rest@2} = molt@internal@parser@scanners:scan_basic_string(
                        Sp,
                        Rest,
                        Pending_nl,
                        Source_rest
                    ),
                    do_consume_array(
                        Sp,
                        Rem@2,
                        [{token_element, Tok_} | Acc@1],
                        Rem_nl@2,
                        Rem_rest@2
                    );

                <<"'"/utf8>> ->
                    {Tok_@1, Rem@3, Rem_nl@3, Rem_rest@3} = molt@internal@parser@scanners:scan_literal_string(
                        Sp,
                        Rest,
                        Pending_nl,
                        Source_rest
                    ),
                    do_consume_array(
                        Sp,
                        Rem@3,
                        [{token_element, Tok_@1} | Acc@1],
                        Rem_nl@3,
                        Rem_rest@3
                    );

                <<"#"/utf8>> ->
                    Acc@2 = [{token_element,
                            {token, comment, <<"#"/utf8, Rest/binary>>}} |
                        Acc@1],
                    pull_next_line_array(Sp, Acc@2, Pending_nl, Source_rest);

                <<"="/utf8>> ->
                    do_consume_array(
                        Sp,
                        Rest,
                        [{token_element, {token, invalid_value, <<"="/utf8>>}} |
                            Acc@1],
                        Pending_nl,
                        Source_rest
                    );

                _ ->
                    do_consume_array(Sp, Rest, Acc@1, Pending_nl, Source_rest)
            end
    end.

-file("src/molt/internal/parser.gleam", 478).
?DOC(false).
-spec consume_array(
    molt@internal@parser@core:splitters(),
    binary(),
    binary(),
    binary()
) -> {greenwood:node_(molt@types:toml_kind()), binary(), binary(), binary()}.
consume_array(Sp, Input, Pending_nl, Source_rest) ->
    {Children_rev, Rem, Rem_nl, Rem_rest} = do_consume_array(
        Sp,
        Input,
        [{token_element, {token, left_bracket, <<""/utf8>>}}],
        Pending_nl,
        Source_rest
    ),
    Children_rev@1 = group_array_elements(Children_rev),
    Node = greenwood:node(array, Children_rev@1),
    {Node, Rem, Rem_nl, Rem_rest}.

-file("src/molt/internal/parser.gleam", 1036).
?DOC(false).
-spec do_consume_inline_table(
    molt@internal@parser@core:splitters(),
    binary(),
    list(greenwood:element(molt@types:toml_kind())),
    binary(),
    binary(),
    boolean()
) -> {list(greenwood:element(molt@types:toml_kind())),
    binary(),
    binary(),
    binary()}.
do_consume_inline_table(Sp, Input, Acc, Pending_nl, Source_rest, After_eq) ->
    case Input of
        <<""/utf8>> ->
            pull_next_line_inline_table(
                Sp,
                Acc,
                Pending_nl,
                Source_rest,
                After_eq
            );

        _ ->
            {Prefix, Delim, Rest} = splitter_ffi:split(
                erlang:element(4, Sp),
                Input
            ),
            Acc@1 = case {Prefix, After_eq} of
                {<<""/utf8>>, _} ->
                    Acc;

                {_, true} ->
                    [{token_element,
                            molt@internal@parser@core:tokenize_value(Prefix)} |
                        Acc];

                {_, false} ->
                    [{token_element, {token, bare_key, Prefix}} | Acc]
            end,
            case Delim of
                <<""/utf8>> ->
                    pull_next_line_inline_table(
                        Sp,
                        Acc@1,
                        Pending_nl,
                        Source_rest,
                        After_eq
                    );

                <<"}"/utf8>> ->
                    {[{token_element, {token, right_brace, <<""/utf8>>}} |
                            Acc@1],
                        Rest,
                        Pending_nl,
                        Source_rest};

                <<","/utf8>> ->
                    do_consume_inline_table(
                        Sp,
                        Rest,
                        [{token_element, {token, comma, <<""/utf8>>}} | Acc@1],
                        Pending_nl,
                        Source_rest,
                        false
                    );

                <<" "/utf8>> ->
                    {Ws, Rest_after} = molt@internal@parser@core:scan_ws(
                        Delim,
                        Rest
                    ),
                    do_consume_inline_table(
                        Sp,
                        Rest_after,
                        [{token_element, {token, whitespace, Ws}} | Acc@1],
                        Pending_nl,
                        Source_rest,
                        After_eq
                    );

                <<"\t"/utf8>> ->
                    {Ws, Rest_after} = molt@internal@parser@core:scan_ws(
                        Delim,
                        Rest
                    ),
                    do_consume_inline_table(
                        Sp,
                        Rest_after,
                        [{token_element, {token, whitespace, Ws}} | Acc@1],
                        Pending_nl,
                        Source_rest,
                        After_eq
                    );

                <<"="/utf8>> ->
                    do_consume_inline_table(
                        Sp,
                        Rest,
                        [{token_element, {token, equals, <<""/utf8>>}} | Acc@1],
                        Pending_nl,
                        Source_rest,
                        true
                    );

                <<"["/utf8>> ->
                    {Nested, Input@1, Pending_nl@1, Source_rest@1} = consume_array(
                        Sp,
                        Rest,
                        Pending_nl,
                        Source_rest
                    ),
                    do_consume_inline_table(
                        Sp,
                        Input@1,
                        [{node_element, Nested} | Acc@1],
                        Pending_nl@1,
                        Source_rest@1,
                        After_eq
                    );

                <<"{"/utf8>> ->
                    {Nested@1, Input@2, Pending_nl@2, Source_rest@2} = consume_inline_table(
                        Sp,
                        Rest,
                        Pending_nl,
                        Source_rest
                    ),
                    do_consume_inline_table(
                        Sp,
                        Input@2,
                        [{node_element, Nested@1} | Acc@1],
                        Pending_nl@2,
                        Source_rest@2,
                        After_eq
                    );

                <<"\""/utf8>> ->
                    {Tok_, Input@3, Pending_nl@3, Source_rest@3} = molt@internal@parser@scanners:scan_basic_string(
                        Sp,
                        Rest,
                        Pending_nl,
                        Source_rest
                    ),
                    do_consume_inline_table(
                        Sp,
                        Input@3,
                        [{token_element, Tok_} | Acc@1],
                        Pending_nl@3,
                        Source_rest@3,
                        After_eq
                    );

                <<"'"/utf8>> ->
                    {Tok_@1, Input@4, Pending_nl@4, Source_rest@4} = molt@internal@parser@scanners:scan_literal_string(
                        Sp,
                        Rest,
                        Pending_nl,
                        Source_rest
                    ),
                    do_consume_inline_table(
                        Sp,
                        Input@4,
                        [{token_element, Tok_@1} | Acc@1],
                        Pending_nl@4,
                        Source_rest@4,
                        After_eq
                    );

                <<"#"/utf8>> ->
                    Acc@2 = [{token_element,
                            {token, comment, <<"#"/utf8, Rest/binary>>}} |
                        Acc@1],
                    pull_next_line_inline_table(
                        Sp,
                        Acc@2,
                        Pending_nl,
                        Source_rest,
                        After_eq
                    );

                _ ->
                    do_consume_inline_table(
                        Sp,
                        Rest,
                        Acc@1,
                        Pending_nl,
                        Source_rest,
                        After_eq
                    )
            end
    end.

-file("src/molt/internal/parser.gleam", 1012).
?DOC(false).
-spec consume_inline_table(
    molt@internal@parser@core:splitters(),
    binary(),
    binary(),
    binary()
) -> {greenwood:node_(molt@types:toml_kind()), binary(), binary(), binary()}.
consume_inline_table(Sp, Input, Pending_nl, Source_rest) ->
    {Children_rev, Rem, Rem_nl, Rem_rest} = do_consume_inline_table(
        Sp,
        Input,
        [{token_element, {token, left_brace, <<""/utf8>>}}],
        Pending_nl,
        Source_rest,
        false
    ),
    Children_rev@1 = group_inline_table_entries(Children_rev),
    Node = greenwood:node(inline_table, Children_rev@1),
    {Node, Rem, Rem_nl, Rem_rest}.

-file("src/molt/internal/parser.gleam", 921).
?DOC(false).
-spec consume_value_after_whitespace(
    molt@internal@parser@core:splitters(),
    binary(),
    list(greenwood:element(molt@types:toml_kind())),
    binary(),
    binary(),
    binary()
) -> {list(greenwood:element(molt@types:toml_kind())), binary(), binary()}.
consume_value_after_whitespace(Sp, Input, Acc, Pending_nl, Source_rest, Delim) ->
    begin
        {Ws, Rest} = molt@internal@parser@core:scan_ws(Delim, Input),
        case try_merge_datetime(Acc, Ws, Rest, Sp) of
            {ok, {Merged_acc, New_rest}} ->
                consume_value(Sp, New_rest, Merged_acc, Pending_nl, Source_rest);

            {error, nil} ->
                consume_value(
                    Sp,
                    Rest,
                    [{token_element, {token, whitespace, Ws}} | Acc],
                    Pending_nl,
                    Source_rest
                )
        end
    end.

-file("src/molt/internal/parser.gleam", 321).
?DOC(false).
-spec consume_value(
    molt@internal@parser@core:splitters(),
    binary(),
    list(greenwood:element(molt@types:toml_kind())),
    binary(),
    binary()
) -> {list(greenwood:element(molt@types:toml_kind())), binary(), binary()}.
consume_value(Sp, Input, Acc, Pending_nl, Source_rest) ->
    case Input of
        <<""/utf8>> ->
            {Acc, Pending_nl, Source_rest};

        _ ->
            {Prefix, Delim, Rest} = splitter_ffi:split(
                erlang:element(4, Sp),
                Input
            ),
            Acc@1 = emit_value_prefix(Prefix, Acc),
            case Delim of
                <<""/utf8>> ->
                    {Acc@1, Pending_nl, Source_rest};

                <<" "/utf8>> ->
                    consume_value_after_whitespace(
                        Sp,
                        Rest,
                        Acc@1,
                        Pending_nl,
                        Source_rest,
                        Delim
                    );

                <<"\t"/utf8>> ->
                    consume_value_after_whitespace(
                        Sp,
                        Rest,
                        Acc@1,
                        Pending_nl,
                        Source_rest,
                        Delim
                    );

                <<"["/utf8>> ->
                    {Node, Rem, Rem_nl, Rem_rest} = consume_array(
                        Sp,
                        Rest,
                        Pending_nl,
                        Source_rest
                    ),
                    consume_value(
                        Sp,
                        Rem,
                        [{node_element, Node} | Acc@1],
                        Rem_nl,
                        Rem_rest
                    );

                <<"{"/utf8>> ->
                    {Node@1, Rem@1, Rem_nl@1, Rem_rest@1} = consume_inline_table(
                        Sp,
                        Rest,
                        Pending_nl,
                        Source_rest
                    ),
                    consume_value(
                        Sp,
                        Rem@1,
                        [{node_element, Node@1} | Acc@1],
                        Rem_nl@1,
                        Rem_rest@1
                    );

                <<"\""/utf8>> ->
                    {Tok_, Rem@2, Rem_nl@2, Rem_rest@2} = molt@internal@parser@scanners:scan_basic_string(
                        Sp,
                        Rest,
                        Pending_nl,
                        Source_rest
                    ),
                    consume_value(
                        Sp,
                        Rem@2,
                        [{token_element, Tok_} | Acc@1],
                        Rem_nl@2,
                        Rem_rest@2
                    );

                <<"'"/utf8>> ->
                    {Tok_@1, Rem@3, Rem_nl@3, Rem_rest@3} = molt@internal@parser@scanners:scan_literal_string(
                        Sp,
                        Rest,
                        Pending_nl,
                        Source_rest
                    ),
                    consume_value(
                        Sp,
                        Rem@3,
                        [{token_element, Tok_@1} | Acc@1],
                        Rem_nl@3,
                        Rem_rest@3
                    );

                <<"#"/utf8>> ->
                    {[{token_element,
                                {token, comment, <<"#"/utf8, Rest/binary>>}} |
                            Acc@1],
                        Pending_nl,
                        Source_rest};

                <<","/utf8>> ->
                    consume_value(
                        Sp,
                        Rest,
                        [{token_element, {token, comma, <<""/utf8>>}} | Acc@1],
                        Pending_nl,
                        Source_rest
                    );

                <<"]"/utf8>> ->
                    consume_value(
                        Sp,
                        Rest,
                        [{token_element, {token, right_bracket, <<""/utf8>>}} |
                            Acc@1],
                        Pending_nl,
                        Source_rest
                    );

                <<"}"/utf8>> ->
                    consume_value(
                        Sp,
                        Rest,
                        [{token_element, {token, right_brace, <<""/utf8>>}} |
                            Acc@1],
                        Pending_nl,
                        Source_rest
                    );

                <<"="/utf8>> ->
                    consume_value(
                        Sp,
                        Rest,
                        [{token_element, {token, equals, <<""/utf8>>}} | Acc@1],
                        Pending_nl,
                        Source_rest
                    );

                _ ->
                    consume_value(Sp, Rest, Acc@1, Pending_nl, Source_rest)
            end
    end.

-file("src/molt/internal/parser.gleam", 222).
?DOC(false).
-spec handle_kv_line(
    molt@internal@parser@core:state(),
    binary(),
    binary(),
    binary()
) -> {molt@internal@parser@core:state(), binary()}.
handle_kv_line(State, Line, Nl, Source_rest) ->
    {Children_rev, After_eq} = molt@internal@parser@scanners:consume_key_and_eq(
        erlang:element(2, State),
        Line,
        []
    ),
    {Children_rev@1, Final_nl, Final_rest} = consume_value(
        erlang:element(2, State),
        After_eq,
        Children_rev,
        Nl,
        Source_rest
    ),
    Children_rev@2 = case Final_nl of
        <<""/utf8>> ->
            Children_rev@1;

        _ ->
            [{token_element, {token, newline, Final_nl}} | Children_rev@1]
    end,
    Children_rev@3 = wrap_dotted_key(Children_rev@2),
    Full = greenwood:node(key_value, Children_rev@3),
    {Leading, State@1} = head_split(State),
    Node = case is_valid_kv(Full) of
        true ->
            {Clean_rev, Trailing} = molt@internal@parser@core:peel_trailing_comment_rev(
                Children_rev@3
            ),
            attach_line_trivia(
                greenwood:node(key_value, Clean_rev),
                Leading,
                Trailing
            );

        false ->
            _pipe = greenwood:node(error, [{node_element, Full}]),
            attach_pending_trivia(_pipe, Leading)
    end,
    State@2 = {state,
        erlang:element(2, State@1),
        [],
        erlang:element(4, State@1),
        erlang:element(5, State@1),
        erlang:element(6, State@1),
        erlang:element(7, State@1),
        erlang:element(8, State@1)},
    {add_kv(State@2, Node), Final_rest}.

-file("src/molt/internal/parser.gleam", 169).
?DOC(false).
-spec handle_table_line(
    molt@internal@parser@core:state(),
    molt@types:toml_kind(),
    binary(),
    binary()
) -> molt@internal@parser@core:state().
handle_table_line(State, Kind, Line, Nl) ->
    Doc_acc = molt@internal@parser@core:flush_current_table(State),
    Header = molt@internal@parser@scanners:tokenize_header_line(
        erlang:element(2, State),
        Line,
        []
    ),
    Header@1 = case Nl of
        <<""/utf8>> ->
            Header;

        _ ->
            [greenwood:token(newline, Nl) | Header]
    end,
    {Children, Trailing} = molt@internal@parser@core:peel_trailing_comment_rev(
        gleam@list:map(Header@1, fun(Field@0) -> {token_element, Field@0} end)
    ),
    {Leading, State@1} = head_split(State),
    {state,
        erlang:element(2, State@1),
        [],
        erlang:element(4, State@1),
        erlang:element(5, State@1),
        Doc_acc,
        {building, Kind, Children, Leading, Trailing},
        erlang:element(8, State@1)}.

-file("src/molt/internal/parser.gleam", 147).
?DOC(false).
-spec handle_comment_line(molt@internal@parser@core:state(), binary(), binary()) -> molt@internal@parser@core:state().
handle_comment_line(State, Line, Nl) ->
    {Pending, Rest@2} = case molt@internal@parser@core:take_ws(Line) of
        {<<""/utf8>>, Rest} ->
            {erlang:element(3, State), Rest};

        {Ws, Rest@1} ->
            {[greenwood:token(whitespace, Ws) | erlang:element(3, State)],
                Rest@1}
    end,
    Pending@1 = [greenwood:token(comment, Rest@2) | Pending],
    Pending@2 = case Nl of
        <<""/utf8>> ->
            Pending@1;

        _ ->
            [greenwood:token(newline, Nl) | Pending@1]
    end,
    {state,
        erlang:element(2, State),
        Pending@2,
        erlang:element(4, State),
        erlang:element(5, State),
        erlang:element(6, State),
        erlang:element(7, State),
        erlang:element(8, State)}.

-file("src/molt/internal/parser.gleam", 131).
?DOC(false).
-spec handle_blank_line(molt@internal@parser@core:state(), binary(), binary()) -> molt@internal@parser@core:state().
handle_blank_line(State, Line, Nl) ->
    Pending = case Line of
        <<""/utf8>> ->
            erlang:element(3, State);

        _ ->
            [greenwood:token(whitespace, Line) | erlang:element(3, State)]
    end,
    Pending@1 = case Nl of
        <<""/utf8>> ->
            Pending;

        _ ->
            [greenwood:token(newline, Nl) | Pending]
    end,
    {state,
        erlang:element(2, State),
        Pending@1,
        erlang:element(4, State),
        erlang:element(5, State),
        erlang:element(6, State),
        erlang:element(7, State),
        erlang:element(8, State)}.

-file("src/molt/internal/parser.gleam", 110).
?DOC(false).
-spec dispatch_line(
    molt@internal@parser@core:state(),
    {binary(), binary(), binary()}
) -> {molt@internal@parser@core:state(), binary()}.
dispatch_line(State, Split_line) ->
    {Line, Nl, Rest} = Split_line,
    case molt@internal@parser@core:peek_first_significant(Line) of
        <<""/utf8>> ->
            {handle_blank_line(State, Line, Nl), Rest};

        <<"#"/utf8, _/binary>> ->
            {handle_comment_line(State, Line, Nl), Rest};

        <<"[["/utf8, _/binary>> ->
            {handle_table_line(State, array_of_tables, Line, Nl), Rest};

        <<"["/utf8, _/binary>> ->
            {handle_table_line(State, table, Line, Nl), Rest};

        _ ->
            handle_kv_line(State, Line, Nl, Rest)
    end.

-file("src/molt/internal/parser.gleam", 106).
?DOC(false).
-spec process_line(molt@internal@parser@core:state(), binary()) -> {molt@internal@parser@core:state(),
    binary()}.
process_line(State, Input) ->
    dispatch_line(
        State,
        splitter_ffi:split(erlang:element(2, erlang:element(2, State)), Input)
    ).

-file("src/molt/internal/parser.gleam", 94).
?DOC(false).
-spec do_parse(molt@internal@parser@core:state(), binary()) -> {ok,
        greenwood:node_(molt@types:toml_kind())} |
    {error, molt@error:molt_error()}.
do_parse(State, Input) ->
    gleam@result:'try'(
        erlang:element(8, State),
        fun(_use0) ->
            nil = _use0,
            case Input of
                <<""/utf8>> ->
                    molt@internal@parser@core:finalize(State);

                _ ->
                    {State@1, Remaining} = process_line(State, Input),
                    do_parse(State@1, Remaining)
            end
        end
    ).

-file("src/molt/internal/parser.gleam", 73).
?DOC(false).
-spec do_scan_control(splitter:splitter(), binary(), integer()) -> {ok, nil} |
    {error, molt@error:molt_error()}.
do_scan_control(Controls, Input, Offset) ->
    {Prefix, Delim, Input@1} = splitter_ffi:split(Controls, Input),
    Here = Offset + erlang:byte_size(Prefix),
    case Delim of
        <<""/utf8>> ->
            {ok, nil};

        <<"\x{FEFF}"/utf8>> ->
            {error, {parse_error, <<"BOM not at start of file"/utf8>>, Here}};

        <<"\x{0000}"/utf8>> ->
            {error, {parse_error, <<"Null byte in input"/utf8>>, Here}};

        <<"\r"/utf8>> ->
            case Input@1 of
                <<"\n"/utf8, More/binary>> ->
                    do_scan_control(Controls, More, Here + 2);

                _ ->
                    {error,
                        {parse_error, <<"Bare carriage return"/utf8>>, Here}}
            end;

        _ ->
            {error, {parse_error, <<"Forbidden control character"/utf8>>, Here}}
    end.

-file("src/molt/internal/parser.gleam", 61).
?DOC(false).
-spec scan_control(binary()) -> {ok, nil} | {error, molt@error:molt_error()}.
scan_control(Source) ->
    _pipe = splitter:new(
        [<<"\x{0000}"/utf8>>,
            <<"\x{0001}"/utf8>>,
            <<"\x{0002}"/utf8>>,
            <<"\x{0003}"/utf8>>,
            <<"\x{0004}"/utf8>>,
            <<"\x{0005}"/utf8>>,
            <<"\x{0006}"/utf8>>,
            <<"\x{0007}"/utf8>>,
            <<"\x{0008}"/utf8>>,
            <<"\x{000B}"/utf8>>,
            <<"\x{000C}"/utf8>>,
            <<"\x{000E}"/utf8>>,
            <<"\x{000F}"/utf8>>,
            <<"\x{0010}"/utf8>>,
            <<"\x{0011}"/utf8>>,
            <<"\x{0012}"/utf8>>,
            <<"\x{0013}"/utf8>>,
            <<"\x{0014}"/utf8>>,
            <<"\x{0015}"/utf8>>,
            <<"\x{0016}"/utf8>>,
            <<"\x{0017}"/utf8>>,
            <<"\x{0018}"/utf8>>,
            <<"\x{0019}"/utf8>>,
            <<"\x{001A}"/utf8>>,
            <<"\x{001B}"/utf8>>,
            <<"\x{001C}"/utf8>>,
            <<"\x{001D}"/utf8>>,
            <<"\x{001E}"/utf8>>,
            <<"\x{001F}"/utf8>>,
            <<"\x{007F}"/utf8>>,
            <<"\x{FEFF}"/utf8>>,
            <<"\r"/utf8>>]
    ),
    do_scan_control(_pipe, Source, 0).

-file("src/molt/internal/parser.gleam", 47).
?DOC(false).
-spec parse(binary()) -> {ok, greenwood:node_(molt@types:toml_kind())} |
    {error, molt@error:molt_error()}.
parse(Source) ->
    {Bom, Source@1} = case Source of
        <<"\x{FEFF}"/utf8, Rest/binary>> ->
            {<<"\x{FEFF}"/utf8>>, Rest};

        _ ->
            {<<""/utf8>>, Source}
    end,
    gleam@result:'try'(
        scan_control(Source@1),
        fun(_) -> _pipe = molt@internal@parser@core:new_state(Bom),
            do_parse(_pipe, Source@1) end
    ).