-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, <<Acc/binary, Text/binary>>);
[{spanned, {comment, Text@1}, _} | Rest@1] ->
scan_trailing(Rest@1, <<Acc/binary, Text@1/binary>>);
[{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,
<<Char/binary,
(gleam@string:join(Rest, <<""/utf8>>))/binary>>}};
false ->
find_offset_separator(Rest, <<Before/binary, Char/binary>>)
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/binary, Char/binary>>);
{_, []} ->
{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/binary, "["/utf8>>,
Current_start,
Parts
);
{strip_normal, [<<"{"/utf8>> | Rest@2]} ->
split_top_level_commas_loop(
Rest@2,
Depth + 1,
strip_normal,
<<Current/binary, "{"/utf8>>,
Current_start,
Parts
);
{strip_normal, [<<"]"/utf8>> | Rest@3]} ->
split_top_level_commas_loop(
Rest@3,
Depth - 1,
strip_normal,
<<Current/binary, "]"/utf8>>,
Current_start,
Parts
);
{strip_normal, [<<"}"/utf8>> | Rest@4]} ->
split_top_level_commas_loop(
Rest@4,
Depth - 1,
strip_normal,
<<Current/binary, "}"/utf8>>,
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/binary, Consumed/binary>>,
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,
<<Acc/binary, Consumed/binary>>
)
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, <<Acc/binary, "\x{0008}"/utf8>>);
<<"t"/utf8>> ->
basic_key_value_loop(Rest, <<Acc/binary, "\t"/utf8>>);
<<"n"/utf8>> ->
basic_key_value_loop(Rest, <<Acc/binary, "\n"/utf8>>);
<<"f"/utf8>> ->
basic_key_value_loop(Rest, <<Acc/binary, "\x{000C}"/utf8>>);
<<"r"/utf8>> ->
basic_key_value_loop(Rest, <<Acc/binary, "\r"/utf8>>);
<<"\""/utf8>> ->
basic_key_value_loop(Rest, <<Acc/binary, "\""/utf8>>);
<<"\\"/utf8>> ->
basic_key_value_loop(Rest, <<Acc/binary, "\\"/utf8>>);
<<"e"/utf8>> ->
basic_key_value_loop(Rest, <<Acc/binary, "\x{001B}"/utf8>>);
<<"x"/utf8>> ->
{Escape, Remaining} = take_chars(Rest, 2, <<""/utf8>>),
basic_key_value_loop(
Remaining,
<<Acc/binary,
(unicode_escape_to_string(Escape))/binary>>
);
<<"u"/utf8>> ->
{Escape@1, Remaining@1} = take_chars(Rest, 4, <<""/utf8>>),
basic_key_value_loop(
Remaining@1,
<<Acc/binary,
(unicode_escape_to_string(Escape@1))/binary>>
);
<<"U"/utf8>> ->
{Escape@2, Remaining@2} = take_chars(Rest, 8, <<""/utf8>>),
basic_key_value_loop(
Remaining@2,
<<Acc/binary,
(unicode_escape_to_string(Escape@2))/binary>>
);
_ ->
basic_key_value_loop(
Rest,
<<<<Acc/binary, "\\"/utf8>>/binary, Escaped/binary>>
)
end;
[Char | Rest@1] ->
basic_key_value_loop(Rest@1, <<Acc/binary, Char/binary>>)
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,
<<<<Current/binary, "\\"/utf8>>/binary, Escaped/binary>>,
Segments,
In_basic,
In_literal
);
false ->
split_key_segments_loop(
Rest,
<<Current/binary, "\\"/utf8>>,
Segments,
In_basic,
In_literal
)
end;
[<<"."/utf8>> | Rest@1] ->
case In_basic orelse In_literal of
true ->
split_key_segments_loop(
Rest@1,
<<Current/binary, "."/utf8>>,
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,
<<Current/binary, "\""/utf8>>,
Segments,
In_basic,
In_literal
);
false ->
split_key_segments_loop(
Rest@2,
<<Current/binary, "\""/utf8>>,
Segments,
not In_basic,
In_literal
)
end;
[<<"'"/utf8>> | Rest@3] ->
case In_basic of
true ->
split_key_segments_loop(
Rest@3,
<<Current/binary, "'"/utf8>>,
Segments,
In_basic,
In_literal
);
false ->
split_key_segments_loop(
Rest@3,
<<Current/binary, "'"/utf8>>,
Segments,
In_basic,
not In_literal
)
end;
[Char | Rest@4] ->
split_key_segments_loop(
Rest@4,
<<Current/binary, Char/binary>>,
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,
<<Key/binary,
(bool_pick(
not Found,
<<"\\"/utf8, Escaped/binary>>,
<<""/utf8>>
))/binary>>,
<<Value/binary,
(bool_pick(
Found,
<<"\\"/utf8, Escaped/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,
<<Key/binary,
(bool_pick(not Found, <<"\""/utf8>>, <<""/utf8>>))/binary>>,
<<Value/binary,
(bool_pick(Found, <<"\""/utf8>>, <<""/utf8>>))/binary>>,
not In_basic,
In_literal,
Found
);
{<<"'"/utf8>>, _, false, _} ->
split_key_value_loop(
Rest,
<<Key/binary,
(bool_pick(not Found, <<"'"/utf8>>, <<""/utf8>>))/binary>>,
<<Value/binary,
(bool_pick(Found, <<"'"/utf8>>, <<""/utf8>>))/binary>>,
In_basic,
not In_literal,
Found
);
{_, false, _, _} ->
split_key_value_loop(
Rest,
<<Key/binary, Char/binary>>,
Value,
In_basic,
In_literal,
Found
);
{_, true, _, _} ->
split_key_value_loop(
Rest,
Key,
<<Value/binary, Char/binary>>,
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/binary, Text/binary>>);
_ ->
{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, <<Trailing/binary, "\n"/utf8>>}},
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, <<Leading_ws/binary, Text/binary>>} | 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.