-module(molt@internal@validate). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/molt/internal/validate.gleam"). -export([count/1, enrich/1]). -export_type([path_entry/0, value_kind/0, pos/0, collector/1, state/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). -type path_entry() :: {explicit_table, molt@types:span()} | {explicit_array_of_tables, integer(), molt@types:span()} | {header_implicit, molt@types:span()} | {dotted_implicit, molt@types:span()} | {closed_implicit, molt@types:span()} | {explicit_scalar, molt@types:span()} | {explicit_inline_table, molt@types:span()} | {explicit_inline_array, molt@types:span()}. -type value_kind() :: scalar_value | inline_table_value | inline_array_value. -type pos() :: {pos, integer(), integer(), integer()}. -type collector(INE) :: {collector, INE, boolean(), fun((INE, fun(() -> molt@types:syntax_error())) -> INE)}. -type state(INF) :: {state, collector(INF), INF, pos(), list(binary()), list(list(binary())), gleam@dict:dict(list(binary()), path_entry()), gleam@dict:dict(list(binary()), integer()), integer()}. -file("src/molt/internal/validate.gleam", 292). ?DOC(false). -spec pop_path(state(IOD)) -> state(IOD). pop_path(State) -> case erlang:element(6, State) of [Parent | Rest] -> {state, erlang:element(2, State), erlang:element(3, State), erlang:element(4, State), Parent, Rest, erlang:element(7, State), erlang:element(8, State), erlang:element(9, State)}; [] -> State end. -file("src/molt/internal/validate.gleam", 272). ?DOC(false). -spec exit_node(state(INV), greenwood:node_(molt@types:toml_kind())) -> state(INV). exit_node(State, Node) -> gleam@bool:guard( erlang:element(2, Node) =:= root, State, fun() -> gleam@bool:guard( erlang:element(2, Node) =:= error, {state, erlang:element(2, State), erlang:element(3, State), erlang:element(4, State), erlang:element(5, State), erlang:element(6, State), erlang:element(7, State), erlang:element(8, State), erlang:element(9, State) - 1}, fun() -> State@1 = case erlang:element(2, Node) of array -> {state, erlang:element(2, State), erlang:element(3, State), erlang:element(4, State), erlang:element(5, State), erlang:element(6, State), erlang:element(7, State), erlang:element(8, State), erlang:element(9, State) - 1}; inline_table -> {state, erlang:element(2, State), erlang:element(3, State), erlang:element(4, State), erlang:element(5, State), erlang:element(6, State), erlang:element(7, State), erlang:element(8, State), erlang:element(9, State) - 1}; _ -> State end, pop_path(State@1) end ) end ). -file("src/molt/internal/validate.gleam", 288). ?DOC(false). -spec push_path(state(INZ), list(binary())) -> state(INZ). push_path(State, New_path) -> {state, erlang:element(2, State), erlang:element(3, State), erlang:element(4, State), New_path, [erlang:element(5, State) | erlang:element(6, State)], erlang:element(7, State), erlang:element(8, State), erlang:element(9, State)}. -file("src/molt/internal/validate.gleam", 388). ?DOC(false). -spec pos_span(pos()) -> molt@types:span(). pos_span(Pos) -> {span, erlang:element(2, Pos), erlang:element(3, Pos), erlang:element(4, Pos)}. -file("src/molt/internal/validate.gleam", 380). ?DOC(false). -spec make_error(state(any()), molt@types:syntax_error_kind(), list(binary())) -> molt@types:syntax_error(). make_error(State, Kind, Path) -> {syntax_error, Kind, Path, pos_span(erlang:element(4, State))}. -file("src/molt/internal/validate.gleam", 190). ?DOC(false). -spec emit(state(INO), fun(() -> molt@types:syntax_error())) -> state(INO). emit(State, Build) -> {state, erlang:element(2, State), (erlang:element(4, erlang:element(2, State)))( erlang:element(3, State), Build ), erlang:element(4, State), erlang:element(5, State), erlang:element(6, State), erlang:element(7, State), erlang:element(8, State), erlang:element(9, State)}. -file("src/molt/internal/validate.gleam", 724). ?DOC(false). -spec push_error(state(IQS), molt@types:syntax_error_kind(), list(binary())) -> state(IQS). push_error(State, Kind, Path) -> emit(State, fun() -> make_error(State, Kind, Path) end). -file("src/molt/internal/validate.gleam", 1039). ?DOC(false). -spec do_inline_commas_ok( list(greenwood:element(molt@types:toml_kind())), boolean() ) -> boolean(). do_inline_commas_ok(Children, Seen_entry) -> case Children of [] -> true; [{token_element, {token, left_brace, _}} | Rest] -> do_inline_commas_ok(Rest, false); [{token_element, {token, right_brace, _}} | Rest@1] -> do_inline_commas_ok(Rest@1, false); [{token_element, {token, comma, _}} | Rest@2] -> case Seen_entry of true -> do_inline_commas_ok(Rest@2, false); false -> false end; [{token_element, {token, whitespace, _}} | Rest@3] -> do_inline_commas_ok(Rest@3, Seen_entry); [{token_element, {token, newline, _}} | Rest@3] -> do_inline_commas_ok(Rest@3, Seen_entry); [{token_element, {token, comment, _}} | Rest@3] -> do_inline_commas_ok(Rest@3, Seen_entry); [_ | Rest@4] -> do_inline_commas_ok(Rest@4, true) end. -file("src/molt/internal/validate.gleam", 1035). ?DOC(false). -spec inline_table_commas_ok(list(greenwood:element(molt@types:toml_kind()))) -> boolean(). inline_table_commas_ok(Children) -> do_inline_commas_ok(Children, false). -file("src/molt/internal/validate.gleam", 1066). ?DOC(false). -spec do_inline_bare_ok( list(greenwood:element(molt@types:toml_kind())), boolean() ) -> boolean(). do_inline_bare_ok(Children, After_eq) -> case Children of [] -> true; [{token_element, {token, equals, _}} | Rest] -> do_inline_bare_ok(Rest, true); [{token_element, {token, comma, _}} | Rest@1] -> do_inline_bare_ok(Rest@1, false); [{token_element, {token, invalid_value, _}} | _] -> false; [{token_element, {token, invalid_basic_string, _}} | _] -> false; [{token_element, {token, invalid_literal_string, _}} | _] -> false; [{token_element, {token, invalid_multiline_basic_string, _}} | _] -> false; [{token_element, {token, invalid_multiline_literal_string, _}} | _] -> false; [{token_element, {token, bare_key, _}} | _] when After_eq -> false; [_ | Rest@2] -> do_inline_bare_ok(Rest@2, After_eq) end. -file("src/molt/internal/validate.gleam", 1062). ?DOC(false). -spec inline_table_bare_values_ok( list(greenwood:element(molt@types:toml_kind())) ) -> boolean(). inline_table_bare_values_ok(Children) -> do_inline_bare_ok(Children, false). -file("src/molt/internal/validate.gleam", 392). ?DOC(false). -spec entry_span(path_entry()) -> molt@types:span(). entry_span(Entry) -> case Entry of {explicit_table, Span} -> Span; {explicit_array_of_tables, _, Span@1} -> Span@1; {header_implicit, Span@2} -> Span@2; {dotted_implicit, Span@3} -> Span@3; {closed_implicit, Span@4} -> Span@4; {explicit_scalar, Span@5} -> Span@5; {explicit_inline_table, Span@6} -> Span@6; {explicit_inline_array, Span@7} -> Span@7 end. -file("src/molt/internal/validate.gleam", 674). ?DOC(false). -spec value_kind_entry(value_kind(), pos()) -> path_entry(). value_kind_entry(Value_kind, Pos) -> Span = pos_span(Pos), case Value_kind of scalar_value -> {explicit_scalar, Span}; inline_table_value -> {explicit_inline_table, Span}; inline_array_value -> {explicit_inline_array, Span} end. -file("src/molt/internal/validate.gleam", 1230). ?DOC(false). -spec last_or_empty(list(binary())) -> binary(). last_or_empty(L) -> _pipe = gleam@list:last(L), gleam@result:unwrap(_pipe, <<""/utf8>>). -file("src/molt/internal/validate.gleam", 1222). ?DOC(false). -spec list_init(list(binary())) -> list(binary()). list_init(L) -> case L of [] -> []; [_] -> []; _ -> gleam@list:take(L, erlang:length(L) - 1) end. -file("src/molt/internal/validate.gleam", 686). ?DOC(false). -spec emit_descent_error( state(IQJ), list(binary()), fun((binary()) -> molt@types:syntax_error_kind()) ) -> state(IQJ). emit_descent_error(State, Prefix, Kind_with_key) -> Key = last_or_empty(Prefix), Parent = list_init(Prefix), emit(State, fun() -> make_error(State, Kind_with_key(Key), Parent) end). -file("src/molt/internal/validate.gleam", 619). ?DOC(false). -spec register_dotted_implicit_parents(state(IQD), list(list(binary()))) -> state(IQD). register_dotted_implicit_parents(State, Parent_paths) -> Span = pos_span(erlang:element(4, State)), gleam@list:fold( Parent_paths, State, fun(State@1, Prefix) -> case gleam_stdlib:map_get(erlang:element(7, State@1), Prefix) of {error, nil} -> {state, erlang:element(2, State@1), erlang:element(3, State@1), erlang:element(4, State@1), erlang:element(5, State@1), erlang:element(6, State@1), gleam@dict:insert( erlang:element(7, State@1), Prefix, {dotted_implicit, Span} ), erlang:element(8, State@1), erlang:element(9, State@1)}; {ok, {dotted_implicit, _}} -> State@1; {ok, {explicit_scalar, Original}} -> emit_descent_error( State@1, Prefix, fun(Key) -> {key_is_scalar, Key, Original} end ); {ok, {explicit_inline_table, Original@1}} -> emit_descent_error( State@1, Prefix, fun(Key@1) -> {key_is_inline_table, Key@1, Original@1} end ); {ok, {explicit_inline_array, Original@2}} -> emit_descent_error( State@1, Prefix, fun(Key@2) -> {key_is_array, Key@2, Original@2} end ); {ok, Entry} -> Original@3 = entry_span(Entry), emit( State@1, fun() -> make_error( State@1, {duplicate_table, Original@3}, Prefix ) end ) end end ). -file("src/molt/internal/validate.gleam", 558). ?DOC(false). -spec register_kv_path(state(IPU), list(binary()), list(binary()), value_kind()) -> state(IPU). register_kv_path(State, Table_path, Segments, Value_kind) -> Full_path = lists:append(Table_path, Segments), Table_len = erlang:length(Table_path), Dotted_prefixes = gleam@list:drop( molt@internal@utils:all_prefixes(Full_path), Table_len ), State@1 = register_dotted_implicit_parents(State, Dotted_prefixes), Key = last_or_empty(Segments), Entry = value_kind_entry(Value_kind, erlang:element(4, State@1)), case gleam_stdlib:map_get(erlang:element(7, State@1), Full_path) of {error, nil} -> {state, erlang:element(2, State@1), erlang:element(3, State@1), erlang:element(4, State@1), erlang:element(5, State@1), erlang:element(6, State@1), gleam@dict:insert(erlang:element(7, State@1), Full_path, Entry), erlang:element(8, State@1), erlang:element(9, State@1)}; {ok, Existing} -> Original = entry_span(Existing), State@2 = {state, erlang:element(2, State@1), erlang:element(3, State@1), erlang:element(4, State@1), erlang:element(5, State@1), erlang:element(6, State@1), gleam@dict:insert(erlang:element(7, State@1), Full_path, Entry), erlang:element(8, State@1), erlang:element(9, State@1)}, emit( State@2, fun() -> make_error( State@2, {duplicate_key, Key, Original}, Table_path ) end ) end. -file("src/molt/internal/validate.gleam", 128). ?DOC(false). -spec enrich_collector() -> collector(list(molt@types:syntax_error())). enrich_collector() -> {collector, [], true, fun(Errors, Build) -> [Build() | Errors] end}. -file("src/molt/internal/validate.gleam", 1212). ?DOC(false). -spec skip_inline_value(list(greenwood:element(molt@types:toml_kind()))) -> list(greenwood:element(molt@types:toml_kind())). skip_inline_value(Children) -> case molt@internal@cst@elements:skip_all_trivia(Children) of [] -> []; [{node_element, _} | Rest] -> Rest; [{token_element, _} | Rest@1] -> Rest@1 end. -file("src/molt/internal/validate.gleam", 1202). ?DOC(false). -spec skip_to_equals_value(list(greenwood:element(molt@types:toml_kind()))) -> list(greenwood:element(molt@types:toml_kind())). skip_to_equals_value(Children) -> case Children of [] -> []; [{token_element, {token, equals, _}} | Rest] -> Rest; [_ | Rest@1] -> skip_to_equals_value(Rest@1) end. -file("src/molt/internal/validate.gleam", 1154). ?DOC(false). -spec take_inline_key_segments( list(greenwood:element(molt@types:toml_kind())), list(binary()) ) -> {list(binary()), list(greenwood:element(molt@types:toml_kind()))}. take_inline_key_segments(Children, Acc) -> case molt@internal@cst@elements:skip_all_trivia(Children) of [] -> {lists:reverse(Acc), []}; [{token_element, {token, equals, _}} | _] = Rest -> {lists:reverse(Acc), Rest}; [{token_element, {token, bare_key, Text}} | Rest@1] -> Segs = begin _pipe = gleam@string:split(Text, <<"."/utf8>>), gleam@list:filter(_pipe, fun(S) -> S /= <<""/utf8>> end) end, take_inline_key_segments( Rest@1, lists:append(lists:reverse(Segs), Acc) ); [{token_element, {token, integer, Text@1}} | Rest@2] -> take_inline_key_segments(Rest@2, [Text@1 | Acc]); [{token_element, {token, basic_string, Text@2}} | Rest@3] -> take_inline_key_segments( Rest@3, [molt@internal@utils:unescape_basic_string(Text@2) | Acc] ); [{token_element, {token, literal_string, Text@3}} | Rest@4] -> take_inline_key_segments(Rest@4, [Text@3 | Acc]); [{token_element, {token, dot, _}} | Rest@5] -> take_inline_key_segments(Rest@5, Acc); [_ | Rest@6] -> take_inline_key_segments(Rest@6, Acc) end. -file("src/molt/internal/validate.gleam", 1177). ?DOC(false). -spec take_inline_key_segments_from_kv( list(greenwood:element(molt@types:toml_kind())), list(binary()) ) -> list(binary()). take_inline_key_segments_from_kv(Children, Acc) -> case Children of [] -> lists:reverse(Acc); [{token_element, {token, equals, _}} | _] -> lists:reverse(Acc); [{token_element, {token, whitespace, _}} | Rest] -> take_inline_key_segments_from_kv(Rest, Acc); [{token_element, {token, dot, _}} | Rest] -> take_inline_key_segments_from_kv(Rest, Acc); [{token_element, {token, bare_key, Text}} | Rest@1] -> take_inline_key_segments_from_kv(Rest@1, [Text | Acc]); [{token_element, {token, integer, Text@1}} | Rest@2] -> take_inline_key_segments_from_kv(Rest@2, [Text@1 | Acc]); [{token_element, {token, basic_string, Text@2}} | Rest@3] -> take_inline_key_segments_from_kv( Rest@3, [molt@internal@utils:unescape_basic_string(Text@2) | Acc] ); [{token_element, {token, literal_string, Text@3}} | Rest@4] -> take_inline_key_segments_from_kv(Rest@4, [Text@3 | Acc]); [_ | Rest@5] -> take_inline_key_segments_from_kv(Rest@5, Acc) end. -file("src/molt/internal/validate.gleam", 1125). ?DOC(false). -spec extract_inline_key_paths( list(greenwood:element(molt@types:toml_kind())), list(list(binary())) ) -> list(list(binary())). extract_inline_key_paths(Children, Acc) -> case molt@internal@cst@elements:skip_all_trivia(Children) of [] -> lists:reverse(Acc); [{token_element, {token, left_brace, _}} | Rest] -> extract_inline_key_paths(Rest, Acc); [{token_element, {token, right_brace, _}} | _] -> lists:reverse(Acc); [{token_element, {token, comma, _}} | Rest@1] -> extract_inline_key_paths(Rest@1, Acc); [{node_element, N} | Rest@2] when erlang:element(2, N) =:= key_value -> case take_inline_key_segments_from_kv(erlang:element(3, N), []) of [] -> extract_inline_key_paths(Rest@2, Acc); Segments -> extract_inline_key_paths(Rest@2, [Segments | Acc]) end; Rest@3 -> {Segments@1, After_key} = take_inline_key_segments(Rest@3, []), After_eq = skip_to_equals_value(After_key), After_value = skip_inline_value(After_eq), case Segments@1 of [] -> extract_inline_key_paths(After_value, Acc); _ -> extract_inline_key_paths(After_value, [Segments@1 | Acc]) end end. -file("src/molt/internal/validate.gleam", 1088). ?DOC(false). -spec inline_table_first_duplicate_key( list(greenwood:element(molt@types:toml_kind())) ) -> gleam@option:option(binary()). inline_table_first_duplicate_key(Children) -> Key_paths = extract_inline_key_paths(Children, []), State = {state, enrich_collector(), [], {pos, 0, 0, 0}, [], [], maps:new(), maps:new(), 0}, State@2 = gleam@list:fold( Key_paths, State, fun(State@1, Segments) -> register_kv_path(State@1, [], Segments, scalar_value) end ), _pipe = lists:reverse(erlang:element(3, State@2)), _pipe@1 = gleam@list:find_map( _pipe, fun(Err) -> case erlang:element(2, Err) of {duplicate_key, Key, _} -> {ok, Key}; {key_is_scalar, Key, _} -> {ok, Key}; {key_is_inline_table, Key, _} -> {ok, Key}; {key_is_array, Key, _} -> {ok, Key}; _ -> {error, nil} end end ), gleam@option:from_result(_pipe@1). -file("src/molt/internal/validate.gleam", 1026). ?DOC(false). -spec inline_table_is_closed(list(greenwood:element(molt@types:toml_kind()))) -> boolean(). inline_table_is_closed(Children) -> gleam@list:any(Children, fun(El) -> case El of {token_element, {token, right_brace, _}} -> true; _ -> false end end). -file("src/molt/internal/validate.gleam", 770). ?DOC(false). -spec check_inline_table_syntax( state(IRG), greenwood:node_(molt@types:toml_kind()), list(binary()) ) -> state(IRG). check_inline_table_syntax(State, Node, Path) -> State@1 = case inline_table_is_closed(erlang:element(3, Node)) of true -> State; false -> push_error(State, unterminated_inline_table, Path) end, State@2 = case inline_table_first_duplicate_key(erlang:element(3, Node)) of none -> State@1; {some, Key} -> push_error(State@1, {duplicate_key_in_inline_table, Key}, Path) end, State@3 = case inline_table_bare_values_ok(erlang:element(3, Node)) of true -> State@2; false -> push_error(State@2, invalid_bare_value_in_inline_table, Path) end, case inline_table_commas_ok(erlang:element(3, Node)) of true -> State@3; false -> push_error(State@3, misplaced_inline_table_separator, Path) end. -file("src/molt/internal/validate.gleam", 1011). ?DOC(false). -spec do_element_value_count( list(greenwood:element(molt@types:toml_kind())), integer() ) -> boolean(). do_element_value_count(Children, Count) -> case Children of [] -> Count =:= 1; [{token_element, {token, whitespace, _}} | Rest] -> do_element_value_count(Rest, Count); [{token_element, {token, newline, _}} | Rest] -> do_element_value_count(Rest, Count); [{token_element, {token, comment, _}} | Rest] -> do_element_value_count(Rest, Count); [{token_element, {token, comma, _}} | Rest] -> do_element_value_count(Rest, Count); [_ | Rest@1] -> do_element_value_count(Rest@1, Count + 1) end. -file("src/molt/internal/validate.gleam", 1007). ?DOC(false). -spec element_has_single_value(list(greenwood:element(molt@types:toml_kind()))) -> boolean(). element_has_single_value(Children) -> do_element_value_count(Children, 0). -file("src/molt/internal/validate.gleam", 990). ?DOC(false). -spec do_array_seps_ok(list(greenwood:element(molt@types:toml_kind()))) -> boolean(). do_array_seps_ok(Children) -> case Children of [] -> true; [{token_element, {token, right_bracket, _}} | _] -> true; [{token_element, {token, left_bracket, _}} | Rest] -> do_array_seps_ok(Rest); [{token_element, {token, whitespace, _}} | Rest@1] -> do_array_seps_ok(Rest@1); [{token_element, {token, newline, _}} | Rest@1] -> do_array_seps_ok(Rest@1); [{token_element, {token, comment, _}} | Rest@1] -> do_array_seps_ok(Rest@1); [{node_element, N} | Rest@2] when erlang:element(2, N) =:= array_element -> gleam@bool:guard( not element_has_single_value(erlang:element(3, N)), false, fun() -> do_array_seps_ok(Rest@2) end ); [{token_element, {token, comma, _}} | _] -> false; [_ | _] -> false end. -file("src/molt/internal/validate.gleam", 986). ?DOC(false). -spec array_separators_ok(list(greenwood:element(molt@types:toml_kind()))) -> boolean(). array_separators_ok(Children) -> do_array_seps_ok(Children). -file("src/molt/internal/validate.gleam", 977). ?DOC(false). -spec array_is_closed(list(greenwood:element(molt@types:toml_kind()))) -> boolean(). array_is_closed(Children) -> gleam@list:any(Children, fun(El) -> case El of {token_element, {token, right_bracket, _}} -> true; _ -> false end end). -file("src/molt/internal/validate.gleam", 753). ?DOC(false). -spec check_array_syntax( state(IRB), greenwood:node_(molt@types:toml_kind()), list(binary()) ) -> state(IRB). check_array_syntax(State, Node, Path) -> State@1 = case array_is_closed(erlang:element(3, Node)) of true -> State; false -> push_error(State, unterminated_array, Path) end, gleam@bool:guard( array_separators_ok(erlang:element(3, Node)), State@1, fun() -> push_error(State@1, misplaced_array_separator, Path) end ). -file("src/molt/internal/validate.gleam", 865). ?DOC(false). -spec do_has_single_value( list(greenwood:element(molt@types:toml_kind())), boolean() ) -> boolean(). do_has_single_value(Children, Saw_value) -> case Children of [] -> true; [{token_element, {token, whitespace, _}} | Rest] -> do_has_single_value(Rest, Saw_value); [{token_element, {token, newline, _}} | Rest] -> do_has_single_value(Rest, Saw_value); [{token_element, {token, comment, _}} | Rest] -> do_has_single_value(Rest, Saw_value); [{token_element, {token, comma, _}} | Rest] -> do_has_single_value(Rest, Saw_value); [_ | Rest@1] -> gleam@bool:guard( Saw_value, false, fun() -> do_has_single_value(Rest@1, true) end ) end. -file("src/molt/internal/validate.gleam", 861). ?DOC(false). -spec has_single_value(list(greenwood:element(molt@types:toml_kind()))) -> boolean(). has_single_value(Value_tokens) -> do_has_single_value(Value_tokens, false). -file("src/molt/internal/validate.gleam", 852). ?DOC(false). -spec has_extra_equals(list(greenwood:element(molt@types:toml_kind()))) -> boolean(). has_extra_equals(Value_tokens) -> gleam@list:any(Value_tokens, fun(El) -> case El of {token_element, {token, equals, _}} -> true; _ -> false end end). -file("src/molt/internal/validate.gleam", 840). ?DOC(false). -spec has_value(list(greenwood:element(molt@types:toml_kind()))) -> boolean(). has_value(Value_tokens) -> gleam@list:any(Value_tokens, fun(El) -> case El of {token_element, {token, whitespace, _}} -> false; {token_element, {token, newline, _}} -> false; {token_element, {token, comment, _}} -> false; {token_element, {token, equals, _}} -> false; _ -> true end end). -file("src/molt/internal/validate.gleam", 800). ?DOC(false). -spec do_check_key_tokens_ok( list(greenwood:element(molt@types:toml_kind())), boolean() ) -> boolean(). do_check_key_tokens_ok(Children, Seen_key) -> case Children of [] -> Seen_key; [{token_element, {token, equals, _}} | _] -> Seen_key; [{token_element, {token, whitespace, _}} | Rest] -> do_check_key_tokens_ok(Rest, Seen_key); [{token_element, {token, dot, _}} | Rest@1] -> case Seen_key of true -> do_check_key_tokens_ok(Rest@1, false); false -> false end; [{token_element, {token, bare_key, Text}} | Rest@2] -> case Seen_key of true -> false; false -> case molt@internal@utils:is_bare_key(Text) of true -> do_check_key_tokens_ok(Rest@2, true); false -> false end end; [{token_element, {token, integer, _}} | Rest@3] -> case Seen_key of true -> false; false -> do_check_key_tokens_ok(Rest@3, true) end; [{token_element, {token, basic_string, _}} | Rest@3] -> case Seen_key of true -> false; false -> do_check_key_tokens_ok(Rest@3, true) end; [{token_element, {token, literal_string, _}} | Rest@3] -> case Seen_key of true -> false; false -> do_check_key_tokens_ok(Rest@3, true) end; [{node_element, N} | Rest@4] when erlang:element(2, N) =:= key -> case check_key_tokens_ok(N) of true -> do_check_key_tokens_ok(Rest@4, true); false -> false end; _ -> false end. -file("src/molt/internal/validate.gleam", 796). ?DOC(false). -spec check_key_tokens_ok(greenwood:node_(molt@types:toml_kind())) -> boolean(). check_key_tokens_ok(Kv) -> do_check_key_tokens_ok(erlang:element(3, Kv), false). -file("src/molt/internal/validate.gleam", 698). ?DOC(false). -spec check_kv_syntax( state(IQN), greenwood:node_(molt@types:toml_kind()), list(binary()) ) -> state(IQN). check_kv_syntax(State, Node, Path) -> State@1 = case check_key_tokens_ok(Node) of true -> State; false -> push_error(State, invalid_key_syntax, Path) end, Value_tokens = molt@internal@cst@elements:value_tokens( erlang:element(3, Node) ), State@2 = case has_value(Value_tokens) of true -> State@1; false -> push_error(State@1, missing_value, Path) end, State@3 = case has_extra_equals(Value_tokens) of false -> State@2; true -> push_error(State@2, extra_equals, Path) end, case has_single_value(Value_tokens) of true -> State@3; false -> push_error(State@3, multiple_values, Path) end. -file("src/molt/internal/validate.gleam", 661). ?DOC(false). -spec kv_value_kind(greenwood:node_(molt@types:toml_kind())) -> value_kind(). kv_value_kind(Kv) -> Value_tokens = molt@internal@cst@elements:value_tokens( erlang:element(3, Kv) ), case molt@internal@cst@elements:find_first_value(Value_tokens) of {some, {node_element, N}} -> case erlang:element(2, N) of inline_table -> inline_table_value; array -> inline_array_value; _ -> scalar_value end; _ -> scalar_value end. -file("src/molt/internal/validate.gleam", 538). ?DOC(false). -spec register_kv( state(IPP), list(binary()), greenwood:node_(molt@types:toml_kind()) ) -> state(IPP). register_kv(State, Table_path, Kv) -> case molt@internal@cst@elements:key_path(erlang:element(3, Kv)) of none -> emit( State, fun() -> make_error(State, invalid_key_syntax, Table_path) end ); {some, Segments} -> register_kv_path(State, Table_path, Segments, kv_value_kind(Kv)) end. -file("src/molt/internal/validate.gleam", 967). ?DOC(false). -spec only_trailing_trivia(list(greenwood:element(molt@types:toml_kind()))) -> boolean(). only_trailing_trivia(Children) -> case Children of [] -> true; [{token_element, {token, newline, _}} | _] -> true; [{token_element, {token, whitespace, _}} | Rest] -> only_trailing_trivia(Rest); [{token_element, {token, comment, _}} | Rest] -> only_trailing_trivia(Rest); _ -> false end. -file("src/molt/internal/validate.gleam", 908). ?DOC(false). -spec consume_brackets_ok( list(greenwood:element(molt@types:toml_kind())), integer(), molt@types:toml_kind() ) -> {ok, list(greenwood:element(molt@types:toml_kind()))} | {error, nil}. consume_brackets_ok(Children, Count, Bracket) -> gleam@bool:guard(Count =:= 0, {ok, Children}, fun() -> case Children of [{token_element, {token, K, _}} | Children@1] when K =:= Bracket -> consume_brackets_ok(Children@1, Count - 1, Bracket); _ -> {error, nil} end end). -file("src/molt/internal/validate.gleam", 940). ?DOC(false). -spec do_check_header_keys_ok( list(greenwood:element(molt@types:toml_kind())), boolean() ) -> boolean(). do_check_header_keys_ok(Tokens, Seen_key) -> case Tokens of [] -> Seen_key; [{token_element, {token, whitespace, _}} | Rest] -> do_check_header_keys_ok(Rest, Seen_key); [{token_element, {token, dot, _}} | Rest@1] -> gleam@bool:guard( not Seen_key, false, fun() -> do_check_header_keys_ok(Rest@1, false) end ); [{token_element, {token, bare_key, Text}} | Rest@2] -> gleam@bool:guard( Seen_key, false, fun() -> gleam@bool:guard( not molt@internal@utils:is_bare_key(Text), false, fun() -> do_check_header_keys_ok(Rest@2, true) end ) end ); [{token_element, {token, basic_string, _}} | Rest@3] -> gleam@bool:guard( Seen_key, false, fun() -> do_check_header_keys_ok(Rest@3, true) end ); [{token_element, {token, literal_string, _}} | Rest@3] -> gleam@bool:guard( Seen_key, false, fun() -> do_check_header_keys_ok(Rest@3, true) end ); [{token_element, {token, integer, _}} | Rest@3] -> gleam@bool:guard( Seen_key, false, fun() -> do_check_header_keys_ok(Rest@3, true) end ); _ -> false end. -file("src/molt/internal/validate.gleam", 936). ?DOC(false). -spec check_header_key_tokens_ok( list(greenwood:element(molt@types:toml_kind())) ) -> boolean(). check_header_key_tokens_ok(Tokens) -> do_check_header_keys_ok(Tokens, false). -file("src/molt/internal/validate.gleam", 922). ?DOC(false). -spec take_until_right_bracket( 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_until_right_bracket(Children, Acc) -> case Children of [] -> {lists:reverse(Acc), []}; [{token_element, {token, right_bracket, _}} | _] -> {lists:reverse(Acc), Children}; [El | Rest] -> take_until_right_bracket(Rest, [El | Acc]) end. -file("src/molt/internal/validate.gleam", 883). ?DOC(false). -spec check_table_bracket_shape_ok( list(greenwood:element(molt@types:toml_kind())), integer() ) -> boolean(). check_table_bracket_shape_ok(Children, Expected) -> Children@1 = molt@internal@cst@elements:skip_trivia(Children), case consume_brackets_ok(Children@1, Expected, left_bracket) of {error, nil} -> false; {ok, Rest} -> {Key_tokens, Children@2} = take_until_right_bracket(Rest, []), gleam@bool:guard( not check_header_key_tokens_ok(Key_tokens), false, fun() -> _pipe = consume_brackets_ok( Children@2, Expected, right_bracket ), _pipe@1 = gleam@result:map( _pipe, fun only_trailing_trivia/1 ), gleam@result:unwrap(_pipe@1, false) end ) end. -file("src/molt/internal/validate.gleam", 732). ?DOC(false). -spec check_table_header_syntax( state(IQW), greenwood:node_(molt@types:toml_kind()), list(binary()) ) -> state(IQW). check_table_header_syntax(State, Node, Path) -> gleam@bool:lazy_guard( Path =:= [], fun() -> push_error(State, empty_table_header, Path) end, fun() -> Expected = case erlang:element(2, Node) of array_of_tables -> 2; _ -> 1 end, gleam@bool:guard( check_table_bracket_shape_ok(erlang:element(3, Node), Expected), State, fun() -> push_error(State, malformed_table_header, Path) end ) end ). -file("src/molt/internal/validate.gleam", 437). ?DOC(false). -spec do_scope_path( state(any()), list(binary()), list(binary()), list(binary()), boolean() ) -> list(binary()). do_scope_path(State, Remaining, Raw_current, Scoped_current, Scope_terminal) -> case Remaining of [] -> Scoped_current; [Segment | Rest] -> Raw_prefix = lists:append(Raw_current, [Segment]), Scoped_prefix = lists:append(Scoped_current, [Segment]), Scope_here = Scope_terminal orelse (Rest /= []), case {Scope_here, gleam_stdlib:map_get(erlang:element(8, State), Raw_prefix)} of {true, {ok, Instance}} -> do_scope_path( State, Rest, Raw_prefix, lists:append( Scoped_prefix, [erlang:integer_to_binary(Instance)] ), Scope_terminal ); {_, _} -> do_scope_path( State, Rest, Raw_prefix, Scoped_prefix, Scope_terminal ) end end. -file("src/molt/internal/validate.gleam", 417). ?DOC(false). -spec scope_path(state(any()), list(binary())) -> list(binary()). scope_path(State, Path) -> do_scope_path(State, Path, [], [], true). -file("src/molt/internal/validate.gleam", 589). ?DOC(false). -spec register_header_implicit_parents(state(IPZ), list(binary())) -> state(IPZ). register_header_implicit_parents(State, Path) -> Parent_paths = molt@internal@utils:all_prefixes(Path), Span = pos_span(erlang:element(4, State)), gleam@list:fold( Parent_paths, State, fun(State@1, Prefix) -> case gleam_stdlib:map_get(erlang:element(7, State@1), Prefix) of {error, nil} -> {state, erlang:element(2, State@1), erlang:element(3, State@1), erlang:element(4, State@1), erlang:element(5, State@1), erlang:element(6, State@1), gleam@dict:insert( erlang:element(7, State@1), Prefix, {header_implicit, Span} ), erlang:element(8, State@1), erlang:element(9, State@1)}; {ok, {explicit_scalar, Original}} -> emit_descent_error( State@1, Prefix, fun(Key) -> {key_is_scalar, Key, Original} end ); {ok, {explicit_inline_table, Original@1}} -> emit_descent_error( State@1, Prefix, fun(Key@1) -> {key_is_inline_table, Key@1, Original@1} end ); {ok, {explicit_inline_array, Original@2}} -> emit_descent_error( State@1, Prefix, fun(Key@2) -> {key_is_array, Key@2, Original@2} end ); {ok, _} -> State@1 end end ). -file("src/molt/internal/validate.gleam", 427). ?DOC(false). -spec scope_header_path(state(any()), list(binary())) -> list(binary()). scope_header_path(State, Path) -> do_scope_path(State, Path, [], [], false). -file("src/molt/internal/validate.gleam", 496). ?DOC(false). -spec register_array_of_tables(state(IPL), list(binary())) -> state(IPL). register_array_of_tables(State, Raw_path) -> Span = pos_span(erlang:element(4, State)), Scoped = scope_header_path(State, Raw_path), State@1 = register_header_implicit_parents(State, Scoped), Count = begin _pipe = gleam_stdlib:map_get(erlang:element(8, State@1), Raw_path), gleam@result:unwrap(_pipe, -1) end + 1, State@2 = {state, erlang:element(2, State@1), erlang:element(3, State@1), erlang:element(4, State@1), erlang:element(5, State@1), erlang:element(6, State@1), erlang:element(7, State@1), gleam@dict:insert(erlang:element(8, State@1), Raw_path, Count), erlang:element(9, State@1)}, case gleam_stdlib:map_get(erlang:element(7, State@2), Scoped) of {error, nil} -> {state, erlang:element(2, State@2), erlang:element(3, State@2), erlang:element(4, State@2), erlang:element(5, State@2), erlang:element(6, State@2), gleam@dict:insert( erlang:element(7, State@2), Scoped, {explicit_array_of_tables, Count, Span} ), erlang:element(8, State@2), erlang:element(9, State@2)}; {ok, {explicit_array_of_tables, _, _}} -> {state, erlang:element(2, State@2), erlang:element(3, State@2), erlang:element(4, State@2), erlang:element(5, State@2), erlang:element(6, State@2), gleam@dict:insert( erlang:element(7, State@2), Scoped, {explicit_array_of_tables, Count, Span} ), erlang:element(8, State@2), erlang:element(9, State@2)}; {ok, Entry} -> Original = entry_span(Entry), State@3 = {state, erlang:element(2, State@2), erlang:element(3, State@2), erlang:element(4, State@2), erlang:element(5, State@2), erlang:element(6, State@2), gleam@dict:insert( erlang:element(7, State@2), Scoped, {explicit_array_of_tables, Count, Span} ), erlang:element(8, State@2), erlang:element(9, State@2)}, emit( State@3, fun() -> make_error(State@3, {duplicate_table, Original}, Scoped) end ) end. -file("src/molt/internal/validate.gleam", 405). ?DOC(false). -spec freeze_dotted(state(IOQ)) -> state(IOQ). freeze_dotted(State) -> {state, erlang:element(2, State), erlang:element(3, State), erlang:element(4, State), erlang:element(5, State), erlang:element(6, State), gleam@dict:map_values(erlang:element(7, State), fun(_, V) -> case V of {dotted_implicit, Span} -> {closed_implicit, Span}; _ -> V end end), erlang:element(8, State), erlang:element(9, State)}. -file("src/molt/internal/validate.gleam", 473). ?DOC(false). -spec register_table(state(IPH), list(binary())) -> state(IPH). register_table(State, Path) -> Span = pos_span(erlang:element(4, State)), State@1 = register_header_implicit_parents(State, Path), case gleam_stdlib:map_get(erlang:element(7, State@1), Path) of {error, nil} -> {state, erlang:element(2, State@1), erlang:element(3, State@1), erlang:element(4, State@1), erlang:element(5, State@1), erlang:element(6, State@1), gleam@dict:insert( erlang:element(7, State@1), Path, {explicit_table, Span} ), erlang:element(8, State@1), erlang:element(9, State@1)}; {ok, {header_implicit, _}} -> {state, erlang:element(2, State@1), erlang:element(3, State@1), erlang:element(4, State@1), erlang:element(5, State@1), erlang:element(6, State@1), gleam@dict:insert( erlang:element(7, State@1), Path, {explicit_table, Span} ), erlang:element(8, State@1), erlang:element(9, State@1)}; {ok, Entry} -> Original = entry_span(Entry), State@2 = {state, erlang:element(2, State@1), erlang:element(3, State@1), erlang:element(4, State@1), erlang:element(5, State@1), erlang:element(6, State@1), gleam@dict:insert( erlang:element(7, State@1), Path, {explicit_table, Span} ), erlang:element(8, State@1), erlang:element(9, State@1)}, emit( State@2, fun() -> make_error(State@2, {duplicate_table, Original}, Path) end ) end. -file("src/molt/internal/validate.gleam", 194). ?DOC(false). -spec enter_node(state(INR), greenwood:node_(molt@types:toml_kind())) -> state(INR). enter_node(State, Node) -> case erlang:element(2, Node) of root -> State; error -> State@1 = emit( State, fun() -> make_error( State, unparsable_content, erlang:element(5, State) ) end ), {state, erlang:element(2, State@1), erlang:element(3, 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), erlang:element(9, State@1) + 1}; table -> Table_path = molt@internal@cst@elements:extract_key_segments( erlang:element(3, Node) ), State@2 = freeze_dotted(State), Scoped = scope_header_path(State@2, Table_path), State@3 = push_path(State@2, Scoped), _pipe = register_table(State@3, Scoped), check_table_header_syntax(_pipe, Node, Table_path); array_of_tables -> Table_path@1 = molt@internal@cst@elements:extract_key_segments( erlang:element(3, Node) ), State@4 = begin _pipe@1 = freeze_dotted(State), register_array_of_tables(_pipe@1, Table_path@1) end, Instance = begin _pipe@2 = gleam_stdlib:map_get( erlang:element(8, State@4), Table_path@1 ), gleam@result:unwrap(_pipe@2, 1) end - 1, Last = last_or_empty(Table_path@1), Scoped_parent = scope_path(State@4, list_init(Table_path@1)), Scoped_path = lists:append( Scoped_parent, [Last, erlang:integer_to_binary(Instance)] ), _pipe@3 = push_path(State@4, Scoped_path), check_table_header_syntax(_pipe@3, Node, Table_path@1); key_value -> State@5 = case erlang:element(9, State) of 0 -> register_kv(State, erlang:element(5, State), Node); _ -> State end, Kv_path = lists:append( erlang:element(5, State@5), begin _pipe@4 = molt@internal@cst@elements:key_path( erlang:element(3, Node) ), gleam@option:unwrap(_pipe@4, []) end ), _pipe@5 = push_path(State@5, Kv_path), check_kv_syntax(_pipe@5, Node, Kv_path); array -> State@6 = {state, erlang:element(2, State), erlang:element(3, State), erlang:element(4, State), erlang:element(5, State), erlang:element(6, State), erlang:element(7, State), erlang:element(8, State), erlang:element(9, State) + 1}, State@7 = push_path(State@6, erlang:element(5, State@6)), check_array_syntax(State@7, Node, erlang:element(5, State@7)); inline_table -> State@8 = {state, erlang:element(2, State), erlang:element(3, State), erlang:element(4, State), erlang:element(5, State), erlang:element(6, State), erlang:element(7, State), erlang:element(8, State), erlang:element(9, State) + 1}, State@9 = push_path(State@8, erlang:element(5, State@8)), check_inline_table_syntax(State@9, Node, erlang:element(5, State@9)); _ -> push_path(State, erlang:element(5, State)) end. -file("src/molt/internal/validate.gleam", 361). ?DOC(false). -spec count_newlines(binary(), integer(), integer()) -> {integer(), integer()}. count_newlines(Text, Line, Col) -> case Text of <<""/utf8>> -> {Line, Col}; <<"\r\n"/utf8, Rest/binary>> -> count_newlines(Rest, Line + 1, 1); <<"\n"/utf8, Rest/binary>> -> count_newlines(Rest, Line + 1, 1); _ -> case gleam_stdlib:string_pop_grapheme(Text) of {ok, {_, Rest@1}} -> count_newlines(Rest@1, Line, Col + 1); {error, nil} -> {Line, Col} end end. -file("src/molt/internal/validate.gleam", 324). ?DOC(false). -spec advance_text(state(IOK), binary(), molt@types:toml_kind()) -> state(IOK). advance_text(State, Text, Kind) -> {pos, Line, Col, Offset} = erlang:element(4, State), Text@1 = case Kind of equals -> <<"="/utf8>>; dot -> <<"."/utf8>>; comma -> <<","/utf8>>; left_bracket -> <<"["/utf8>>; right_bracket -> <<"]"/utf8>>; left_brace -> <<"{"/utf8>>; right_brace -> <<"}"/utf8>>; basic_string -> <<<<"\""/utf8, Text/binary>>/binary, "\""/utf8>>; literal_string -> <<<<"'"/utf8, Text/binary>>/binary, "'"/utf8>>; multiline_basic_string -> <<<<"\"\"\""/utf8, Text/binary>>/binary, "\"\"\""/utf8>>; multiline_basic_string_nl -> <<<<"\"\"\"\n"/utf8, Text/binary>>/binary, "\"\"\""/utf8>>; multiline_literal_string -> <<<<"'''"/utf8, Text/binary>>/binary, "'''"/utf8>>; multiline_literal_string_nl -> <<<<"'''\n"/utf8, Text/binary>>/binary, "'''"/utf8>>; _ -> Text end, Len = erlang:byte_size(Text@1), {New_line, New_col} = count_newlines(Text@1, Line, Col), {state, erlang:element(2, State), erlang:element(3, State), {pos, New_line, New_col, Offset + Len}, erlang:element(5, State), erlang:element(6, State), erlang:element(7, State), erlang:element(8, State), erlang:element(9, State)}. -file("src/molt/internal/validate.gleam", 299). ?DOC(false). -spec advance_token(state(IOG), greenwood:token(molt@types:toml_kind())) -> state(IOG). advance_token(State, Token) -> State@1 = case erlang:element(2, Token) of invalid_value -> emit( State, fun() -> make_error(State, {bad_value, erlang:element(3, Token)}, []) end ); invalid_basic_string -> emit(State, fun() -> make_error(State, unterminated_string, []) end); invalid_literal_string -> emit(State, fun() -> make_error(State, unterminated_string, []) end); invalid_multiline_basic_string -> emit( State, fun() -> make_error(State, unterminated_multiline_string, []) end ); invalid_multiline_literal_string -> emit( State, fun() -> make_error(State, unterminated_multiline_string, []) end ); _ -> State end, case erlang:element(3, erlang:element(2, State@1)) of true -> advance_text( State@1, erlang:element(3, Token), erlang:element(2, Token) ); false -> State@1 end. -file("src/molt/internal/validate.gleam", 137). ?DOC(false). -spec walk(greenwood:node_(molt@types:toml_kind()), collector(INM)) -> INM. walk(Tree, Collector) -> case molt@internal@cst@elements:is_toml(erlang:element(3, Tree)) of false -> (erlang:element(4, Collector))( erlang:element(2, Collector), fun() -> {syntax_error, no_valid_toml_structure, [], {span, 1, 1, 0}} end ); true -> State = {state, Collector, erlang:element(2, Collector), {pos, 1, 1, 0}, [], [], maps:new(), maps:new(), 0}, Tree@1 = molt@internal@cst@elements:inline_trailing_trivia(Tree), State@5 = begin _pipe = greenwood:visitor(), _pipe@1 = greenwood:on_trivia( _pipe, fun(State@1, Tok) -> {continue, advance_token(State@1, Tok)} end ), _pipe@2 = greenwood:on_token( _pipe@1, fun(State@2, Tok@1) -> {continue, advance_token(State@2, Tok@1)} end ), _pipe@3 = greenwood:on_enter_node( _pipe@2, fun(State@3, Node) -> {continue, enter_node(State@3, Node)} end ), _pipe@4 = greenwood:on_exit_node( _pipe@3, fun(State@4, Node@1) -> {continue, exit_node(State@4, Node@1)} end ), greenwood:traverse(Tree@1, State, _pipe@4) end, erlang:element(3, State@5) end. -file("src/molt/internal/validate.gleam", 107). ?DOC(false). -spec count(greenwood:node_(molt@types:toml_kind())) -> integer(). count(Tree) -> walk(Tree, {collector, 0, false, fun(N, _) -> N + 1 end}). -file("src/molt/internal/validate.gleam", 120). ?DOC(false). -spec enrich(greenwood:node_(molt@types:toml_kind())) -> list(molt@types:syntax_error()). enrich(Tree) -> _pipe = walk(Tree, enrich_collector()), lists:reverse(_pipe).