-module(swatch@internal@lexer).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/swatch/internal/lexer.gleam").
-export([lex_token_to_source/1, lex/1, lex_to_source/1, is_valid_hex_color/1, annotate_nested/1]).
-export_type([lex_token/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 lex_token() :: {lex_whitespace, binary()} |
{lex_comment, binary()} |
lex_cdo |
lex_cdc |
{lex_string, binary()} |
{lex_hash, binary()} |
{lex_at_keyword, binary()} |
{lex_ident, binary()} |
{lex_function, binary()} |
{lex_url_body, binary()} |
{lex_number, binary()} |
{lex_dimension, binary(), binary()} |
{lex_percentage, binary()} |
{lex_urange, binary()} |
{lex_delim, binary()} |
lex_colon |
lex_semicolon |
lex_comma |
lex_open_paren |
lex_close_paren |
lex_open_bracket |
lex_close_bracket |
lex_open_brace |
lex_close_brace.
-file("src/swatch/internal/lexer.gleam", 54).
?DOC(false).
-spec lex_token_to_source(lex_token()) -> binary().
lex_token_to_source(Token) ->
case Token of
{lex_whitespace, S} ->
S;
{lex_comment, S@1} ->
S@1;
lex_cdo ->
<<"<!--"/utf8>>;
lex_cdc ->
<<"-->"/utf8>>;
{lex_string, S@2} ->
S@2;
{lex_hash, S@3} ->
S@3;
{lex_at_keyword, S@4} ->
S@4;
{lex_ident, S@5} ->
S@5;
{lex_function, S@6} ->
S@6;
{lex_url_body, S@7} ->
S@7;
{lex_number, S@8} ->
S@8;
{lex_dimension, Number, Unit} ->
<<Number/binary, Unit/binary>>;
{lex_percentage, Number@1} ->
<<Number@1/binary, "%"/utf8>>;
{lex_urange, S@9} ->
S@9;
{lex_delim, S@10} ->
S@10;
lex_colon ->
<<":"/utf8>>;
lex_semicolon ->
<<";"/utf8>>;
lex_comma ->
<<","/utf8>>;
lex_open_paren ->
<<"("/utf8>>;
lex_close_paren ->
<<")"/utf8>>;
lex_open_bracket ->
<<"["/utf8>>;
lex_close_bracket ->
<<"]"/utf8>>;
lex_open_brace ->
<<"{"/utf8>>;
lex_close_brace ->
<<"}"/utf8>>
end.
-file("src/swatch/internal/lexer.gleam", 599).
?DOC(false).
-spec consumed(bitstring(), bitstring()) -> binary().
consumed(Input, Here) ->
Len = erlang:byte_size(Input) - erlang:byte_size(Here),
Bytes@1 = case gleam_stdlib:bit_array_slice(Input, 0, Len) of
{ok, Bytes} -> Bytes;
_assert_fail ->
erlang:error(#{gleam_error => let_assert,
message => <<"Pattern match failed, no pattern matched the value."/utf8>>,
file => <<?FILEPATH/utf8>>,
module => <<"swatch/internal/lexer"/utf8>>,
function => <<"consumed"/utf8>>,
line => 601,
value => _assert_fail,
start => 19218,
'end' => 19271,
pattern_start => 19229,
pattern_end => 19238})
end,
Text@1 = case gleam@bit_array:to_string(Bytes@1) of
{ok, Text} -> Text;
_assert_fail@1 ->
erlang:error(#{gleam_error => let_assert,
message => <<"Pattern match failed, no pattern matched the value."/utf8>>,
file => <<?FILEPATH/utf8>>,
module => <<"swatch/internal/lexer"/utf8>>,
function => <<"consumed"/utf8>>,
line => 602,
value => _assert_fail@1,
start => 19274,
'end' => 19322,
pattern_start => 19285,
pattern_end => 19293})
end,
Text@1.
-file("src/swatch/internal/lexer.gleam", 801).
?DOC(false).
-spec is_whitespace(binary()) -> boolean().
is_whitespace(Char) ->
case Char of
<<" "/utf8>> ->
true;
<<"\t"/utf8>> ->
true;
<<"\n"/utf8>> ->
true;
<<"\r"/utf8>> ->
true;
<<"\f"/utf8>> ->
true;
<<"\r\n"/utf8>> ->
true;
_ ->
false
end.
-file("src/swatch/internal/lexer.gleam", 403).
?DOC(false).
-spec codepoint_string(bitstring(), bitstring()) -> {ok,
{binary(), bitstring()}} |
{error, nil}.
codepoint_string(Cp, Rest) ->
case gleam@bit_array:to_string(Cp) of
{ok, Char} ->
{ok, {Char, Rest}};
{error, _} ->
{error, nil}
end.
-file("src/swatch/internal/lexer.gleam", 391).
?DOC(false).
-spec pop_codepoint(bitstring()) -> {ok, {binary(), bitstring()}} | {error, nil}.
pop_codepoint(Input) ->
case Input of
<<16#0D, 16#0A, Rest/bitstring>> ->
{ok, {<<"\r\n"/utf8>>, Rest}};
<<B0, Rest@1/bitstring>> when B0 < 16#80 ->
codepoint_string(<<B0>>, Rest@1);
<<B0@1, B1, Rest@2/bitstring>> when B0@1 < 16#E0 ->
codepoint_string(<<B0@1, B1>>, Rest@2);
<<B0@2, B1@1, B2, Rest@3/bitstring>> when B0@2 < 16#F0 ->
codepoint_string(<<B0@2, B1@1, B2>>, Rest@3);
<<B0@3, B1@2, B2@1, B3, Rest@4/bitstring>> ->
codepoint_string(<<B0@3, B1@2, B2@1, B3>>, Rest@4);
_ ->
{error, nil}
end.
-file("src/swatch/internal/lexer.gleam", 674).
?DOC(false).
-spec escape_trailing_whitespace(bitstring(), binary()) -> {binary(),
bitstring()}.
escape_trailing_whitespace(Input, Acc) ->
case pop_codepoint(Input) of
{ok, {Char, Rest}} ->
case is_whitespace(Char) of
true ->
{<<Acc/binary, Char/binary>>, Rest};
false ->
{Acc, Input}
end;
{error, _} ->
{Acc, Input}
end.
-file("src/swatch/internal/lexer.gleam", 815).
?DOC(false).
-spec is_hex_digit(binary()) -> boolean().
is_hex_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;
<<"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/swatch/internal/lexer.gleam", 655).
?DOC(false).
-spec take_hex_escape(bitstring(), binary(), integer()) -> {binary(),
bitstring()}.
take_hex_escape(Input, Acc, Count) ->
case Count >= 6 of
true ->
escape_trailing_whitespace(Input, Acc);
false ->
case pop_codepoint(Input) of
{ok, {Char, Rest}} ->
case is_hex_digit(Char) of
true ->
take_hex_escape(
Rest,
<<Acc/binary, Char/binary>>,
Count + 1
);
false ->
escape_trailing_whitespace(Input, Acc)
end;
{error, _} ->
{Acc, Input}
end
end.
-file("src/swatch/internal/lexer.gleam", 643).
?DOC(false).
-spec take_identifier_escape(bitstring()) -> {binary(), bitstring()}.
take_identifier_escape(Input) ->
case pop_codepoint(Input) of
{error, _} ->
{<<""/utf8>>, Input};
{ok, {<<"\n"/utf8>>, _}} ->
{<<""/utf8>>, Input};
{ok, {<<"\r"/utf8>>, _}} ->
{<<""/utf8>>, Input};
{ok, {<<"\f"/utf8>>, _}} ->
{<<""/utf8>>, Input};
{ok, {Char, Rest}} ->
case is_hex_digit(Char) of
true ->
take_hex_escape(Rest, Char, 1);
false ->
{Char, Rest}
end
end.
-file("src/swatch/internal/lexer.gleam", 874).
?DOC(false).
-spec starts_with_valid_escape(bitstring()) -> boolean().
starts_with_valid_escape(Input) ->
case pop_codepoint(Input) of
{ok, {<<"\n"/utf8>>, _}} ->
false;
{ok, {<<"\r"/utf8>>, _}} ->
false;
{ok, {<<"\f"/utf8>>, _}} ->
false;
{ok, _} ->
true;
{error, _} ->
false
end.
-file("src/swatch/internal/lexer.gleam", 419).
?DOC(false).
-spec scan_url_body(bitstring()) -> bitstring().
scan_url_body(Input) ->
case Input of
<<16#5C, After/bitstring>> ->
case starts_with_valid_escape(After) of
true ->
{_, Rest2} = take_identifier_escape(After),
scan_url_body(Rest2);
false ->
Input
end;
<<B, _/bitstring>> when (((((B =:= 16#29) orelse (B =:= 16#20)) orelse (B =:= 16#09)) orelse (B =:= 16#0A)) orelse (B =:= 16#0D)) orelse (B =:= 16#0C) ->
Input;
<<_, Rest/bitstring>> ->
scan_url_body(Rest);
_ ->
<<>>
end.
-file("src/swatch/internal/lexer.gleam", 413).
?DOC(false).
-spec take_url_body(bitstring()) -> {binary(), bitstring()}.
take_url_body(Input) ->
Rest = scan_url_body(Input),
{consumed(Input, Rest), Rest}.
-file("src/swatch/internal/lexer.gleam", 790).
?DOC(false).
-spec scan_whitespace(bitstring()) -> bitstring().
scan_whitespace(Input) ->
case Input of
<<B, Rest/bitstring>> when ((((B =:= 16#20) orelse (B =:= 16#09)) orelse (B =:= 16#0A)) orelse (B =:= 16#0D)) orelse (B =:= 16#0C) ->
scan_whitespace(Rest);
_ ->
Input
end.
-file("src/swatch/internal/lexer.gleam", 785).
?DOC(false).
-spec take_whitespace(bitstring(), binary()) -> {binary(), bitstring()}.
take_whitespace(Input, Acc) ->
Rest = scan_whitespace(Input),
{<<Acc/binary, (consumed(Input, Rest))/binary>>, Rest}.
-file("src/swatch/internal/lexer.gleam", 302).
?DOC(false).
-spec lex_url_call(binary(), bitstring(), integer(), list(lex_token())) -> {bitstring(),
integer(),
list(lex_token())}.
lex_url_call(Name, After_paren, Bracket_depth, Out) ->
Out2 = [lex_open_paren, {lex_function, Name} | Out],
{Whitespace, After_whitespace} = take_whitespace(After_paren, <<""/utf8>>),
Out3 = case Whitespace of
<<""/utf8>> ->
Out2;
_ ->
[{lex_whitespace, Whitespace} | Out2]
end,
case pop_codepoint(After_whitespace) of
{ok, {<<"\""/utf8>>, _}} ->
{After_whitespace, Bracket_depth, Out3};
{ok, {<<"'"/utf8>>, _}} ->
{After_whitespace, Bracket_depth, Out3};
{ok, {<<")"/utf8>>, _}} ->
{After_whitespace, Bracket_depth, Out3};
{ok, _} ->
{Body, After_body} = take_url_body(After_whitespace),
{After_body, Bracket_depth, [{lex_url_body, Body} | Out3]};
{error, _} ->
{After_whitespace, Bracket_depth, Out3}
end.
-file("src/swatch/internal/lexer.gleam", 278).
?DOC(false).
-spec lex_ident_or_function(binary(), bitstring(), integer(), list(lex_token())) -> {bitstring(),
integer(),
list(lex_token())}.
lex_ident_or_function(Name, Rest, Bracket_depth, Out) ->
case Rest of
<<"("/utf8, After_paren/bitstring>> ->
case gleam_stdlib:string_starts_with(Name, <<"--"/utf8>>) of
true ->
{Rest, Bracket_depth, [{lex_ident, Name} | Out]};
false ->
case string:lowercase(Name) =:= <<"url"/utf8>> of
true ->
lex_url_call(Name, After_paren, Bracket_depth, Out);
false ->
{After_paren,
Bracket_depth,
[lex_open_paren, {lex_function, Name} | Out]}
end
end;
_ ->
{Rest, Bracket_depth, [{lex_ident, Name} | Out]}
end.
-file("src/swatch/internal/lexer.gleam", 616).
?DOC(false).
-spec scan_identifier(bitstring()) -> bitstring().
scan_identifier(Input) ->
case Input of
<<16#5C, After/bitstring>> ->
case starts_with_valid_escape(After) of
true ->
{_, Rest2} = take_identifier_escape(After),
scan_identifier(Rest2);
false ->
Input
end;
<<B, Rest/bitstring>> when (B >= 16#61) andalso (B =< 16#7A) ->
scan_identifier(Rest);
<<B@1, Rest@1/bitstring>> when (B@1 >= 16#41) andalso (B@1 =< 16#5A) ->
scan_identifier(Rest@1);
<<B@2, Rest@2/bitstring>> when (B@2 >= 16#30) andalso (B@2 =< 16#39) ->
scan_identifier(Rest@2);
<<B@3, Rest@3/bitstring>> when (B@3 =:= 16#2D) orelse (B@3 =:= 16#5F) ->
scan_identifier(Rest@3);
<<B@4, _/bitstring>> when B@4 >= 16#80 ->
case pop_codepoint(Input) of
{ok, {_, Rest@4}} ->
scan_identifier(Rest@4);
{error, _} ->
Input
end;
_ ->
Input
end.
-file("src/swatch/internal/lexer.gleam", 608).
?DOC(false).
-spec take_identifier(bitstring(), binary()) -> {binary(), bitstring()}.
take_identifier(Input, Acc) ->
Rest = scan_identifier(Input),
{<<Acc/binary, (consumed(Input, Rest))/binary>>, Rest}.
-file("src/swatch/internal/lexer.gleam", 488).
?DOC(false).
-spec take_range_wildcards(bitstring(), binary(), integer()) -> {binary(),
bitstring()}.
take_range_wildcards(Input, Acc, Count) ->
case Count >= 6 of
true ->
{Acc, Input};
false ->
case pop_codepoint(Input) of
{ok, {<<"?"/utf8>>, Rest}} ->
take_range_wildcards(
Rest,
<<Acc/binary, "?"/utf8>>,
Count + 1
);
_ ->
{Acc, Input}
end
end.
-file("src/swatch/internal/lexer.gleam", 463).
?DOC(false).
-spec take_range_chars(bitstring(), binary(), integer(), boolean()) -> {binary(),
bitstring()}.
take_range_chars(Input, Acc, Count, Allow_wildcard) ->
case Count >= 6 of
true ->
{Acc, Input};
false ->
case pop_codepoint(Input) of
{ok, {Char, Rest}} ->
case is_hex_digit(Char) of
true ->
take_range_chars(
Rest,
<<Acc/binary, Char/binary>>,
Count + 1,
Allow_wildcard
);
false ->
case Allow_wildcard andalso (Char =:= <<"?"/utf8>>) of
true ->
take_range_wildcards(
Rest,
<<Acc/binary, Char/binary>>,
Count + 1
);
false ->
{Acc, Input}
end
end;
{error, _} ->
{Acc, Input}
end
end.
-file("src/swatch/internal/lexer.gleam", 446).
?DOC(false).
-spec range_continuation(bitstring()) -> {ok, {binary(), bitstring()}} |
{error, nil}.
range_continuation(Input) ->
case pop_codepoint(Input) of
{ok, {<<"-"/utf8>>, After_dash}} ->
case pop_codepoint(After_dash) of
{ok, {Char, _}} ->
case is_hex_digit(Char) of
true ->
{ok,
take_range_chars(
After_dash,
<<""/utf8>>,
0,
false
)};
false ->
{error, nil}
end;
{error, _} ->
{error, nil}
end;
_ ->
{error, nil}
end.
-file("src/swatch/internal/lexer.gleam", 363).
?DOC(false).
-spec lex_take_urange(binary(), bitstring()) -> {binary(), bitstring()}.
lex_take_urange(Char, Rest) ->
After_plus = case Rest of
<<"+"/utf8, After/bitstring>> ->
After;
_ ->
Rest
end,
{First, After_first} = take_range_chars(After_plus, <<""/utf8>>, 0, true),
Prefix = <<<<Char/binary, "+"/utf8>>/binary, First/binary>>,
case gleam_stdlib:contains_string(First, <<"?"/utf8>>) of
true ->
{Prefix, After_first};
false ->
case range_continuation(After_first) of
{ok, {Second, After_second}} ->
{<<<<Prefix/binary, "-"/utf8>>/binary, Second/binary>>,
After_second};
{error, _} ->
{Prefix, After_first}
end
end.
-file("src/swatch/internal/lexer.gleam", 347).
?DOC(false).
-spec lex_starts_urange(binary(), bitstring()) -> boolean().
lex_starts_urange(Char1, Rest) ->
case (Char1 =:= <<"u"/utf8>>) orelse (Char1 =:= <<"U"/utf8>>) of
false ->
false;
true ->
case pop_codepoint(Rest) of
{ok, {<<"+"/utf8>>, After_plus}} ->
case pop_codepoint(After_plus) of
{ok, {Char2, _}} ->
is_hex_digit(Char2) orelse (Char2 =:= <<"?"/utf8>>);
{error, _} ->
false
end;
_ ->
false
end
end.
-file("src/swatch/internal/lexer.gleam", 850).
?DOC(false).
-spec is_non_ascii(binary()) -> boolean().
is_non_ascii(Char) ->
case gleam@string:to_utf_codepoints(Char) of
[First | _] ->
gleam_stdlib:identity(First) >= 16#80;
[] ->
false
end.
-file("src/swatch/internal/lexer.gleam", 826).
?DOC(false).
-spec is_alpha(binary()) -> boolean().
is_alpha(Char) ->
case Char of
<<"a"/utf8>> ->
true;
<<"b"/utf8>> ->
true;
<<"c"/utf8>> ->
true;
<<"d"/utf8>> ->
true;
<<"e"/utf8>> ->
true;
<<"f"/utf8>> ->
true;
<<"g"/utf8>> ->
true;
<<"h"/utf8>> ->
true;
<<"i"/utf8>> ->
true;
<<"j"/utf8>> ->
true;
<<"k"/utf8>> ->
true;
<<"l"/utf8>> ->
true;
<<"m"/utf8>> ->
true;
<<"n"/utf8>> ->
true;
<<"o"/utf8>> ->
true;
<<"p"/utf8>> ->
true;
<<"q"/utf8>> ->
true;
<<"r"/utf8>> ->
true;
<<"s"/utf8>> ->
true;
<<"t"/utf8>> ->
true;
<<"u"/utf8>> ->
true;
<<"v"/utf8>> ->
true;
<<"w"/utf8>> ->
true;
<<"x"/utf8>> ->
true;
<<"y"/utf8>> ->
true;
<<"z"/utf8>> ->
true;
<<"A"/utf8>> ->
true;
<<"B"/utf8>> ->
true;
<<"C"/utf8>> ->
true;
<<"D"/utf8>> ->
true;
<<"E"/utf8>> ->
true;
<<"F"/utf8>> ->
true;
<<"G"/utf8>> ->
true;
<<"H"/utf8>> ->
true;
<<"I"/utf8>> ->
true;
<<"J"/utf8>> ->
true;
<<"K"/utf8>> ->
true;
<<"L"/utf8>> ->
true;
<<"M"/utf8>> ->
true;
<<"N"/utf8>> ->
true;
<<"O"/utf8>> ->
true;
<<"P"/utf8>> ->
true;
<<"Q"/utf8>> ->
true;
<<"R"/utf8>> ->
true;
<<"S"/utf8>> ->
true;
<<"T"/utf8>> ->
true;
<<"U"/utf8>> ->
true;
<<"V"/utf8>> ->
true;
<<"W"/utf8>> ->
true;
<<"X"/utf8>> ->
true;
<<"Y"/utf8>> ->
true;
<<"Z"/utf8>> ->
true;
_ ->
case gleam@string:to_utf_codepoints(Char) of
[_] ->
false;
[] ->
false;
[Codepoint | _] ->
N = gleam_stdlib:identity(Codepoint),
((N >= 16#41) andalso (N =< 16#5A)) orelse ((N >= 16#61)
andalso (N =< 16#7A))
end
end.
-file("src/swatch/internal/lexer.gleam", 845).
?DOC(false).
-spec is_identifier_start(binary()) -> boolean().
is_identifier_start(Char) ->
(is_alpha(Char) orelse (Char =:= <<"_"/utf8>>)) orelse is_non_ascii(Char).
-file("src/swatch/internal/lexer.gleam", 331).
?DOC(false).
-spec lex_number_token(binary(), bitstring()) -> {lex_token(), bitstring()}.
lex_number_token(Num, Rest) ->
case pop_codepoint(Rest) of
{ok, {<<"%"/utf8>>, Rest2}} ->
{{lex_percentage, Num}, Rest2};
{ok, {Char, _}} ->
case is_identifier_start(Char) of
true ->
{Unit, Rest2@1} = take_identifier(Rest, <<""/utf8>>),
{{lex_dimension, Num, Unit}, Rest2@1};
false ->
{{lex_number, Num}, Rest}
end;
{error, _} ->
{{lex_number, Num}, Rest}
end.
-file("src/swatch/internal/lexer.gleam", 776).
?DOC(false).
-spec scan_digits(bitstring()) -> bitstring().
scan_digits(Input) ->
case Input of
<<B, Rest/bitstring>> when (B >= 16#30) andalso (B =< 16#39) ->
scan_digits(Rest);
_ ->
Input
end.
-file("src/swatch/internal/lexer.gleam", 771).
?DOC(false).
-spec take_digits(bitstring(), binary()) -> {binary(), bitstring()}.
take_digits(Input, Acc) ->
Rest = scan_digits(Input),
{<<Acc/binary, (consumed(Input, Rest))/binary>>, Rest}.
-file("src/swatch/internal/lexer.gleam", 754).
?DOC(false).
-spec finish_exponent(binary(), bitstring()) -> {ok, {binary(), bitstring()}} |
{error, nil}.
finish_exponent(Exponent_char, Rest) ->
{Sign, After_sign} = case pop_codepoint(Rest) of
{ok, {<<"+"/utf8>>, After}} ->
{<<"+"/utf8>>, After};
{ok, {<<"-"/utf8>>, After@1}} ->
{<<"-"/utf8>>, After@1};
_ ->
{<<""/utf8>>, Rest}
end,
{Digits, Rest2} = take_digits(After_sign, <<""/utf8>>),
case Digits of
<<""/utf8>> ->
{error, nil};
_ ->
{ok,
{<<<<Exponent_char/binary, Sign/binary>>/binary, Digits/binary>>,
Rest2}}
end.
-file("src/swatch/internal/lexer.gleam", 746).
?DOC(false).
-spec maybe_exponent(bitstring()) -> {ok, {binary(), bitstring()}} |
{error, nil}.
maybe_exponent(Input) ->
case pop_codepoint(Input) of
{ok, {<<"e"/utf8>>, Rest}} ->
finish_exponent(<<"e"/utf8>>, Rest);
{ok, {<<"E"/utf8>>, Rest@1}} ->
finish_exponent(<<"E"/utf8>>, Rest@1);
_ ->
{error, nil}
end.
-file("src/swatch/internal/lexer.gleam", 808).
?DOC(false).
-spec is_digit(binary()) -> boolean().
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/swatch/internal/lexer.gleam", 728).
?DOC(false).
-spec take_optional_fraction(bitstring(), binary()) -> {binary(), bitstring()}.
take_optional_fraction(Input, Acc) ->
case pop_codepoint(Input) of
{ok, {<<"."/utf8>>, After_dot}} ->
case pop_codepoint(After_dot) of
{ok, {Char, _}} ->
case is_digit(Char) of
true ->
{Fraction, Rest} = take_digits(
After_dot,
<<""/utf8>>
),
{<<<<Acc/binary, "."/utf8>>/binary,
Fraction/binary>>,
Rest};
false ->
{Acc, Input}
end;
{error, _} ->
{Acc, Input}
end;
_ ->
{Acc, Input}
end.
-file("src/swatch/internal/lexer.gleam", 712).
?DOC(false).
-spec take_number(bitstring(), binary()) -> {binary(), bitstring()}.
take_number(Input, Acc) ->
Already_has_dot = gleam_stdlib:contains_string(Acc, <<"."/utf8>>),
{Int_digits, After_int} = take_digits(Input, <<""/utf8>>),
Mantissa = <<Acc/binary, Int_digits/binary>>,
{Mantissa2, After_fraction} = case Already_has_dot of
true ->
{Mantissa, After_int};
false ->
take_optional_fraction(After_int, Mantissa)
end,
case maybe_exponent(After_fraction) of
{ok, {Exponent, Rest}} ->
{<<Mantissa2/binary, Exponent/binary>>, Rest};
{error, _} ->
{Mantissa2, After_fraction}
end.
-file("src/swatch/internal/lexer.gleam", 693).
?DOC(false).
-spec would_start_number(bitstring()) -> boolean().
would_start_number(Input) ->
case pop_codepoint(Input) of
{ok, {Char1, Rest}} ->
case is_digit(Char1) of
true ->
true;
false ->
case Char1 =:= <<"."/utf8>> of
true ->
case pop_codepoint(Rest) of
{ok, {Char2, _}} ->
is_digit(Char2);
{error, _} ->
false
end;
false ->
false
end
end;
{error, _} ->
false
end.
-file("src/swatch/internal/lexer.gleam", 859).
?DOC(false).
-spec starts_identifier_sequence(bitstring()) -> boolean().
starts_identifier_sequence(Input) ->
case pop_codepoint(Input) of
{ok, {<<"-"/utf8>>, Rest}} ->
case pop_codepoint(Rest) of
{ok, {<<"-"/utf8>>, _}} ->
true;
{ok, {<<"\\"/utf8>>, Escape_rest}} ->
starts_with_valid_escape(Escape_rest);
{ok, {Char, _}} ->
is_identifier_start(Char);
{error, _} ->
false
end;
{ok, {<<"\\"/utf8>>, Rest@1}} ->
starts_with_valid_escape(Rest@1);
{ok, {Char@1, _}} ->
is_identifier_start(Char@1);
{error, _} ->
false
end.
-file("src/swatch/internal/lexer.gleam", 268).
?DOC(false).
-spec int_max(integer(), integer()) -> integer().
int_max(A, B) ->
case A > B of
true ->
A;
false ->
B
end.
-file("src/swatch/internal/lexer.gleam", 146).
?DOC(false).
-spec lex_step(binary(), bitstring(), integer(), list(lex_token())) -> {bitstring(),
integer(),
list(lex_token())}.
lex_step(Char, Rest, Bracket_depth, Out) ->
case Char of
<<" "/utf8>> ->
{Whitespace, Rest2} = take_whitespace(Rest, Char),
{Rest2, Bracket_depth, [{lex_whitespace, Whitespace} | Out]};
<<"\t"/utf8>> ->
{Whitespace, Rest2} = take_whitespace(Rest, Char),
{Rest2, Bracket_depth, [{lex_whitespace, Whitespace} | Out]};
<<"\n"/utf8>> ->
{Whitespace, Rest2} = take_whitespace(Rest, Char),
{Rest2, Bracket_depth, [{lex_whitespace, Whitespace} | Out]};
<<"\r"/utf8>> ->
{Whitespace, Rest2} = take_whitespace(Rest, Char),
{Rest2, Bracket_depth, [{lex_whitespace, Whitespace} | Out]};
<<"\f"/utf8>> ->
{Whitespace, Rest2} = take_whitespace(Rest, Char),
{Rest2, Bracket_depth, [{lex_whitespace, Whitespace} | Out]};
<<"\r\n"/utf8>> ->
{Whitespace, Rest2} = take_whitespace(Rest, Char),
{Rest2, Bracket_depth, [{lex_whitespace, Whitespace} | Out]};
<<"{"/utf8>> ->
{Rest, Bracket_depth, [lex_open_brace | Out]};
<<"}"/utf8>> ->
{Rest, Bracket_depth, [lex_close_brace | Out]};
<<"("/utf8>> ->
{Rest, Bracket_depth, [lex_open_paren | Out]};
<<")"/utf8>> ->
{Rest, Bracket_depth, [lex_close_paren | Out]};
<<"["/utf8>> ->
{Rest, Bracket_depth + 1, [lex_open_bracket | Out]};
<<"]"/utf8>> ->
{Rest, int_max(Bracket_depth - 1, 0), [lex_close_bracket | Out]};
<<":"/utf8>> ->
{Rest, Bracket_depth, [lex_colon | Out]};
<<";"/utf8>> ->
{Rest, Bracket_depth, [lex_semicolon | Out]};
<<","/utf8>> ->
{Rest, Bracket_depth, [lex_comma | Out]};
<<"@"/utf8>> ->
case starts_identifier_sequence(Rest) of
true ->
{Name, Rest2@1} = take_identifier(Rest, <<""/utf8>>),
{Rest2@1,
Bracket_depth,
[{lex_at_keyword, <<"@"/utf8, Name/binary>>} | Out]};
false ->
{Rest, Bracket_depth, [{lex_delim, <<"@"/utf8>>} | Out]}
end;
<<"#"/utf8>> ->
{Name@1, Rest2@2} = take_identifier(Rest, <<""/utf8>>),
case Name@1 of
<<""/utf8>> ->
{Rest, Bracket_depth, [{lex_delim, <<"#"/utf8>>} | Out]};
_ ->
{Rest2@2,
Bracket_depth,
[{lex_hash, <<"#"/utf8, Name@1/binary>>} | Out]}
end;
<<"."/utf8>> ->
case pop_codepoint(Rest) of
{ok, {Next, _}} ->
case is_digit(Next) of
true ->
{Num, Rest2@3} = take_number(Rest, <<"."/utf8>>),
{Token, Rest3} = lex_number_token(Num, Rest2@3),
{Rest3, Bracket_depth, [Token | Out]};
false ->
{Rest,
Bracket_depth,
[{lex_delim, <<"."/utf8>>} | Out]}
end;
{error, _} ->
{Rest, Bracket_depth, [{lex_delim, <<"."/utf8>>} | Out]}
end;
<<"-"/utf8>> ->
case would_start_number(Rest) of
true ->
{Num@1, Rest2@4} = take_number(Rest, <<"-"/utf8>>),
{Token@1, Rest3@1} = lex_number_token(Num@1, Rest2@4),
{Rest3@1, Bracket_depth, [Token@1 | Out]};
false ->
case starts_identifier_sequence(Rest) of
true ->
{Name@2, Rest2@5} = take_identifier(
Rest,
<<"-"/utf8>>
),
lex_ident_or_function(
Name@2,
Rest2@5,
Bracket_depth,
Out
);
false ->
{Rest,
Bracket_depth,
[{lex_delim, <<"-"/utf8>>} | Out]}
end
end;
<<"+"/utf8>> ->
case would_start_number(Rest) of
true ->
{Num@2, Rest2@6} = take_number(Rest, <<"+"/utf8>>),
{Token@2, Rest3@2} = lex_number_token(Num@2, Rest2@6),
{Rest3@2, Bracket_depth, [Token@2 | Out]};
false ->
{Rest, Bracket_depth, [{lex_delim, <<"+"/utf8>>} | Out]}
end;
<<"\\"/utf8>> ->
case starts_with_valid_escape(Rest) of
true ->
{Escape, Rest2@7} = take_identifier_escape(Rest),
{Name@3, Rest3@3} = take_identifier(
Rest2@7,
<<"\\"/utf8, Escape/binary>>
),
lex_ident_or_function(Name@3, Rest3@3, Bracket_depth, Out);
false ->
{Rest, Bracket_depth, [{lex_delim, <<"\\"/utf8>>} | Out]}
end;
<<"*"/utf8>> ->
{Rest, Bracket_depth, [{lex_delim, Char} | Out]};
<<"/"/utf8>> ->
{Rest, Bracket_depth, [{lex_delim, Char} | Out]};
<<"<"/utf8>> ->
{Rest, Bracket_depth, [{lex_delim, Char} | Out]};
<<">"/utf8>> ->
{Rest, Bracket_depth, [{lex_delim, Char} | Out]};
<<"~"/utf8>> ->
{Rest, Bracket_depth, [{lex_delim, Char} | Out]};
<<"|"/utf8>> ->
{Rest, Bracket_depth, [{lex_delim, Char} | Out]};
<<"&"/utf8>> ->
{Rest, Bracket_depth, [{lex_delim, Char} | Out]};
<<"="/utf8>> ->
{Rest, Bracket_depth, [{lex_delim, Char} | Out]};
<<"!"/utf8>> ->
{Rest, Bracket_depth, [{lex_delim, Char} | Out]};
_ ->
case is_digit(Char) of
true ->
{Num@3, Rest2@8} = take_number(Rest, Char),
{Token@3, Rest3@4} = lex_number_token(Num@3, Rest2@8),
{Rest3@4, Bracket_depth, [Token@3 | Out]};
false ->
case is_identifier_start(Char) of
true ->
case lex_starts_urange(Char, Rest) of
true ->
{Urange, Rest2@9} = lex_take_urange(
Char,
Rest
),
{Rest2@9,
Bracket_depth,
[{lex_urange, Urange} | Out]};
false ->
{Name@4, Rest2@10} = take_identifier(
Rest,
Char
),
lex_ident_or_function(
Name@4,
Rest2@10,
Bracket_depth,
Out
)
end;
false ->
{Rest, Bracket_depth, [{lex_delim, Char} | Out]}
end
end
end.
-file("src/swatch/internal/lexer.gleam", 563).
?DOC(false).
-spec quote_byte(binary()) -> integer().
quote_byte(Quote) ->
case Quote of
<<"\""/utf8>> ->
16#22;
_ ->
16#27
end.
-file("src/swatch/internal/lexer.gleam", 574).
?DOC(false).
-spec scan_quoted(bitstring(), integer(), boolean()) -> bitstring().
scan_quoted(Input, Quote, Stop_on_newline) ->
case Input of
<<16#5C, After/bitstring>> ->
case pop_codepoint(After) of
{ok, {_, Rest2}} ->
scan_quoted(Rest2, Quote, Stop_on_newline);
{error, _} ->
<<>>
end;
<<B, Rest/bitstring>> ->
case Stop_on_newline andalso (((B =:= 16#0A) orelse (B =:= 16#0D))
orelse (B =:= 16#0C)) of
true ->
Input;
false ->
case B =:= Quote of
true ->
Rest;
false ->
scan_quoted(Rest, Quote, Stop_on_newline)
end
end;
_ ->
<<>>
end.
-file("src/swatch/internal/lexer.gleam", 550).
?DOC(false).
-spec take_string(bitstring(), binary()) -> {binary(), bitstring()}.
take_string(Input, Quote) ->
Rest = scan_quoted(Input, quote_byte(Quote), true),
{consumed(Input, Rest), Rest}.
-file("src/swatch/internal/lexer.gleam", 557).
?DOC(false).
-spec take_quoted(bitstring(), binary()) -> {binary(), bitstring()}.
take_quoted(Input, Quote) ->
Rest = scan_quoted(Input, quote_byte(Quote), false),
{consumed(Input, Rest), Rest}.
-file("src/swatch/internal/lexer.gleam", 132).
?DOC(false).
-spec lex_string(bitstring(), binary(), integer()) -> {binary(), bitstring()}.
lex_string(Input, Quote, Bracket_depth) ->
case Bracket_depth > 0 of
true ->
take_quoted(Input, Quote);
false ->
take_string(Input, Quote)
end.
-file("src/swatch/internal/lexer.gleam", 538).
?DOC(false).
-spec scan_comment_body(bitstring()) -> bitstring().
scan_comment_body(Input) ->
case Input of
<<"*/"/utf8, Rest/bitstring>> ->
Rest;
<<_, Rest@1/bitstring>> ->
scan_comment_body(Rest@1);
_ ->
<<>>
end.
-file("src/swatch/internal/lexer.gleam", 531).
?DOC(false).
-spec take_until(bitstring()) -> {binary(), bitstring()}.
take_until(Input) ->
Rest = scan_comment_body(Input),
{consumed(Input, Rest), Rest}.
-file("src/swatch/internal/lexer.gleam", 95).
?DOC(false).
-spec lex_loop(bitstring(), integer(), list(lex_token())) -> list(lex_token()).
lex_loop(Code, Bracket_depth, Out) ->
case Code of
<<>> ->
lists:reverse(Out);
<<"/*"/utf8, Rest/bitstring>> ->
{Body, Rest2} = take_until(Rest),
lex_loop(
Rest2,
Bracket_depth,
[{lex_comment, <<"/*"/utf8, Body/binary>>} | Out]
);
<<"<!--"/utf8, Rest@1/bitstring>> ->
lex_loop(Rest@1, Bracket_depth, [lex_cdo | Out]);
<<"-->"/utf8, Rest@2/bitstring>> ->
lex_loop(Rest@2, Bracket_depth, [lex_cdc | Out]);
<<"\""/utf8, Rest@3/bitstring>> ->
{Body@1, Rest2@1} = lex_string(Rest@3, <<"\""/utf8>>, Bracket_depth),
lex_loop(
Rest2@1,
Bracket_depth,
[{lex_string, <<"\""/utf8, Body@1/binary>>} | Out]
);
<<"'"/utf8, Rest@4/bitstring>> ->
{Body@2, Rest2@2} = lex_string(Rest@4, <<"'"/utf8>>, Bracket_depth),
lex_loop(
Rest2@2,
Bracket_depth,
[{lex_string, <<"'"/utf8, Body@2/binary>>} | Out]
);
_ ->
case pop_codepoint(Code) of
{error, _} ->
lists:reverse(Out);
{ok, {Char, Rest@5}} ->
{Rest2@3, Depth2, Out2} = lex_step(
Char,
Rest@5,
Bracket_depth,
Out
),
lex_loop(Rest2@3, Depth2, Out2)
end
end.
-file("src/swatch/internal/lexer.gleam", 83).
?DOC(false).
-spec lex(binary()) -> list(lex_token()).
lex(Code) ->
lex_loop(gleam_stdlib:identity(Code), 0, []).
-file("src/swatch/internal/lexer.gleam", 89).
?DOC(false).
-spec lex_to_source(list(lex_token())) -> binary().
lex_to_source(Tokens) ->
_pipe = Tokens,
_pipe@1 = gleam@list:map(_pipe, fun lex_token_to_source/1),
erlang:list_to_binary(_pipe@1).
-file("src/swatch/internal/lexer.gleam", 512).
?DOC(false).
-spec all_hex_digits(bitstring()) -> boolean().
all_hex_digits(Input) ->
case pop_codepoint(Input) of
{error, _} ->
true;
{ok, {Char, Rest}} ->
case is_hex_digit(Char) of
true ->
all_hex_digits(Rest);
false ->
false
end
end.
-file("src/swatch/internal/lexer.gleam", 504).
?DOC(false).
-spec is_valid_hex_color(binary()) -> boolean().
is_valid_hex_color(Name) ->
Bytes = gleam_stdlib:identity(Name),
case erlang:byte_size(Bytes) of
3 ->
all_hex_digits(Bytes);
4 ->
all_hex_digits(Bytes);
6 ->
all_hex_digits(Bytes);
8 ->
all_hex_digits(Bytes);
_ ->
false
end.
-file("src/swatch/internal/lexer.gleam", 911).
?DOC(false).
-spec annotate_step(lex_token(), boolean(), list(boolean())) -> {boolean(),
boolean(),
list(boolean())}.
annotate_step(Token, Answer, Stack) ->
case {Token, Stack} of
{lex_open_paren, [Saved | Rest]} ->
{Saved, Saved, Rest};
{lex_open_bracket, [Saved | Rest]} ->
{Saved, Saved, Rest};
{lex_open_paren, []} ->
{false, false, []};
{lex_open_bracket, []} ->
{false, false, []};
{lex_close_paren, _} ->
{false, false, [Answer | Stack]};
{lex_close_bracket, _} ->
{false, false, [Answer | Stack]};
{lex_open_brace, _} ->
{true, true, Stack};
{lex_close_brace, _} ->
{false, false, Stack};
{lex_semicolon, _} ->
{false, false, Stack};
{_, _} ->
{Answer, Answer, Stack}
end.
-file("src/swatch/internal/lexer.gleam", 896).
?DOC(false).
-spec annotate_loop(
list(lex_token()),
boolean(),
list(boolean()),
list(boolean())
) -> list(boolean()).
annotate_loop(Rev_tokens, Answer, Stack, Out) ->
case Rev_tokens of
[] ->
Out;
[Token | Rest] ->
{Flag, Answer2, Stack2} = annotate_step(Token, Answer, Stack),
annotate_loop(Rest, Answer2, Stack2, [Flag | Out])
end.
-file("src/swatch/internal/lexer.gleam", 892).
?DOC(false).
-spec annotate_nested(list(lex_token())) -> list(boolean()).
annotate_nested(Tokens) ->
annotate_loop(lists:reverse(Tokens), false, [], []).