-module(tomlet@parser). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/tomlet/parser.gleam"). -export([date_repr_is_valid/1, time_repr_is_valid/1, datetime_repr_is_valid/1, parse/2]). -export_type([parse_error/0, expected_token_kind/0, version/0, assembly_state/0, strip_state/0, strip_step/0]). -if(?OTP_RELEASE >= 27). -define(MODULEDOC(Str), -moduledoc(Str)). -define(DOC(Str), -doc(Str)). -else. -define(MODULEDOC(Str), -compile([])). -define(DOC(Str), -compile([])). -endif. ?MODULEDOC(false). -type parse_error() :: {unexpected, binary(), expected_token_kind(), integer()} | {key_already_in_use, list(binary()), integer()}. -type expected_token_kind() :: expected_value | expected_key | expected_table_header | expected_syntax. -type version() :: toml10 | toml11. -type assembly_state() :: {assembly_state, list(binary()), list(list(binary())), list(list(binary())), list(list(binary())), list(list(binary())), list(list(binary()))}. -type strip_state() :: strip_normal | strip_basic | strip_literal | strip_multi_basic | strip_multi_literal. -type strip_step() :: {strip_step, list(binary()), strip_state(), binary()}. -file("src/tomlet/parser.gleam", 139). ?DOC(false). -spec token_src(william:token()) -> binary(). token_src(Token) -> william:to_source([Token]). -file("src/tomlet/parser.gleam", 917). ?DOC(false). -spec dotted_table_paths_loop( list(binary()), list(binary()), list(binary()), list(list(binary())) ) -> list(list(binary())). dotted_table_paths_loop(Key, Prefix, Active_table, Acc) -> case Key of [] -> Acc; [_] -> Acc; [Segment | Rest] -> Next_prefix = lists:append(Prefix, [Segment]), Next_acc = case erlang:length(Next_prefix) > erlang:length( Active_table ) of true -> [Next_prefix | Acc]; false -> Acc end, dotted_table_paths_loop(Rest, Next_prefix, Active_table, Next_acc) end. -file("src/tomlet/parser.gleam", 910). ?DOC(false). -spec dotted_table_paths(list(binary()), list(binary())) -> list(list(binary())). dotted_table_paths(Active_table, Key) -> dotted_table_paths_loop(Key, [], Active_table, []). -file("src/tomlet/parser.gleam", 937). ?DOC(false). -spec add_paths(list(list(binary())), list(list(binary()))) -> list(list(binary())). add_paths(Paths, Existing) -> case Paths of [] -> Existing; [Path | Rest] -> case gleam@list:contains(Existing, Path) of true -> add_paths(Rest, Existing); false -> add_paths(Rest, [Path | Existing]) end end. -file("src/tomlet/parser.gleam", 902). ?DOC(false). -spec add_dotted_table_paths( list(list(binary())), list(binary()), list(binary()) ) -> list(list(binary())). add_dotted_table_paths(Existing, Active_table, Key) -> add_paths(dotted_table_paths(Active_table, Key), Existing). -file("src/tomlet/parser.gleam", 886). ?DOC(false). -spec dotted_key_extends_table( list(list(binary())), list(binary()), list(binary()) ) -> boolean(). dotted_key_extends_table(Table_paths, Active_table, Key) -> case Table_paths of [] -> false; [Table | Rest] -> (tomlet@key:starts_with(Key, Table) andalso not tomlet@key:starts_with( Active_table, Table )) orelse dotted_key_extends_table(Rest, Active_table, Key) end. -file("src/tomlet/parser.gleam", 876). ?DOC(false). -spec dotted_key_extends_defined_table( list(list(binary())), list(list(binary())), list(binary()), list(binary()) ) -> boolean(). dotted_key_extends_defined_table( Explicit_tables, Array_tables, Active_table, Key ) -> dotted_key_extends_table(Explicit_tables, Active_table, Key) orelse dotted_key_extends_table( Array_tables, Active_table, Key ). -file("src/tomlet/parser.gleam", 814). ?DOC(false). -spec key_path_conflicts(list(list(binary())), list(binary())) -> boolean(). key_path_conflicts(Seen, Key) -> case Seen of [] -> false; [Existing | Rest] -> (tomlet@key:starts_with(Existing, Key) orelse tomlet@key:starts_with( Key, Existing )) orelse key_path_conflicts(Rest, Key) end. -file("src/tomlet/parser.gleam", 432). ?DOC(false). -spec apply_key_value_state(assembly_state(), tomlet@ast:key(), integer()) -> {ok, assembly_state()} | {error, parse_error()}. apply_key_value_state(State, Key, Key_offset) -> Full_key = lists:append( erlang:element(2, State), tomlet@key:to_strings(Key) ), case key_path_conflicts(erlang:element(3, State), Full_key) orelse dotted_key_extends_defined_table( erlang:element(4, State), erlang:element(5, State), erlang:element(2, State), Full_key ) of true -> {error, {key_already_in_use, Full_key, Key_offset}}; false -> {ok, {assembly_state, erlang:element(2, State), [Full_key | erlang:element(3, State)], erlang:element(4, State), erlang:element(5, State), erlang:element(6, State), add_dotted_table_paths( erlang:element(7, State), erlang:element(2, State), Full_key )}} end. -file("src/tomlet/parser.gleam", 348). ?DOC(false). -spec scan_trailing(list(tomlet@lexer:spanned()), binary()) -> {ok, {binary(), list(tomlet@lexer:spanned())}} | {error, parse_error()}. scan_trailing(Spans, Acc) -> case Spans of [] -> {ok, {Acc, []}}; [{spanned, {whitespace, Text}, _} | Rest] -> scan_trailing(Rest, <>); [{spanned, {comment, Text@1}, _} | Rest@1] -> scan_trailing(Rest@1, <>); [{spanned, {end_of_line, _}, _} | Rest@2] -> {ok, {Acc, Rest@2}}; [{spanned, Token, Offset} | _] -> {error, {unexpected, token_src(Token), expected_syntax, Offset}} end. -file("src/tomlet/parser.gleam", 1693). ?DOC(false). -spec based_int_result({ok, integer()} | {error, nil}, binary(), integer()) -> {ok, tomlet@ast:value()} | {error, parse_error()}. based_int_result(Result, Source_text, Offset) -> case Result of {ok, Value} -> {ok, {int, Value, Source_text}}; {error, nil} -> {error, {unexpected, Source_text, expected_value, Offset}} end. -file("src/tomlet/parser.gleam", 1731). ?DOC(false). -spec based_digit_value(binary()) -> {ok, integer()} | {error, nil}. based_digit_value(Char) -> case Char of <<"0"/utf8>> -> {ok, 0}; <<"1"/utf8>> -> {ok, 1}; <<"2"/utf8>> -> {ok, 2}; <<"3"/utf8>> -> {ok, 3}; <<"4"/utf8>> -> {ok, 4}; <<"5"/utf8>> -> {ok, 5}; <<"6"/utf8>> -> {ok, 6}; <<"7"/utf8>> -> {ok, 7}; <<"8"/utf8>> -> {ok, 8}; <<"9"/utf8>> -> {ok, 9}; <<"a"/utf8>> -> {ok, 10}; <<"A"/utf8>> -> {ok, 10}; <<"b"/utf8>> -> {ok, 11}; <<"B"/utf8>> -> {ok, 11}; <<"c"/utf8>> -> {ok, 12}; <<"C"/utf8>> -> {ok, 12}; <<"d"/utf8>> -> {ok, 13}; <<"D"/utf8>> -> {ok, 13}; <<"e"/utf8>> -> {ok, 14}; <<"E"/utf8>> -> {ok, 14}; <<"f"/utf8>> -> {ok, 15}; <<"F"/utf8>> -> {ok, 15}; _ -> {error, nil} end. -file("src/tomlet/parser.gleam", 1712). ?DOC(false). -spec parse_based_int_digits_loop(list(binary()), integer(), integer()) -> {ok, integer()} | {error, nil}. parse_based_int_digits_loop(Chars, Base, Acc) -> case Chars of [] -> {ok, Acc}; [Char | Rest] -> case based_digit_value(Char) of {ok, Value} -> case Value < Base of true -> parse_based_int_digits_loop( Rest, Base, (Acc * Base) + Value ); false -> {error, nil} end; {error, nil} -> {error, nil} end end. -file("src/tomlet/parser.gleam", 1704). ?DOC(false). -spec parse_based_int_digits(binary(), integer(), integer()) -> {ok, integer()} | {error, nil}. parse_based_int_digits(Text, Base, Acc) -> parse_based_int_digits_loop(gleam@string:to_graphemes(Text), Base, Acc). -file("src/tomlet/parser.gleam", 1668). ?DOC(false). -spec parse_based_int_value(binary(), binary(), integer()) -> {ok, tomlet@ast:value()} | {error, parse_error()}. parse_based_int_value(Normalized, Source_text, Offset) -> case gleam_stdlib:string_starts_with(Normalized, <<"0x"/utf8>>) of true -> _pipe = parse_based_int_digits( gleam@string:drop_start(Normalized, 2), 16, 0 ), based_int_result(_pipe, Source_text, Offset); false -> case gleam_stdlib:string_starts_with(Normalized, <<"0o"/utf8>>) of true -> _pipe@1 = parse_based_int_digits( gleam@string:drop_start(Normalized, 2), 8, 0 ), based_int_result(_pipe@1, Source_text, Offset); false -> case gleam_stdlib:string_starts_with( Normalized, <<"0b"/utf8>> ) of true -> _pipe@2 = parse_based_int_digits( gleam@string:drop_start(Normalized, 2), 2, 0 ), based_int_result(_pipe@2, Source_text, Offset); false -> {error, {unexpected, Source_text, expected_value, Offset}} end end end. -file("src/tomlet/parser.gleam", 2158). ?DOC(false). -spec char_is_digit(binary()) -> boolean(). char_is_digit(Char) -> case Char of <<"0"/utf8>> -> true; <<"1"/utf8>> -> true; <<"2"/utf8>> -> true; <<"3"/utf8>> -> true; <<"4"/utf8>> -> true; <<"5"/utf8>> -> true; <<"6"/utf8>> -> true; <<"7"/utf8>> -> true; <<"8"/utf8>> -> true; <<"9"/utf8>> -> true; _ -> false end. -file("src/tomlet/parser.gleam", 1904). ?DOC(false). -spec separated_digits_loop( list(binary()), fun((binary()) -> boolean()), boolean(), boolean() ) -> boolean(). separated_digits_loop( Chars, Is_valid_digit, Seen_digit, Previous_was_underscore ) -> case Chars of [] -> Seen_digit andalso not Previous_was_underscore; [<<"_"/utf8>> | Rest] -> case Seen_digit andalso not Previous_was_underscore of true -> separated_digits_loop( Rest, Is_valid_digit, Seen_digit, true ); false -> false end; [Char | Rest@1] -> case Is_valid_digit(Char) of true -> separated_digits_loop(Rest@1, Is_valid_digit, true, false); false -> false end end. -file("src/tomlet/parser.gleam", 1897). ?DOC(false). -spec separated_digits_are_valid(list(binary()), fun((binary()) -> boolean())) -> boolean(). separated_digits_are_valid(Chars, Is_valid_digit) -> separated_digits_loop(Chars, Is_valid_digit, false, false). -file("src/tomlet/parser.gleam", 1872). ?DOC(false). -spec decimal_digits_are_valid(binary()) -> boolean(). decimal_digits_are_valid(Text) -> gleam@bool:guard( not separated_digits_are_valid( gleam@string:to_graphemes(Text), fun char_is_digit/1 ), false, fun() -> case gleam@string:replace(Text, <<"_"/utf8>>, <<""/utf8>>) of <<""/utf8>> -> false; Digits -> Has_leading_zero = (string:length(Digits) > 1) andalso gleam_stdlib:string_starts_with( Digits, <<"0"/utf8>> ), not Has_leading_zero end end ). -file("src/tomlet/parser.gleam", 2187). ?DOC(false). -spec is_bin_digit_string(binary()) -> boolean(). is_bin_digit_string(Char) -> (Char =:= <<"0"/utf8>>) orelse (Char =:= <<"1"/utf8>>). -file("src/tomlet/parser.gleam", 1887). ?DOC(false). -spec based_digits_are_valid(binary(), fun((binary()) -> boolean())) -> boolean(). based_digits_are_valid(Text, Is_valid_digit) -> case gleam@string:replace(Text, <<"_"/utf8>>, <<""/utf8>>) of <<""/utf8>> -> false; _ -> separated_digits_are_valid( gleam@string:to_graphemes(Text), Is_valid_digit ) end. -file("src/tomlet/parser.gleam", 2180). ?DOC(false). -spec is_oct_digit_string(binary()) -> boolean(). is_oct_digit_string(Char) -> case Char of <<"0"/utf8>> -> true; <<"1"/utf8>> -> true; <<"2"/utf8>> -> true; <<"3"/utf8>> -> true; <<"4"/utf8>> -> true; <<"5"/utf8>> -> true; <<"6"/utf8>> -> true; <<"7"/utf8>> -> true; _ -> false end. -file("src/tomlet/parser.gleam", 2165). ?DOC(false). -spec char_is_hex_digit(binary()) -> boolean(). char_is_hex_digit(Char) -> char_is_digit(Char) orelse (case Char of <<"a"/utf8>> -> true; <<"b"/utf8>> -> true; <<"c"/utf8>> -> true; <<"d"/utf8>> -> true; <<"e"/utf8>> -> true; <<"f"/utf8>> -> true; <<"A"/utf8>> -> true; <<"B"/utf8>> -> true; <<"C"/utf8>> -> true; <<"D"/utf8>> -> true; <<"E"/utf8>> -> true; <<"F"/utf8>> -> true; _ -> false end). -file("src/tomlet/parser.gleam", 2176). ?DOC(false). -spec is_hex_digit_string(binary()) -> boolean(). is_hex_digit_string(Char) -> char_is_hex_digit(Char). -file("src/tomlet/parser.gleam", 2152). ?DOC(false). -spec drop_sign(binary()) -> binary(). drop_sign(Text) -> Has_sign = gleam_stdlib:string_starts_with(Text, <<"+"/utf8>>) orelse gleam_stdlib:string_starts_with( Text, <<"-"/utf8>> ), gleam@bool:guard( not Has_sign, Text, fun() -> gleam@string:drop_start(Text, 1) end ). -file("src/tomlet/parser.gleam", 1840). ?DOC(false). -spec int_repr_is_valid(binary()) -> boolean(). int_repr_is_valid(Text) -> Has_sign = gleam_stdlib:string_starts_with(Text, <<"+"/utf8>>) orelse gleam_stdlib:string_starts_with( Text, <<"-"/utf8>> ), Unsigned = drop_sign(Text), case gleam_stdlib:string_starts_with(Unsigned, <<"0x"/utf8>>) of true -> not Has_sign andalso based_digits_are_valid( gleam@string:drop_start(Unsigned, 2), fun is_hex_digit_string/1 ); false -> case gleam_stdlib:string_starts_with(Unsigned, <<"0o"/utf8>>) of true -> not Has_sign andalso based_digits_are_valid( gleam@string:drop_start(Unsigned, 2), fun is_oct_digit_string/1 ); false -> case gleam_stdlib:string_starts_with( Unsigned, <<"0b"/utf8>> ) of true -> not Has_sign andalso based_digits_are_valid( gleam@string:drop_start(Unsigned, 2), fun is_bin_digit_string/1 ); false -> decimal_digits_are_valid(Unsigned) end end end. -file("src/tomlet/parser.gleam", 1656). ?DOC(false). -spec parse_int_value(binary(), integer()) -> {ok, tomlet@ast:value()} | {error, parse_error()}. parse_int_value(Text, Offset) -> Normalized = gleam@string:replace(Text, <<"_"/utf8>>, <<""/utf8>>), case int_repr_is_valid(Text) of true -> case gleam_stdlib:parse_int(Normalized) of {ok, Value} -> {ok, {int, Value, Text}}; {error, nil} -> parse_based_int_value(Normalized, Text, Offset) end; false -> {error, {unexpected, Text, expected_value, Offset}} end. -file("src/tomlet/parser.gleam", 2137). ?DOC(false). -spec is_leap_year(integer()) -> boolean(). is_leap_year(Year) -> ((Year rem 4) =:= 0) andalso (((Year rem 100) /= 0) orelse ((Year rem 400) =:= 0)). -file("src/tomlet/parser.gleam", 2124). ?DOC(false). -spec days_in_month(integer(), integer()) -> integer(). days_in_month(Year, Month) -> case Month of 1 -> 31; 3 -> 31; 5 -> 31; 7 -> 31; 8 -> 31; 10 -> 31; 12 -> 31; 4 -> 30; 6 -> 30; 9 -> 30; 11 -> 30; 2 -> case is_leap_year(Year) of true -> 29; false -> 28 end; _ -> 0 end. -file("src/tomlet/parser.gleam", 2141). ?DOC(false). -spec two_digits_in_range(binary(), integer(), integer()) -> boolean(). two_digits_in_range(Text, Minimum, Maximum) -> Has_two_digits = (string:length(Text) =:= 2) andalso separated_digits_are_valid( gleam@string:to_graphemes(Text), fun char_is_digit/1 ), gleam@bool:guard( not Has_two_digits, false, fun() -> case gleam_stdlib:parse_int(Text) of {ok, Value} -> (Value >= Minimum) andalso (Value =< Maximum); {error, nil} -> false end end ). -file("src/tomlet/parser.gleam", 2105). ?DOC(false). -spec date_parts_are_valid(binary()) -> boolean(). date_parts_are_valid(Text) -> Year = gleam@string:slice(Text, 0, 4), Month = gleam@string:slice(Text, 5, 2), Day = gleam@string:slice(Text, 8, 2), case (separated_digits_are_valid( gleam@string:to_graphemes(Year), fun char_is_digit/1 ) andalso two_digits_in_range(Month, 1, 12)) andalso two_digits_in_range(Day, 1, 31) of true -> case {gleam_stdlib:parse_int(Year), gleam_stdlib:parse_int(Month), gleam_stdlib:parse_int(Day)} of {{ok, Year_number}, {ok, Month_number}, {ok, Day_number}} -> Day_number =< days_in_month(Year_number, Month_number); {_, _, _} -> false end; false -> false end. -file("src/tomlet/parser.gleam", 1964). ?DOC(false). -spec date_repr_is_valid(binary()) -> boolean(). date_repr_is_valid(Text) -> Has_date_shape = ((string:length(Text) =:= 10) andalso (gleam@string:slice( Text, 4, 1 ) =:= <<"-"/utf8>>)) andalso (gleam@string:slice(Text, 7, 1) =:= <<"-"/utf8>>), gleam@bool:guard( not Has_date_shape, false, fun() -> date_parts_are_valid(Text) end ). -file("src/tomlet/parser.gleam", 2043). ?DOC(false). -spec hour_minute_repr_is_valid(binary()) -> boolean(). hour_minute_repr_is_valid(Text) -> (((string:length(Text) =:= 5) andalso (gleam@string:slice(Text, 2, 1) =:= <<":"/utf8>>)) andalso two_digits_in_range(gleam@string:slice(Text, 0, 2), 0, 23)) andalso two_digits_in_range(gleam@string:slice(Text, 3, 2), 0, 59). -file("src/tomlet/parser.gleam", 2091). ?DOC(false). -spec fraction_is_valid(binary()) -> boolean(). fraction_is_valid(Text) -> case Text of <<""/utf8>> -> true; _ -> case gleam_stdlib:string_starts_with(Text, <<"."/utf8>>) of true -> Digits = gleam@string:drop_start(Text, 1), separated_digits_are_valid( gleam@string:to_graphemes(Digits), fun char_is_digit/1 ); false -> false end end. -file("src/tomlet/parser.gleam", 2075). ?DOC(false). -spec time_repr_is_valid(binary()) -> boolean(). time_repr_is_valid(Text) -> Has_time_shape = ((string:length(Text) >= 8) andalso (gleam@string:slice( Text, 2, 1 ) =:= <<":"/utf8>>)) andalso (gleam@string:slice(Text, 5, 1) =:= <<":"/utf8>>), gleam@bool:guard( not Has_time_shape, false, fun() -> Hour = gleam@string:slice(Text, 0, 2), Minute = gleam@string:slice(Text, 3, 2), Seconds = gleam@string:slice(Text, 6, 2), Fraction = gleam@string:drop_start(Text, 8), ((two_digits_in_range(Hour, 0, 23) andalso two_digits_in_range( Minute, 0, 59 )) andalso two_digits_in_range(Seconds, 0, 59)) andalso fraction_is_valid(Fraction) end ). -file("src/tomlet/parser.gleam", 2034). ?DOC(false). -spec time_repr_is_valid_versioned(binary(), version()) -> boolean(). time_repr_is_valid_versioned(Text, Version) -> case Version of toml10 -> time_repr_is_valid(Text); toml11 -> time_repr_is_valid(Text) orelse hour_minute_repr_is_valid(Text) end. -file("src/tomlet/parser.gleam", 2064). ?DOC(false). -spec offset_repr_is_valid(binary()) -> boolean(). offset_repr_is_valid(Text) -> Has_offset_shape = ((string:length(Text) =:= 6) andalso (gleam_stdlib:string_starts_with( Text, <<"+"/utf8>> ) orelse gleam_stdlib:string_starts_with(Text, <<"-"/utf8>>))) andalso (gleam@string:slice(Text, 3, 1) =:= <<":"/utf8>>), gleam@bool:guard( not Has_offset_shape, false, fun() -> Hour = gleam@string:slice(Text, 1, 2), Minute = gleam@string:slice(Text, 4, 2), two_digits_in_range(Hour, 0, 23) andalso two_digits_in_range( Minute, 0, 59 ) end ). -file("src/tomlet/parser.gleam", 2050). ?DOC(false). -spec find_offset_separator(list(binary()), binary()) -> {ok, {binary(), binary()}} | {error, nil}. find_offset_separator(Chars, Before) -> case Chars of [] -> {error, nil}; [Char | Rest] -> case (Char =:= <<"+"/utf8>>) orelse (Char =:= <<"-"/utf8>>) of true -> {ok, {Before, <>))/binary>>}}; false -> find_offset_separator(Rest, <>) end end. -file("src/tomlet/parser.gleam", 2021). ?DOC(false). -spec time_offset_repr_is_valid_versioned(binary(), version()) -> boolean(). time_offset_repr_is_valid_versioned(Text, Version) -> case gleam_stdlib:string_ends_with(Text, <<"Z"/utf8>>) orelse gleam_stdlib:string_ends_with( Text, <<"z"/utf8>> ) of true -> time_repr_is_valid_versioned( gleam@string:drop_end(Text, 1), Version ); false -> case find_offset_separator( gleam@string:to_graphemes(Text), <<""/utf8>> ) of {ok, {Time, Offset}} -> time_repr_is_valid_versioned(Time, Version) andalso offset_repr_is_valid( Offset ); {error, nil} -> time_repr_is_valid_versioned(Text, Version) end end. -file("src/tomlet/parser.gleam", 1975). ?DOC(false). -spec split_datetime(binary()) -> {ok, {binary(), binary()}} | {error, nil}. split_datetime(Text) -> case gleam@string:split_once(Text, <<"T"/utf8>>) of {ok, Parts} -> {ok, Parts}; {error, nil} -> case gleam@string:split_once(Text, <<"t"/utf8>>) of {ok, Parts@1} -> {ok, Parts@1}; {error, nil} -> gleam@string:split_once(Text, <<" "/utf8>>) end end. -file("src/tomlet/parser.gleam", 1994). ?DOC(false). -spec time_offset_repr_is_valid(binary()) -> boolean(). time_offset_repr_is_valid(Text) -> case gleam_stdlib:string_ends_with(Text, <<"Z"/utf8>>) orelse gleam_stdlib:string_ends_with( Text, <<"z"/utf8>> ) of true -> time_repr_is_valid(gleam@string:drop_end(Text, 1)); false -> case find_offset_separator( gleam@string:to_graphemes(Text), <<""/utf8>> ) of {ok, {Time, Offset}} -> time_repr_is_valid(Time) andalso offset_repr_is_valid( Offset ); {error, nil} -> time_repr_is_valid(Text) end end. -file("src/tomlet/parser.gleam", 1986). ?DOC(false). -spec datetime_repr_is_valid(binary()) -> boolean(). datetime_repr_is_valid(Text) -> case split_datetime(Text) of {ok, {Date, Time_offset}} -> date_repr_is_valid(Date) andalso time_offset_repr_is_valid( Time_offset ); {error, nil} -> false end. -file("src/tomlet/parser.gleam", 2008). ?DOC(false). -spec datetime_repr_is_valid_versioned(binary(), version()) -> boolean(). datetime_repr_is_valid_versioned(Text, Version) -> case Version of toml10 -> datetime_repr_is_valid(Text); toml11 -> case split_datetime(Text) of {ok, {Date, Time_offset}} -> date_repr_is_valid(Date) andalso time_offset_repr_is_valid_versioned( Time_offset, Version ); {error, nil} -> false end end. -file("src/tomlet/parser.gleam", 1640). ?DOC(false). -spec parse_date_like_value(binary(), version()) -> {ok, tomlet@ast:value()} | {error, nil}. parse_date_like_value(Text, Version) -> gleam@bool:guard( datetime_repr_is_valid_versioned(Text, Version), {ok, {date_time, Text}}, fun() -> gleam@bool:guard( time_repr_is_valid_versioned(Text, Version), {ok, {time, Text}}, fun() -> gleam@bool:guard( date_repr_is_valid(Text), {ok, {date, Text}}, fun() -> {error, nil} end ) end ) end ). -file("src/tomlet/parser.gleam", 1632). ?DOC(false). -spec parse_signed_exponent(binary()) -> {ok, integer()} | {error, nil}. parse_signed_exponent(Text) -> Without_plus = case gleam_stdlib:string_starts_with(Text, <<"+"/utf8>>) of true -> gleam@string:drop_start(Text, 1); false -> Text end, gleam_stdlib:parse_int(Without_plus). -file("src/tomlet/parser.gleam", 1621). ?DOC(false). -spec parse_number_part_as_float(binary()) -> {ok, float()} | {error, nil}. parse_number_part_as_float(Text) -> case gleam_stdlib:parse_float(Text) of {ok, Value} -> {ok, Value}; {error, nil} -> case gleam_stdlib:parse_int(Text) of {ok, Value@1} -> {ok, erlang:float(Value@1)}; {error, nil} -> {error, nil} end end. -file("src/tomlet/parser.gleam", 1609). ?DOC(false). -spec parse_exponent_float_parts({binary(), binary()}) -> {ok, float()} | {error, nil}. parse_exponent_float_parts(Parts) -> {Mantissa, Exponent} = Parts, case {parse_number_part_as_float(Mantissa), parse_signed_exponent(Exponent)} of {{ok, Mantissa_value}, {ok, Exponent_value}} -> case gleam@float:power(10.0, erlang:float(Exponent_value)) of {ok, Scale} -> {ok, Mantissa_value * Scale}; {error, nil} -> {error, nil} end; {_, _} -> {error, nil} end. -file("src/tomlet/parser.gleam", 1598). ?DOC(false). -spec parse_exponent_float(binary()) -> {ok, float()} | {error, nil}. parse_exponent_float(Text) -> case gleam@string:split_once(Text, <<"e"/utf8>>) of {ok, Parts} -> parse_exponent_float_parts(Parts); {error, nil} -> case gleam@string:split_once(Text, <<"E"/utf8>>) of {ok, Parts@1} -> parse_exponent_float_parts(Parts@1); {error, nil} -> {error, nil} end end. -file("src/tomlet/parser.gleam", 1591). ?DOC(false). -spec parse_toml_float(binary()) -> {ok, float()} | {error, nil}. parse_toml_float(Text) -> case gleam_stdlib:parse_float(Text) of {ok, Value} -> {ok, Value}; {error, nil} -> parse_exponent_float(Text) end. -file("src/tomlet/parser.gleam", 1576). ?DOC(false). -spec parse_special_float_value(binary(), binary()) -> {ok, tomlet@ast:value()} | {error, nil}. parse_special_float_value(Normalized, Source_text) -> case Normalized of <<"inf"/utf8>> -> {ok, {special_float, positive_infinity, Source_text}}; <<"+inf"/utf8>> -> {ok, {special_float, positive_infinity, Source_text}}; <<"-inf"/utf8>> -> {ok, {special_float, negative_infinity, Source_text}}; <<"nan"/utf8>> -> {ok, {special_float, not_a_number, Source_text}}; <<"+nan"/utf8>> -> {ok, {special_float, not_a_number, Source_text}}; <<"-nan"/utf8>> -> {ok, {special_float, not_a_number, Source_text}}; _ -> {error, nil} end. -file("src/tomlet/parser.gleam", 1945). ?DOC(false). -spec mantissa_repr_is_valid(binary()) -> boolean(). mantissa_repr_is_valid(Text) -> case gleam@string:split_once(Text, <<"."/utf8>>) of {ok, {Whole, Fraction}} -> decimal_digits_are_valid(Whole) andalso separated_digits_are_valid( gleam@string:to_graphemes(Fraction), fun char_is_digit/1 ); {error, nil} -> decimal_digits_are_valid(Text) end. -file("src/tomlet/parser.gleam", 1957). ?DOC(false). -spec exponent_repr_is_valid(binary()) -> boolean(). exponent_repr_is_valid(Text) -> separated_digits_are_valid( gleam@string:to_graphemes(drop_sign(Text)), fun char_is_digit/1 ). -file("src/tomlet/parser.gleam", 1925). ?DOC(false). -spec float_repr_is_valid(binary()) -> boolean(). float_repr_is_valid(Text) -> case Text of <<"inf"/utf8>> -> true; <<"+inf"/utf8>> -> true; <<"-inf"/utf8>> -> true; <<"nan"/utf8>> -> true; <<"+nan"/utf8>> -> true; <<"-nan"/utf8>> -> true; _ -> Unsigned = drop_sign(Text), case gleam@string:split_once(Unsigned, <<"e"/utf8>>) of {ok, {Mantissa, Exponent}} -> mantissa_repr_is_valid(Mantissa) andalso exponent_repr_is_valid( Exponent ); {error, nil} -> case gleam@string:split_once(Unsigned, <<"E"/utf8>>) of {ok, {Mantissa@1, Exponent@1}} -> mantissa_repr_is_valid(Mantissa@1) andalso exponent_repr_is_valid( Exponent@1 ); {error, nil} -> mantissa_repr_is_valid(Unsigned) end end end. -file("src/tomlet/parser.gleam", 1547). ?DOC(false). -spec parse_float_value(binary()) -> {ok, tomlet@ast:value()} | {error, nil}. parse_float_value(Text) -> Normalized = gleam@string:replace(Text, <<"_"/utf8>>, <<""/utf8>>), case float_repr_is_valid(Text) andalso ((((((((gleam_stdlib:contains_string( Normalized, <<"."/utf8>> ) orelse gleam_stdlib:contains_string(Normalized, <<"e"/utf8>>)) orelse gleam_stdlib:contains_string(Normalized, <<"E"/utf8>>)) orelse (Normalized =:= <<"inf"/utf8>>)) orelse (Normalized =:= <<"+inf"/utf8>>)) orelse (Normalized =:= <<"-inf"/utf8>>)) orelse (Normalized =:= <<"nan"/utf8>>)) orelse (Normalized =:= <<"+nan"/utf8>>)) orelse (Normalized =:= <<"-nan"/utf8>>)) of true -> case parse_special_float_value(Normalized, Text) of {ok, Value} -> {ok, Value}; {error, nil} -> case parse_toml_float(Normalized) of {ok, Value@1} -> {ok, {float, Value@1, Text}}; {error, _} -> {error, nil} end end; false -> {error, nil} end. -file("src/tomlet/parser.gleam", 1539). ?DOC(false). -spec parse_bool_value(binary()) -> {ok, tomlet@ast:value()} | {error, nil}. parse_bool_value(Text) -> case Text of <<"true"/utf8>> -> {ok, {bool, true, Text}}; <<"false"/utf8>> -> {ok, {bool, false, Text}}; _ -> {error, nil} end. -file("src/tomlet/parser.gleam", 2191). ?DOC(false). -spec char_is_disallowed_control(binary()) -> boolean(). char_is_disallowed_control(Char) -> case Char of <<"\x{0000}"/utf8>> -> true; <<"\x{0001}"/utf8>> -> true; <<"\x{0002}"/utf8>> -> true; <<"\x{0003}"/utf8>> -> true; <<"\x{0004}"/utf8>> -> true; <<"\x{0005}"/utf8>> -> true; <<"\x{0006}"/utf8>> -> true; <<"\x{0007}"/utf8>> -> true; <<"\x{0008}"/utf8>> -> true; <<"\x{000B}"/utf8>> -> true; <<"\x{000C}"/utf8>> -> true; <<"\r"/utf8>> -> true; <<"\x{000E}"/utf8>> -> true; <<"\x{000F}"/utf8>> -> true; <<"\x{0010}"/utf8>> -> true; <<"\x{0011}"/utf8>> -> true; <<"\x{0012}"/utf8>> -> true; <<"\x{0013}"/utf8>> -> true; <<"\x{0014}"/utf8>> -> true; <<"\x{0015}"/utf8>> -> true; <<"\x{0016}"/utf8>> -> true; <<"\x{0017}"/utf8>> -> true; <<"\x{0018}"/utf8>> -> true; <<"\x{0019}"/utf8>> -> true; <<"\x{001A}"/utf8>> -> true; <<"\x{001B}"/utf8>> -> true; <<"\x{001C}"/utf8>> -> true; <<"\x{001D}"/utf8>> -> true; <<"\x{001E}"/utf8>> -> true; <<"\x{001F}"/utf8>> -> true; <<"\x{007F}"/utf8>> -> true; _ -> false end. -file("src/tomlet/parser.gleam", 1440). ?DOC(false). -spec literal_string_chars_are_valid(list(binary())) -> boolean(). literal_string_chars_are_valid(Chars) -> case Chars of [] -> true; [<<"'"/utf8>> | _] -> false; [<<"\n"/utf8>> | _] -> false; [Char | Rest] -> case char_is_disallowed_control(Char) of true -> false; false -> literal_string_chars_are_valid(Rest) end end. -file("src/tomlet/parser.gleam", 1436). ?DOC(false). -spec literal_string_content_is_valid(binary()) -> boolean(). literal_string_content_is_valid(Text) -> literal_string_chars_are_valid(gleam@string:to_graphemes(Text)). -file("src/tomlet/parser.gleam", 1420). ?DOC(false). -spec parse_literal_string(binary()) -> {ok, tomlet@ast:value()} | {error, nil}. parse_literal_string(Text) -> Is_delimited = gleam_stdlib:string_starts_with(Text, <<"'"/utf8>>) andalso gleam_stdlib:string_ends_with( Text, <<"'"/utf8>> ), gleam@bool:guard( not Is_delimited, {error, nil}, fun() -> Inner = begin _pipe = Text, _pipe@1 = gleam@string:drop_start(_pipe, 1), gleam@string:drop_end(_pipe@1, 1) end, gleam@bool:guard( not literal_string_content_is_valid(Inner), {error, nil}, fun() -> {ok, {string, Inner, literal_string, Text}} end ) end ). -file("src/tomlet/parser.gleam", 2283). ?DOC(false). -spec hex_to_int(list(binary()), integer()) -> {ok, integer()} | {error, nil}. hex_to_int(Chars, Acc) -> case Chars of [] -> {ok, Acc}; [Char | Rest] -> case based_digit_value(Char) of {ok, Value} -> hex_to_int(Rest, (Acc * 16) + Value); {error, nil} -> {error, nil} end end. -file("src/tomlet/parser.gleam", 1829). ?DOC(false). -spec unicode_escape_scalar_is_valid(binary()) -> boolean(). unicode_escape_scalar_is_valid(Escape) -> case hex_to_int(gleam@string:to_graphemes(Escape), 0) of {ok, Value} -> case gleam@string:utf_codepoint(Value) of {ok, _} -> true; {error, nil} -> false end; {error, nil} -> false end. -file("src/tomlet/parser.gleam", 2294). ?DOC(false). -spec take_chars(list(binary()), integer(), binary()) -> {binary(), list(binary())}. take_chars(Chars, Count, Acc) -> case {Count, Chars} of {0, _} -> {Acc, Chars}; {_, [Char | Rest]} -> take_chars(Rest, Count - 1, <>); {_, []} -> {Acc, []} end. -file("src/tomlet/parser.gleam", 1815). ?DOC(false). -spec unicode_escape_is_valid_for( fun((list(binary())) -> boolean()), list(binary()), integer() ) -> boolean(). unicode_escape_is_valid_for(Validate_remaining, Chars, Count) -> {Escape, Remaining} = take_chars(Chars, Count, <<""/utf8>>), case (string:length(Escape) =:= Count) andalso unicode_escape_scalar_is_valid( Escape ) of true -> Validate_remaining(Remaining); false -> false end. -file("src/tomlet/parser.gleam", 1789). ?DOC(false). -spec hex_escape_is_valid_for( fun((list(binary())) -> boolean()), list(binary()) ) -> boolean(). hex_escape_is_valid_for(Validate_remaining, Chars) -> case Chars of [High, Low | Rest] -> case is_hex_digit_string(High) andalso is_hex_digit_string(Low) of true -> Validate_remaining(Rest); false -> false end; _ -> false end. -file("src/tomlet/parser.gleam", 1803). ?DOC(false). -spec unicode_escape_is_valid(list(binary()), integer(), version()) -> boolean(). unicode_escape_is_valid(Chars, Count, Version) -> unicode_escape_is_valid_for( fun(Remaining) -> basic_string_chars_are_valid(Remaining, Version) end, Chars, Count ). -file("src/tomlet/parser.gleam", 1757). ?DOC(false). -spec basic_string_chars_are_valid(list(binary()), version()) -> boolean(). basic_string_chars_are_valid(Chars, Version) -> case Chars of [] -> true; [<<"\\"/utf8>>] -> false; [<<"\\"/utf8>>, <<"e"/utf8>> | Rest] when Version =:= toml11 -> basic_string_chars_are_valid(Rest, Version); [<<"\\"/utf8>>, <<"x"/utf8>> | Rest@1] when Version =:= toml11 -> hex_escape_is_valid_for( fun(Remaining) -> basic_string_chars_are_valid(Remaining, Version) end, Rest@1 ); [<<"\\"/utf8>>, Escaped | Rest@2] -> case Escaped of <<"b"/utf8>> -> basic_string_chars_are_valid(Rest@2, Version); <<"t"/utf8>> -> basic_string_chars_are_valid(Rest@2, Version); <<"n"/utf8>> -> basic_string_chars_are_valid(Rest@2, Version); <<"f"/utf8>> -> basic_string_chars_are_valid(Rest@2, Version); <<"r"/utf8>> -> basic_string_chars_are_valid(Rest@2, Version); <<"\""/utf8>> -> basic_string_chars_are_valid(Rest@2, Version); <<"\\"/utf8>> -> basic_string_chars_are_valid(Rest@2, Version); <<"u"/utf8>> -> unicode_escape_is_valid(Rest@2, 4, Version); <<"U"/utf8>> -> unicode_escape_is_valid(Rest@2, 8, Version); _ -> false end; [<<"\n"/utf8>> | _] -> false; [<<"\""/utf8>> | _] -> false; [Char | Rest@3] -> case char_is_disallowed_control(Char) of true -> false; false -> basic_string_chars_are_valid(Rest@3, Version) end end. -file("src/tomlet/parser.gleam", 1753). ?DOC(false). -spec basic_string_content_is_valid(binary(), version()) -> boolean(). basic_string_content_is_valid(Text, Version) -> basic_string_chars_are_valid(gleam@string:to_graphemes(Text), Version). -file("src/tomlet/parser.gleam", 1401). ?DOC(false). -spec parse_basic_string(binary(), version()) -> {ok, tomlet@ast:value()} | {error, nil}. parse_basic_string(Text, Version) -> Is_delimited = gleam_stdlib:string_starts_with(Text, <<"\""/utf8>>) andalso gleam_stdlib:string_ends_with( Text, <<"\""/utf8>> ), gleam@bool:guard( not Is_delimited, {error, nil}, fun() -> Inner = begin _pipe = Text, _pipe@1 = gleam@string:drop_start(_pipe, 1), gleam@string:drop_end(_pipe@1, 1) end, gleam@bool:guard( not basic_string_content_is_valid(Inner, Version), {error, nil}, fun() -> {ok, {string, Inner, basic_string, Text}} end ) end ). -file("src/tomlet/parser.gleam", 1527). ?DOC(false). -spec multiline_literal_string_chars_are_valid(list(binary())) -> boolean(). multiline_literal_string_chars_are_valid(Chars) -> case Chars of [] -> true; [<<"'"/utf8>>, <<"'"/utf8>>, <<"'"/utf8>> | _] -> false; [Char | Rest] -> case char_is_disallowed_control(Char) of true -> false; false -> multiline_literal_string_chars_are_valid(Rest) end end. -file("src/tomlet/parser.gleam", 1523). ?DOC(false). -spec multiline_literal_string_content_is_valid(binary()) -> boolean(). multiline_literal_string_content_is_valid(Text) -> multiline_literal_string_chars_are_valid(gleam@string:to_graphemes(Text)). -file("src/tomlet/parser.gleam", 1386). ?DOC(false). -spec parse_multiline_literal_string(binary()) -> {ok, tomlet@ast:value()} | {error, nil}. parse_multiline_literal_string(Text) -> Is_delimited = gleam_stdlib:string_starts_with(Text, <<"'''"/utf8>>) andalso gleam_stdlib:string_ends_with( Text, <<"'''"/utf8>> ), gleam@bool:guard( not Is_delimited, {error, nil}, fun() -> Inner = begin _pipe = Text, _pipe@1 = gleam@string:drop_start(_pipe, 3), gleam@string:drop_end(_pipe@1, 3) end, Content_valid = (Text /= <<"'''"/utf8>>) andalso multiline_literal_string_content_is_valid( Inner ), gleam@bool:guard( not Content_valid, {error, nil}, fun() -> {ok, {string, Inner, multi_literal_string, Text}} end ) end ). -file("src/tomlet/parser.gleam", 1508). ?DOC(false). -spec multiline_basic_line_ending_escape_is_valid(list(binary()), version()) -> boolean(). multiline_basic_line_ending_escape_is_valid(Chars, Version) -> case Chars of [] -> false; [<<" "/utf8>> | Rest] -> multiline_basic_line_ending_escape_is_valid(Rest, Version); [<<"\t"/utf8>> | Rest@1] -> multiline_basic_line_ending_escape_is_valid(Rest@1, Version); [<<"\n"/utf8>> | Rest@2] -> multiline_basic_string_chars_are_valid(Rest@2, Version); [<<"\r"/utf8>>, <<"\n"/utf8>> | Rest@3] -> multiline_basic_string_chars_are_valid(Rest@3, Version); _ -> false end. -file("src/tomlet/parser.gleam", 1482). ?DOC(false). -spec multiline_basic_escape_is_valid(list(binary()), version()) -> boolean(). multiline_basic_escape_is_valid(Chars, Version) -> Continue = fun(Rest) -> multiline_basic_string_chars_are_valid(Rest, Version) end, case Chars of [] -> false; [<<"\n"/utf8>> | Rest@1] -> Continue(Rest@1); [<<"\r"/utf8>>, <<"\n"/utf8>> | Rest@2] -> Continue(Rest@2); [<<" "/utf8>> | Rest@3] -> multiline_basic_line_ending_escape_is_valid(Rest@3, Version); [<<"\t"/utf8>> | Rest@4] -> multiline_basic_line_ending_escape_is_valid(Rest@4, Version); [<<"e"/utf8>> | Rest@5] when Version =:= toml11 -> Continue(Rest@5); [<<"x"/utf8>> | Rest@6] when Version =:= toml11 -> hex_escape_is_valid_for(Continue, Rest@6); [Escaped | Rest@7] -> case Escaped of <<"b"/utf8>> -> Continue(Rest@7); <<"t"/utf8>> -> Continue(Rest@7); <<"n"/utf8>> -> Continue(Rest@7); <<"f"/utf8>> -> Continue(Rest@7); <<"r"/utf8>> -> Continue(Rest@7); <<"\""/utf8>> -> Continue(Rest@7); <<"\\"/utf8>> -> Continue(Rest@7); <<"u"/utf8>> -> unicode_escape_is_valid_for(Continue, Rest@7, 4); <<"U"/utf8>> -> unicode_escape_is_valid_for(Continue, Rest@7, 8); _ -> false end end. -file("src/tomlet/parser.gleam", 1465). ?DOC(false). -spec multiline_basic_string_chars_are_valid(list(binary()), version()) -> boolean(). multiline_basic_string_chars_are_valid(Chars, Version) -> case Chars of [] -> true; [<<"\\"/utf8>>] -> false; [<<"\\"/utf8>> | Rest] -> multiline_basic_escape_is_valid(Rest, Version); [<<"\""/utf8>>, <<"\""/utf8>>, <<"\""/utf8>> | _] -> false; [Char | Rest@1] -> case char_is_disallowed_control(Char) of true -> false; false -> multiline_basic_string_chars_are_valid(Rest@1, Version) end end. -file("src/tomlet/parser.gleam", 1458). ?DOC(false). -spec multiline_basic_string_content_is_valid(binary(), version()) -> boolean(). multiline_basic_string_content_is_valid(Text, Version) -> multiline_basic_string_chars_are_valid( gleam@string:to_graphemes(Text), Version ). -file("src/tomlet/parser.gleam", 1368). ?DOC(false). -spec parse_multiline_basic_string(binary(), version()) -> {ok, tomlet@ast:value()} | {error, nil}. parse_multiline_basic_string(Text, Version) -> Is_delimited = gleam_stdlib:string_starts_with(Text, <<"\"\"\""/utf8>>) andalso gleam_stdlib:string_ends_with(Text, <<"\"\"\""/utf8>>), gleam@bool:guard( not Is_delimited, {error, nil}, fun() -> Inner = begin _pipe = Text, _pipe@1 = gleam@string:drop_start(_pipe, 3), gleam@string:drop_end(_pipe@1, 3) end, Content_valid = (Text /= <<"\"\"\""/utf8>>) andalso multiline_basic_string_content_is_valid( Inner, Version ), gleam@bool:guard( not Content_valid, {error, nil}, fun() -> {ok, {string, Inner, multi_basic_string, Text}} end ) end ). -file("src/tomlet/parser.gleam", 966). ?DOC(false). -spec parse_scalar_value(binary(), integer(), version()) -> {ok, tomlet@ast:value()} | {error, parse_error()}. parse_scalar_value(Text, Offset, Version) -> Parsers = [fun(Text@1) -> parse_multiline_basic_string(Text@1, Version) end, fun parse_multiline_literal_string/1, fun(Text@2) -> parse_basic_string(Text@2, Version) end, fun parse_literal_string/1, fun parse_bool_value/1, fun parse_float_value/1, fun(Text@3) -> parse_date_like_value(Text@3, Version) end], case gleam@list:find_map(Parsers, fun(Parse) -> Parse(Text) end) of {ok, Value} -> {ok, Value}; {error, nil} -> parse_int_value(Text, Offset) end. -file("src/tomlet/parser.gleam", 1305). ?DOC(false). -spec strip_state_step(list(binary()), strip_state(), boolean()) -> strip_step(). strip_state_step(Chars, State, Close_single_line_on_newline) -> case {State, Chars} of {_, []} -> {strip_step, [], State, <<""/utf8>>}; {strip_normal, [<<"\""/utf8>>, <<"\""/utf8>>, <<"\""/utf8>> | Rest]} -> {strip_step, Rest, strip_multi_basic, <<"\"\"\""/utf8>>}; {strip_normal, [<<"'"/utf8>>, <<"'"/utf8>>, <<"'"/utf8>> | Rest@1]} -> {strip_step, Rest@1, strip_multi_literal, <<"'''"/utf8>>}; {strip_normal, [<<"\""/utf8>> | Rest@2]} -> {strip_step, Rest@2, strip_basic, <<"\""/utf8>>}; {strip_normal, [<<"'"/utf8>> | Rest@3]} -> {strip_step, Rest@3, strip_literal, <<"'"/utf8>>}; {strip_normal, [Char | Rest@4]} -> {strip_step, Rest@4, strip_normal, Char}; {strip_basic, [<<"\\"/utf8>>, Escaped | Rest@5]} -> {strip_step, Rest@5, strip_basic, <<"\\"/utf8, Escaped/binary>>}; {strip_basic, [<<"\""/utf8>> | Rest@6]} -> {strip_step, Rest@6, strip_normal, <<"\""/utf8>>}; {strip_basic, [<<"\n"/utf8>> | Rest@7]} when Close_single_line_on_newline -> {strip_step, Rest@7, strip_normal, <<"\n"/utf8>>}; {strip_basic, [Char@1 | Rest@8]} -> {strip_step, Rest@8, strip_basic, Char@1}; {strip_literal, [<<"'"/utf8>> | Rest@9]} -> {strip_step, Rest@9, strip_normal, <<"'"/utf8>>}; {strip_literal, [<<"\n"/utf8>> | Rest@10]} when Close_single_line_on_newline -> {strip_step, Rest@10, strip_normal, <<"\n"/utf8>>}; {strip_literal, [Char@2 | Rest@11]} -> {strip_step, Rest@11, strip_literal, Char@2}; {strip_multi_basic, [<<"\\"/utf8>>, Escaped@1 | Rest@12]} -> {strip_step, Rest@12, strip_multi_basic, <<"\\"/utf8, Escaped@1/binary>>}; {strip_multi_basic, [<<"\""/utf8>>, <<"\""/utf8>>, <<"\""/utf8>> | Rest@13]} -> {strip_step, Rest@13, strip_normal, <<"\"\"\""/utf8>>}; {strip_multi_basic, [Char@3 | Rest@14]} -> {strip_step, Rest@14, strip_multi_basic, Char@3}; {strip_multi_literal, [<<"'"/utf8>>, <<"'"/utf8>>, <<"'"/utf8>> | Rest@15]} -> {strip_step, Rest@15, strip_normal, <<"'''"/utf8>>}; {strip_multi_literal, [Char@4 | Rest@16]} -> {strip_step, Rest@16, strip_multi_literal, Char@4} end. -file("src/tomlet/parser.gleam", 1079). ?DOC(false). -spec trim_start_byte_offset(binary()) -> integer(). trim_start_byte_offset(Text) -> erlang:byte_size(Text) - erlang:byte_size(gleam@string:trim_start(Text)). -file("src/tomlet/parser.gleam", 997). ?DOC(false). -spec split_top_level_commas_loop( list(binary()), integer(), strip_state(), binary(), integer(), list({binary(), integer()}) ) -> list({binary(), integer()}). split_top_level_commas_loop(Chars, Depth, State, Current, Current_start, Parts) -> case {State, Chars} of {_, []} -> lists:reverse( [{gleam@string:trim(Current), Current_start + trim_start_byte_offset(Current)} | Parts] ); {strip_normal, [<<","/utf8>> | Rest]} when Depth =:= 0 -> split_top_level_commas_loop( Rest, Depth, strip_normal, <<""/utf8>>, (Current_start + erlang:byte_size(Current)) + 1, [{gleam@string:trim(Current), Current_start + trim_start_byte_offset(Current)} | Parts] ); {strip_normal, [<<"["/utf8>> | Rest@1]} -> split_top_level_commas_loop( Rest@1, Depth + 1, strip_normal, <>, Current_start, Parts ); {strip_normal, [<<"{"/utf8>> | Rest@2]} -> split_top_level_commas_loop( Rest@2, Depth + 1, strip_normal, <>, Current_start, Parts ); {strip_normal, [<<"]"/utf8>> | Rest@3]} -> split_top_level_commas_loop( Rest@3, Depth - 1, strip_normal, <>, Current_start, Parts ); {strip_normal, [<<"}"/utf8>> | Rest@4]} -> split_top_level_commas_loop( Rest@4, Depth - 1, strip_normal, <>, Current_start, Parts ); {_, _} -> {strip_step, Rest@5, Next_state, Consumed} = strip_state_step( Chars, State, false ), split_top_level_commas_loop( Rest@5, Depth, Next_state, <>, Current_start, Parts ) end. -file("src/tomlet/parser.gleam", 986). ?DOC(false). -spec split_top_level_commas(binary()) -> list({binary(), integer()}). split_top_level_commas(Text) -> split_top_level_commas_loop( gleam@string:to_graphemes(Text), 0, strip_normal, <<""/utf8>>, 0, [] ). -file("src/tomlet/parser.gleam", 1346). ?DOC(false). -spec strip_inline_comments_loop(list(binary()), strip_state(), binary()) -> binary(). strip_inline_comments_loop(Chars, State, Acc) -> case {State, Chars} of {_, []} -> Acc; {strip_normal, [<<"#"/utf8>> | Rest]} -> strip_inline_comments_loop( gleam@list:drop_while( Rest, fun(Char) -> Char /= <<"\n"/utf8>> end ), strip_normal, Acc ); {_, _} -> {strip_step, Rest@1, Next_state, Consumed} = strip_state_step( Chars, State, true ), strip_inline_comments_loop( Rest@1, Next_state, <> ) end. -file("src/tomlet/parser.gleam", 1289). ?DOC(false). -spec strip_inline_comments_by_line(binary()) -> binary(). strip_inline_comments_by_line(Text) -> strip_inline_comments_loop( gleam@string:to_graphemes(Text), strip_normal, <<""/utf8>> ). -file("src/tomlet/parser.gleam", 2272). ?DOC(false). -spec unicode_escape_to_string(binary()) -> binary(). unicode_escape_to_string(Escape) -> case hex_to_int(gleam@string:to_graphemes(Escape), 0) of {ok, Value} -> case gleam@string:utf_codepoint(Value) of {ok, Codepoint} -> gleam_stdlib:utf_codepoint_list_to_string([Codepoint]); {error, nil} -> <<<<"\\u{"/utf8, Escape/binary>>/binary, "}"/utf8>> end; {error, nil} -> <<<<"\\u{"/utf8, Escape/binary>>/binary, "}"/utf8>> end. -file("src/tomlet/parser.gleam", 2232). ?DOC(false). -spec basic_key_value_loop(list(binary()), binary()) -> binary(). basic_key_value_loop(Chars, Acc) -> case Chars of [] -> Acc; [<<"\\"/utf8>>, Escaped | Rest] -> case Escaped of <<"b"/utf8>> -> basic_key_value_loop(Rest, <>); <<"t"/utf8>> -> basic_key_value_loop(Rest, <>); <<"n"/utf8>> -> basic_key_value_loop(Rest, <>); <<"f"/utf8>> -> basic_key_value_loop(Rest, <>); <<"r"/utf8>> -> basic_key_value_loop(Rest, <>); <<"\""/utf8>> -> basic_key_value_loop(Rest, <>); <<"\\"/utf8>> -> basic_key_value_loop(Rest, <>); <<"e"/utf8>> -> basic_key_value_loop(Rest, <>); <<"x"/utf8>> -> {Escape, Remaining} = take_chars(Rest, 2, <<""/utf8>>), basic_key_value_loop( Remaining, <> ); <<"u"/utf8>> -> {Escape@1, Remaining@1} = take_chars(Rest, 4, <<""/utf8>>), basic_key_value_loop( Remaining@1, <> ); <<"U"/utf8>> -> {Escape@2, Remaining@2} = take_chars(Rest, 8, <<""/utf8>>), basic_key_value_loop( Remaining@2, <> ); _ -> basic_key_value_loop( Rest, <<<>/binary, Escaped/binary>> ) end; [Char | Rest@1] -> basic_key_value_loop(Rest@1, <>) end. -file("src/tomlet/parser.gleam", 2228). ?DOC(false). -spec basic_key_value(binary()) -> binary(). basic_key_value(Text) -> basic_key_value_loop(gleam@string:to_graphemes(Text), <<""/utf8>>). -file("src/tomlet/parser.gleam", 1453). ?DOC(false). -spec string_is_multiline_delimited(binary()) -> boolean(). string_is_multiline_delimited(Text) -> (gleam_stdlib:string_starts_with(Text, <<"\"\"\""/utf8>>) andalso gleam_stdlib:string_ends_with( Text, <<"\"\"\""/utf8>> )) orelse (gleam_stdlib:string_starts_with(Text, <<"'''"/utf8>>) andalso gleam_stdlib:string_ends_with( Text, <<"'''"/utf8>> )). -file("src/tomlet/parser.gleam", 749). ?DOC(false). -spec parse_key_segment(binary(), version()) -> {ok, tomlet@ast:key_segment()} | {error, nil}. parse_key_segment(Segment, Version) -> Trimmed = gleam@string:trim(Segment), gleam@bool:guard( Trimmed =:= <<""/utf8>>, {error, nil}, fun() -> gleam@bool:guard( string_is_multiline_delimited(Trimmed), {error, nil}, fun() -> case (gleam_stdlib:string_starts_with( Trimmed, <<"\""/utf8>> ) andalso gleam_stdlib:string_ends_with( Trimmed, <<"\""/utf8>> )) andalso (string:length(Trimmed) > 1) of true -> Inner = begin _pipe = Trimmed, _pipe@1 = gleam@string:drop_start(_pipe, 1), gleam@string:drop_end(_pipe@1, 1) end, case basic_string_content_is_valid(Inner, Version) of true -> {ok, {quoted_key_segment, basic_key_value(Inner), Trimmed}}; false -> {error, nil} end; false -> case (gleam_stdlib:string_starts_with( Trimmed, <<"'"/utf8>> ) andalso gleam_stdlib:string_ends_with( Trimmed, <<"'"/utf8>> )) andalso (string:length(Trimmed) > 1) of true -> {ok, {quoted_key_segment, begin _pipe@2 = Trimmed, _pipe@3 = gleam@string:drop_start( _pipe@2, 1 ), gleam@string:drop_end( _pipe@3, 1 ) end, Trimmed}}; false -> case (((gleam_stdlib:string_starts_with( Trimmed, <<"\""/utf8>> ) orelse gleam_stdlib:string_ends_with( Trimmed, <<"\""/utf8>> )) orelse gleam_stdlib:string_starts_with( Trimmed, <<"'"/utf8>> )) orelse gleam_stdlib:string_ends_with( Trimmed, <<"'"/utf8>> )) orelse not tomlet@key:is_bare_key(Trimmed) of true -> {error, nil}; false -> {ok, {bare_key_segment, Trimmed}} end end end end ) end ). -file("src/tomlet/parser.gleam", 568). ?DOC(false). -spec split_key_segments_loop( list(binary()), binary(), list(binary()), boolean(), boolean() ) -> list(binary()). split_key_segments_loop(Chars, Current, Segments, In_basic, In_literal) -> case Chars of [] -> lists:reverse([Current | Segments]); [<<"\\"/utf8>>, Escaped | Rest] -> case In_basic of true -> split_key_segments_loop( Rest, <<<>/binary, Escaped/binary>>, Segments, In_basic, In_literal ); false -> split_key_segments_loop( Rest, <>, Segments, In_basic, In_literal ) end; [<<"."/utf8>> | Rest@1] -> case In_basic orelse In_literal of true -> split_key_segments_loop( Rest@1, <>, Segments, In_basic, In_literal ); false -> split_key_segments_loop( Rest@1, <<""/utf8>>, [Current | Segments], In_basic, In_literal ) end; [<<"\""/utf8>> | Rest@2] -> case In_literal of true -> split_key_segments_loop( Rest@2, <>, Segments, In_basic, In_literal ); false -> split_key_segments_loop( Rest@2, <>, Segments, not In_basic, In_literal ) end; [<<"'"/utf8>> | Rest@3] -> case In_basic of true -> split_key_segments_loop( Rest@3, <>, Segments, In_basic, In_literal ); false -> split_key_segments_loop( Rest@3, <>, Segments, In_basic, not In_literal ) end; [Char | Rest@4] -> split_key_segments_loop( Rest@4, <>, Segments, In_basic, In_literal ) end. -file("src/tomlet/parser.gleam", 564). ?DOC(false). -spec split_key_segments_text(binary()) -> list(binary()). split_key_segments_text(Text) -> split_key_segments_loop( gleam@string:to_graphemes(Text), <<""/utf8>>, [], false, false ). -file("src/tomlet/parser.gleam", 554). ?DOC(false). -spec parse_key(binary(), version()) -> {ok, tomlet@ast:key()} | {error, nil}. parse_key(Text, Version) -> _pipe = split_key_segments_text(Text), _pipe@1 = gleam@list:try_map( _pipe, fun(Segment) -> parse_key_segment(Segment, Version) end ), gleam@result:map(_pipe@1, fun(Field@0) -> {key, Field@0} end). -file("src/tomlet/parser.gleam", 744). ?DOC(false). -spec bool_pick(boolean(), binary(), binary()) -> binary(). bool_pick(Condition, Yes, No) -> gleam@bool:guard(Condition, Yes, fun() -> No end). -file("src/tomlet/parser.gleam", 664). ?DOC(false). -spec split_key_value_loop( list(binary()), binary(), binary(), boolean(), boolean(), boolean() ) -> {ok, {binary(), binary()}} | {error, nil}. split_key_value_loop(Chars, Key, Value, In_basic, In_literal, Found) -> case Chars of [] -> case Found of true -> {ok, {Key, Value}}; false -> {error, nil} end; [Char | Rest] -> case {Char, Found, In_basic, In_literal} of {<<"\\"/utf8>>, _, true, false} -> case Rest of [] -> split_key_value_loop( Rest, Key, Value, In_basic, In_literal, Found ); [Escaped | After_escape] -> split_key_value_loop( After_escape, <>, <<""/utf8>> ))/binary>>, <>, <<""/utf8>> ))/binary>>, In_basic, In_literal, Found ) end; {<<"="/utf8>>, false, false, false} -> split_key_value_loop( Rest, Key, Value, In_basic, In_literal, true ); {<<"\""/utf8>>, _, _, false} -> split_key_value_loop( Rest, <>, <<""/utf8>>))/binary>>, <>, <<""/utf8>>))/binary>>, not In_basic, In_literal, Found ); {<<"'"/utf8>>, _, false, _} -> split_key_value_loop( Rest, <>, <<""/utf8>>))/binary>>, <>, <<""/utf8>>))/binary>>, In_basic, not In_literal, Found ); {_, false, _, _} -> split_key_value_loop( Rest, <>, Value, In_basic, In_literal, Found ); {_, true, _, _} -> split_key_value_loop( Rest, Key, <>, In_basic, In_literal, Found ) end end. -file("src/tomlet/parser.gleam", 560). ?DOC(false). -spec split_key_value(binary()) -> {ok, {binary(), binary()}} | {error, nil}. split_key_value(Line) -> split_key_value_loop( gleam@string:to_graphemes(Line), <<""/utf8>>, <<""/utf8>>, false, false, false ). -file("src/tomlet/parser.gleam", 1196). ?DOC(false). -spec inline_table_newlines_are_valid_loop( list(binary()), integer(), strip_state() ) -> boolean(). inline_table_newlines_are_valid_loop(Chars, Depth, State) -> case {State, Chars} of {_, []} -> true; {strip_normal, [<<"\n"/utf8>> | Rest]} -> case Depth > 0 of true -> inline_table_newlines_are_valid_loop( Rest, Depth, strip_normal ); false -> false end; {strip_normal, [<<"["/utf8>> | Rest@1]} -> inline_table_newlines_are_valid_loop( Rest@1, Depth + 1, strip_normal ); {strip_normal, [<<"{"/utf8>> | Rest@2]} -> inline_table_newlines_are_valid_loop( Rest@2, Depth + 1, strip_normal ); {strip_normal, [<<"]"/utf8>> | Rest@3]} -> inline_table_newlines_are_valid_loop( Rest@3, Depth - 1, strip_normal ); {strip_normal, [<<"}"/utf8>> | Rest@4]} -> inline_table_newlines_are_valid_loop( Rest@4, Depth - 1, strip_normal ); {_, _} -> {strip_step, Rest@5, Next_state, _} = strip_state_step( Chars, State, false ), inline_table_newlines_are_valid_loop(Rest@5, Depth, Next_state) end. -file("src/tomlet/parser.gleam", 1184). ?DOC(false). -spec inline_table_newlines_are_valid(binary(), version()) -> boolean(). inline_table_newlines_are_valid(Text, Version) -> case Version of toml11 -> true; toml10 -> inline_table_newlines_are_valid_loop( gleam@string:to_graphemes(Text), 0, strip_normal ) end. -file("src/tomlet/parser.gleam", 1225). ?DOC(false). -spec parse_inline_entries( list({binary(), integer()}), integer(), list(list(binary())), version() ) -> {ok, list(tomlet@ast:inline_table_entry())} | {error, parse_error()}. parse_inline_entries(Parts, Body_offset, Seen, Version) -> case Parts of [] -> {ok, []}; [{Part, Part_offset} | Rest] -> Entry_offset = Body_offset + Part_offset, case gleam@string:trim(Part) of <<""/utf8>> -> case {Version, Rest} of {toml11, []} -> {ok, []}; {_, _} -> {error, {unexpected, <<""/utf8>>, expected_syntax, Entry_offset}} end; _ -> gleam@result:'try'( gleam@result:replace_error( split_key_value(Part), {unexpected, Part, expected_syntax, Entry_offset} ), fun(_use0) -> {Raw_key, Raw_value} = _use0, gleam@result:'try'( gleam@result:replace_error( parse_key( gleam@string:trim(Raw_key), Version ), {unexpected, Part, expected_key, Entry_offset} ), fun(Key) -> Key_path = tomlet@key:to_strings(Key), gleam@bool:guard( key_path_conflicts(Seen, Key_path), {error, {unexpected, Part, expected_syntax, Entry_offset}}, fun() -> gleam@result:'try'( parse_value( gleam@string:trim( strip_inline_comments_by_line( Raw_value ) ), ((Entry_offset + erlang:byte_size( Raw_key )) + 1) + trim_start_byte_offset( Raw_value ), Version ), fun(Value) -> gleam@result:'try'( parse_inline_entries( Rest, Body_offset, [Key_path | Seen], Version ), fun(Entries) -> {ok, [{inline_table_entry, {trivia, <<""/utf8>>}, Key, Value, {trivia, <<""/utf8>>}} | Entries]} end ) end ) end ) end ) end ) end end. -file("src/tomlet/parser.gleam", 1146). ?DOC(false). -spec parse_inline_table_value(binary(), integer(), version()) -> {ok, tomlet@ast:value()} | {error, parse_error()}. parse_inline_table_value(Text, Offset, Version) -> Is_inline_table = gleam_stdlib:string_starts_with(Text, <<"{"/utf8>>) andalso gleam_stdlib:string_ends_with(Text, <<"}"/utf8>>), gleam@bool:guard( not Is_inline_table, {error, {unexpected, Text, expected_syntax, Offset}}, fun() -> Body = begin _pipe = Text, _pipe@1 = gleam@string:drop_start(_pipe, 1), gleam@string:drop_end(_pipe@1, 1) end, Clean_body = strip_inline_comments_by_line(Body), gleam@bool:guard( not inline_table_newlines_are_valid(Body, Version), {error, {unexpected, Text, expected_syntax, Offset}}, fun() -> case gleam@string:trim(Clean_body) of <<""/utf8>> -> {ok, {inline_table, [], Text}}; _ -> case parse_inline_entries( split_top_level_commas(Clean_body), Offset + 1, [], Version ) of {ok, Entries} -> {ok, {inline_table, Entries, Text}}; {error, Error} -> {error, Error} end end end ) end ). -file("src/tomlet/parser.gleam", 1115). ?DOC(false). -spec parse_array_items(list({binary(), integer()}), integer(), version()) -> {ok, list(tomlet@ast:array_item())} | {error, parse_error()}. parse_array_items(Parts, Body_offset, Version) -> case Parts of [] -> {ok, []}; [{Part, Part_offset} | Rest] -> case gleam@string:trim(strip_inline_comments_by_line(Part)) of <<""/utf8>> -> case Rest of [] -> {ok, []}; _ -> {error, {unexpected, <<""/utf8>>, expected_value, Body_offset + Part_offset}} end; Clean_part -> case parse_value( Clean_part, Body_offset + Part_offset, Version ) of {ok, Value} -> case parse_array_items(Rest, Body_offset, Version) of {ok, Items} -> {ok, [{array_item, {trivia, <<""/utf8>>}, Value, {trivia, <<""/utf8>>}} | Items]}; {error, Error} -> {error, Error} end; {error, Error@1} -> {error, Error@1} end end end. -file("src/tomlet/parser.gleam", 1083). ?DOC(false). -spec parse_array_value(binary(), integer(), version()) -> {ok, tomlet@ast:value()} | {error, parse_error()}. parse_array_value(Text, Offset, Version) -> Is_array = gleam_stdlib:string_starts_with(Text, <<"["/utf8>>) andalso gleam_stdlib:string_ends_with( Text, <<"]"/utf8>> ), gleam@bool:guard( not Is_array, {error, {unexpected, Text, expected_syntax, Offset}}, fun() -> Body = begin _pipe = Text, _pipe@1 = gleam@string:drop_start(_pipe, 1), gleam@string:drop_end(_pipe@1, 1) end, Clean_body = strip_inline_comments_by_line(Body), case gleam@string:trim(Clean_body) of <<""/utf8>> -> {ok, {array, [], Text}}; _ -> case parse_array_items( split_top_level_commas(Clean_body), Offset + 1, Version ) of {ok, Items} -> {ok, {array, Items, Text}}; {error, Error} -> {error, Error} end end end ). -file("src/tomlet/parser.gleam", 951). ?DOC(false). -spec parse_value(binary(), integer(), version()) -> {ok, tomlet@ast:value()} | {error, parse_error()}. parse_value(Text, Offset, Version) -> case gleam_stdlib:string_starts_with(Text, <<"["/utf8>>) of true -> parse_array_value(Text, Offset, Version); false -> case gleam_stdlib:string_starts_with(Text, <<"{"/utf8>>) of true -> parse_inline_table_value(Text, Offset, Version); false -> parse_scalar_value(Text, Offset, Version) end end. -file("src/tomlet/parser.gleam", 310). ?DOC(false). -spec spans_source(list(tomlet@lexer:spanned())) -> binary(). spans_source(Spans) -> _pipe = Spans, _pipe@1 = gleam@list:map( _pipe, fun(Span) -> {spanned, Token, _} = Span, Token end ), william:to_source(_pipe@1). -file("src/tomlet/parser.gleam", 298). ?DOC(false). -spec finish_value( list(tomlet@lexer:spanned()), integer(), list(tomlet@lexer:spanned()), version() ) -> {ok, {tomlet@ast:value(), binary(), list(tomlet@lexer:spanned())}} | {error, parse_error()}. finish_value(Span, Offset, Rest, Version) -> Source = spans_source(Span), gleam@result:'try'( parse_value(Source, Offset, Version), fun(Value) -> gleam@result:map( scan_trailing(Rest, <<""/utf8>>), fun(_use0) -> {Trailing, After} = _use0, {Value, Trailing, After} end ) end ). -file("src/tomlet/parser.gleam", 322). ?DOC(false). -spec balanced_span( list(tomlet@lexer:spanned()), integer(), list(tomlet@lexer:spanned()) ) -> {list(tomlet@lexer:spanned()), list(tomlet@lexer:spanned())}. balanced_span(Spans, Depth, Acc) -> case Spans of [] -> {lists:reverse(Acc), []}; [Span | Rest] -> {spanned, Token, _} = Span, Next_depth = case Token of open_bracket -> Depth + 1; open_brace -> Depth + 1; close_bracket -> Depth - 1; close_brace -> Depth - 1; _ -> Depth end, Acc@1 = [Span | Acc], case Next_depth =:= 0 of true -> {lists:reverse(Acc@1), Rest}; false -> balanced_span(Rest, Next_depth, Acc@1) end end. -file("src/tomlet/parser.gleam", 143). ?DOC(false). -spec take_whitespace(list(tomlet@lexer:spanned()), binary()) -> {binary(), list(tomlet@lexer:spanned())}. take_whitespace(Spans, Acc) -> case Spans of [{spanned, {whitespace, Text}, _} | Rest] -> take_whitespace(Rest, <>); _ -> {Acc, Spans} end. -file("src/tomlet/parser.gleam", 264). ?DOC(false). -spec parse_value_tokens(list(tomlet@lexer:spanned()), integer(), version()) -> {ok, {tomlet@ast:value(), binary(), list(tomlet@lexer:spanned())}} | {error, parse_error()}. parse_value_tokens(Spans, Equal_offset, Version) -> {_, Spans@1} = take_whitespace(Spans, <<""/utf8>>), case Spans@1 of [{spanned, open_bracket, Offset} | _] -> {Span, Rest} = balanced_span(Spans@1, 0, []), finish_value(Span, Offset, Rest, Version); [{spanned, open_brace, Offset@1} | _] -> {Span@1, Rest@1} = balanced_span(Spans@1, 0, []), finish_value(Span@1, Offset@1, Rest@1, Version); [{spanned, {end_of_line, _}, Offset@2} | _] -> gleam@result:map( parse_value(<<""/utf8>>, Offset@2, Version), fun(Value) -> {Value, <<""/utf8>>, Spans@1} end ); [{spanned, {comment, _}, Offset@2} | _] -> gleam@result:map( parse_value(<<""/utf8>>, Offset@2, Version), fun(Value) -> {Value, <<""/utf8>>, Spans@1} end ); [] -> gleam@result:map( parse_value(<<""/utf8>>, Equal_offset + 1, Version), fun(Value@1) -> {Value@1, <<""/utf8>>, []} end ); [{spanned, Token, Offset@3} | Rest@2] -> gleam@result:'try'( parse_value(token_src(Token), Offset@3, Version), fun(Value@2) -> gleam@result:map( scan_trailing(Rest@2, <<""/utf8>>), fun(_use0) -> {Trailing, After} = _use0, {Value@2, Trailing, After} end ) end ) end. -file("src/tomlet/parser.gleam", 204). ?DOC(false). -spec key_segment_from_string(william:string_delimiter(), binary(), version()) -> {ok, tomlet@ast:key_segment()} | {error, nil}. key_segment_from_string(Delimiter, Value, Version) -> case Delimiter of basic_string -> case basic_string_content_is_valid(Value, Version) of true -> {ok, {quoted_key_segment, basic_key_value(Value), <<<<"\""/utf8, Value/binary>>/binary, "\""/utf8>>}}; false -> {error, nil} end; literal_string -> {ok, {quoted_key_segment, Value, <<<<"'"/utf8, Value/binary>>/binary, "'"/utf8>>}}; multiline_basic_string -> {error, nil}; multiline_literal_string -> {error, nil} end. -file("src/tomlet/parser.gleam", 164). ?DOC(false). -spec collect_segments( list(tomlet@lexer:spanned()), boolean(), list(tomlet@ast:key_segment()), version() ) -> {ok, {list(tomlet@ast:key_segment()), list(tomlet@lexer:spanned())}} | {error, parse_error()}. collect_segments(Spans, Expect_segment, Acc, Version) -> {_, Spans@1} = take_whitespace(Spans, <<""/utf8>>), case Spans@1 of [{spanned, {bare_key, Name}, _} | Rest] when Expect_segment -> collect_segments( Rest, false, [{bare_key_segment, Name} | Acc], Version ); [{spanned, {string, Delimiter, Value}, Offset} | Rest@1] when Expect_segment -> case key_segment_from_string(Delimiter, Value, Version) of {ok, Segment} -> collect_segments(Rest@1, false, [Segment | Acc], Version); {error, nil} -> {error, {unexpected, token_src({string, Delimiter, Value}), expected_key, Offset}} end; [{spanned, dot, _} | Rest@2] when not Expect_segment -> collect_segments(Rest@2, true, Acc, Version); _ -> case Expect_segment of true -> case Spans@1 of [{spanned, Token, Offset@1} | _] -> {error, {unexpected, token_src(Token), expected_key, Offset@1}}; [] -> {error, {unexpected, <<""/utf8>>, expected_key, 0}} end; false -> {ok, {lists:reverse(Acc), Spans@1}} end end. -file("src/tomlet/parser.gleam", 807). ?DOC(false). -spec remove_keys_under_table(list(list(binary())), list(binary())) -> list(list(binary())). remove_keys_under_table(Seen, Table_key) -> gleam@list:filter( Seen, fun(Key) -> not tomlet@key:starts_with(Key, Table_key) end ). -file("src/tomlet/parser.gleam", 862). ?DOC(false). -spec array_table_parent_already_implied( tomlet@ast:header(), list(list(binary())), list(list(binary())), list(binary()) ) -> boolean(). array_table_parent_already_implied( Header, Array_tables, Array_table_parents, Key ) -> case Header of {header, _, array_of_tables_header, _} -> gleam@list:contains(Array_table_parents, Key) andalso not gleam@list:contains( Array_tables, Key ); _ -> false end. -file("src/tomlet/parser.gleam", 849). ?DOC(false). -spec table_kind_already_defined( tomlet@ast:header(), list(list(binary())), list(list(binary())), list(binary()) ) -> boolean(). table_kind_already_defined(Header, Explicit_tables, Array_tables, Key) -> case Header of {header, _, standard_table, _} -> gleam@list:contains(Array_tables, Key); {header, _, array_of_tables_header, _} -> gleam@list:contains(Explicit_tables, Key) end. -file("src/tomlet/parser.gleam", 837). ?DOC(false). -spec standard_table_already_defined( tomlet@ast:header(), list(list(binary())), list(binary()) ) -> boolean(). standard_table_already_defined(Header, Explicit_tables, Key) -> case Header of {header, _, standard_table, _} -> gleam@list:contains(Explicit_tables, Key); _ -> false end. -file("src/tomlet/parser.gleam", 824). ?DOC(false). -spec key_path_conflicts_for_table_header(list(list(binary())), list(binary())) -> boolean(). key_path_conflicts_for_table_header(Seen, Key) -> case Seen of [] -> false; [Existing | Rest] -> ((Existing =:= Key) orelse tomlet@key:starts_with(Key, Existing)) orelse key_path_conflicts_for_table_header(Rest, Key) end. -file("src/tomlet/parser.gleam", 802). ?DOC(false). -spec header_key(tomlet@ast:header()) -> list(binary()). header_key(Header) -> {header, Key, _, _} = Header, tomlet@key:to_strings(Key). -file("src/tomlet/parser.gleam", 463). ?DOC(false). -spec apply_header_state(assembly_state(), tomlet@ast:header(), integer()) -> {ok, assembly_state()} | {error, parse_error()}. apply_header_state(State, Header, Open_offset) -> Table_key = header_key(Header), case (((key_path_conflicts_for_table_header( erlang:element(3, State), Table_key ) orelse gleam@list:contains(erlang:element(7, State), Table_key)) orelse standard_table_already_defined( Header, erlang:element(4, State), Table_key )) orelse table_kind_already_defined( Header, erlang:element(4, State), erlang:element(5, State), Table_key )) orelse array_table_parent_already_implied( Header, erlang:element(5, State), erlang:element(6, State), Table_key ) of true -> {error, {key_already_in_use, Table_key, Open_offset}}; false -> Is_array = case Header of {header, _, array_of_tables_header, _} -> true; _ -> false end, Next_seen = case Is_array of true -> remove_keys_under_table(erlang:element(3, State), Table_key); false -> erlang:element(3, State) end, Next_explicit = case Header of {header, _, standard_table, _} -> [Table_key | erlang:element(4, State)]; {header, _, array_of_tables_header, _} -> remove_keys_under_table(erlang:element(4, State), Table_key) end, Next_dotted = case Is_array of true -> remove_keys_under_table(erlang:element(7, State), Table_key); false -> erlang:element(7, State) end, Next_arrays = case Is_array of true -> [Table_key | erlang:element(5, State)]; false -> erlang:element(5, State) end, Next_parents = case Is_array of true -> add_paths( dotted_table_paths([], Table_key), erlang:element(6, State) ); false -> erlang:element(6, State) end, {ok, {assembly_state, Table_key, Next_seen, Next_explicit, Next_arrays, Next_parents, Next_dotted}} end. -file("src/tomlet/parser.gleam", 416). ?DOC(false). -spec scan_header_trailing(list(tomlet@lexer:spanned()), integer()) -> {ok, list(tomlet@lexer:spanned())} | {error, parse_error()}. scan_header_trailing(Spans, Open_offset) -> case Spans of [] -> {ok, []}; [{spanned, {whitespace, _}, _} | Rest] -> scan_header_trailing(Rest, Open_offset); [{spanned, {comment, _}, _} | Rest@1] -> scan_header_trailing(Rest@1, Open_offset); [{spanned, {end_of_line, _}, _} | Rest@2] -> {ok, Rest@2}; [{spanned, _, _} | _] -> {error, {unexpected, <<""/utf8>>, expected_table_header, Open_offset}} end. -file("src/tomlet/parser.gleam", 407). ?DOC(false). -spec after_key_is_close_array_table(list(tomlet@lexer:spanned())) -> {ok, list(tomlet@lexer:spanned())} | {error, nil}. after_key_is_close_array_table(Spans) -> case Spans of [{spanned, close_array_table, _} | Rest] -> {ok, Rest}; _ -> {error, nil} end. -file("src/tomlet/parser.gleam", 398). ?DOC(false). -spec after_key_is_close_table(list(tomlet@lexer:spanned())) -> {ok, list(tomlet@lexer:spanned())} | {error, nil}. after_key_is_close_table(Spans) -> case Spans of [{spanned, close_table, _} | Rest] -> {ok, Rest}; _ -> {error, nil} end. -file("src/tomlet/parser.gleam", 154). ?DOC(false). -spec drop_one_eol(list(tomlet@lexer:spanned())) -> list(tomlet@lexer:spanned()). drop_one_eol(Spans) -> case Spans of [{spanned, {end_of_line, _}, _} | Rest] -> Rest; _ -> Spans end. -file("src/tomlet/parser.gleam", 223). ?DOC(false). -spec parse_key_value_tokens( list(tomlet@lexer:spanned()), integer(), assembly_state(), list(tomlet@ast:entry()), version() ) -> {ok, tomlet@ast:table()} | {error, parse_error()}. parse_key_value_tokens(Spans, Key_offset, State, Entries, Version) -> gleam@result:'try'( collect_segments(Spans, true, [], Version), fun(_use0) -> {Segments, After_key} = _use0, case After_key of [{spanned, equal, Equal_offset} | After_equal] -> Key = {key, Segments}, gleam@result:'try'( parse_value_tokens(After_equal, Equal_offset, Version), fun(_use0@1) -> {Value, Trailing, Rest} = _use0@1, Entry = {key_value, {trivia, <<""/utf8>>}, Key, Value, {trivia, <>}}, gleam@result:'try'( apply_key_value_state(State, Key, Key_offset), fun(Next_state) -> assemble_loop( Rest, Next_state, [Entry | Entries], Version ) end ) end ); [{spanned, Token, Offset} | _] -> {error, {unexpected, token_src(Token), expected_syntax, Offset}}; [] -> {error, {unexpected, <<""/utf8>>, expected_syntax, Key_offset}} end end ). -file("src/tomlet/parser.gleam", 364). ?DOC(false). -spec parse_header_tokens( list(tomlet@lexer:spanned()), tomlet@ast:header_kind(), integer(), assembly_state(), list(tomlet@ast:entry()), version() ) -> {ok, tomlet@ast:table()} | {error, parse_error()}. parse_header_tokens(Spans, Kind, Open_offset, State, Entries, Version) -> gleam@result:'try'( collect_segments(Spans, true, [], Version), fun(_use0) -> {Segments, After_key} = _use0, Closer = case Kind of standard_table -> after_key_is_close_table(After_key); array_of_tables_header -> after_key_is_close_array_table(After_key) end, case Closer of {ok, After_close} -> gleam@result:'try'( scan_header_trailing(After_close, Open_offset), fun(Rest) -> Header = {header, {key, Segments}, Kind, {trivia, <<""/utf8>>}}, Entry = {table_header, Header}, gleam@result:'try'( apply_header_state(State, Header, Open_offset), fun(Next_state) -> assemble_loop( Rest, Next_state, [Entry | Entries], Version ) end ) end ); {error, nil} -> {error, {unexpected, <<""/utf8>>, expected_table_header, Open_offset}} end end ). -file("src/tomlet/parser.gleam", 80). ?DOC(false). -spec assemble_loop( list(tomlet@lexer:spanned()), assembly_state(), list(tomlet@ast:entry()), version() ) -> {ok, tomlet@ast:table()} | {error, parse_error()}. assemble_loop(Spans, State, Entries, Version) -> {Leading_ws, Rest} = take_whitespace(Spans, <<""/utf8>>), case Rest of [] -> case Leading_ws of <<""/utf8>> -> {ok, {table, lists:reverse(Entries), none}}; _ -> {ok, {table, lists:reverse([blank_line | Entries]), none}} end; [{spanned, {end_of_line, _}, _} | Tail] -> assemble_loop(Tail, State, [blank_line | Entries], Version); [{spanned, {comment, Text}, _} | Tail@1] -> assemble_loop( drop_one_eol(Tail@1), State, [{comment, <>} | Entries], Version ); [{spanned, open_table, Offset} | Tail@2] -> parse_header_tokens( Tail@2, standard_table, Offset, State, Entries, Version ); [{spanned, open_array_table, Offset@1} | Tail@3] -> parse_header_tokens( Tail@3, array_of_tables_header, Offset@1, State, Entries, Version ); [{spanned, {bare_key, _}, Offset@2} | _] -> parse_key_value_tokens(Rest, Offset@2, State, Entries, Version); [{spanned, {string, _, _}, Offset@2} | _] -> parse_key_value_tokens(Rest, Offset@2, State, Entries, Version); [{spanned, Token, Offset@3} | _] -> {error, {unexpected, token_src(Token), expected_syntax, Offset@3}} end. -file("src/tomlet/parser.gleam", 61). ?DOC(false). -spec assemble(list(tomlet@lexer:spanned()), version()) -> {ok, tomlet@ast:table()} | {error, parse_error()}. assemble(Spans, Version) -> assemble_loop(Spans, {assembly_state, [], [], [], [], [], []}, [], Version). -file("src/tomlet/parser.gleam", 536). ?DOC(false). -spec first_disallowed_control_offset_loop(list(binary()), integer()) -> {ok, integer()} | {error, nil}. first_disallowed_control_offset_loop(Chars, Offset) -> case Chars of [] -> {error, nil}; [Char | Rest] -> case char_is_disallowed_control(Char) of true -> {ok, Offset}; false -> first_disallowed_control_offset_loop( Rest, Offset + erlang:byte_size(Char) ) end end. -file("src/tomlet/parser.gleam", 532). ?DOC(false). -spec first_disallowed_control_offset(binary()) -> {ok, integer()} | {error, nil}. first_disallowed_control_offset(Input) -> first_disallowed_control_offset_loop(gleam@string:to_graphemes(Input), 0). -file("src/tomlet/parser.gleam", 40). ?DOC(false). -spec parse(binary(), version()) -> {ok, tomlet@ast:table()} | {error, parse_error()}. parse(Input, Version) -> case first_disallowed_control_offset(Input) of {ok, Offset} -> {error, {unexpected, <<""/utf8>>, expected_syntax, Offset}}; {error, nil} -> assemble(tomlet@lexer:lex(Input), Version) end.