-module(william). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/william.gleam"). -export([new/0, tokenise/2, to_highlight/1, highlight/1, to_ansi/1, to_html/1, to_source/1, ignore_whitespace/1, ignore_comments/1]). -export_type([highlight_token/0, highlight_context/0, token/0, base/0, string_delimiter/0, mode/0, container/0, lexer/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. -type highlight_token() :: {highlight_error, binary()} | {highlight_key, binary()} | {highlight_table, binary()} | {highlight_string, binary()} | {highlight_number, binary()} | {highlight_date_time, binary()} | {highlight_literal, binary()} | {highlight_operator, binary()} | {highlight_punctuation, binary()} | {highlight_comment, binary()} | {highlight_whitespace, binary()}. -type highlight_context() :: normal | table_header. -type token() :: {end_of_line, binary()} | {whitespace, binary()} | {comment, binary()} | {bare_key, binary()} | {string, string_delimiter(), binary()} | {boolean, binary()} | {integer, base(), binary()} | {float, binary()} | {date_time, binary()} | equal | dot | comma | open_table | close_table | open_array_table | close_array_table | open_bracket | close_bracket | open_brace | close_brace | {unexpected, binary()} | {invalid_number, binary()} | {unterminated_string, string_delimiter(), binary()}. -type base() :: binary | octal | decimal | hexadecimal. -type string_delimiter() :: basic_string | literal_string | multiline_basic_string | multiline_literal_string. -type mode() :: key_mode | value_mode | after_value_mode | table_mode. -type container() :: array_container | inline_table_container. -opaque lexer() :: {lexer, boolean(), boolean(), splitter:splitter(), splitter:splitter(), splitter:splitter(), splitter:splitter(), splitter:splitter(), splitter:splitter(), splitter:splitter()}. -file("src/william.gleam", 307). ?DOC( " Create a new Lexer with default settings.\n" "\n" " Lexers can be cached and reused to parse many source files efficiently.\n" ). -spec new() -> lexer(). new() -> {lexer, false, false, splitter:new([<<"\r\n"/utf8>>, <<"\n"/utf8>>, <<"\r"/utf8>>]), splitter:new( [<<"\r\n"/utf8>>, <<"\n"/utf8>>, <<"\r"/utf8>>, <<" "/utf8>>, <<"\t"/utf8>>, <<"#"/utf8>>, <<","/utf8>>, <<"]"/utf8>>, <<"}"/utf8>>, <<"["/utf8>>, <<"{"/utf8>>, <<"="/utf8>>, <<"\""/utf8>>, <<"'"/utf8>>] ), splitter:new( [<<"\r\n"/utf8>>, <<"\n"/utf8>>, <<"\r"/utf8>>, <<" "/utf8>>, <<"\t"/utf8>>, <<"#"/utf8>>, <<","/utf8>>, <<"]"/utf8>>, <<"}"/utf8>>] ), splitter:new( [<<"\r\n"/utf8>>, <<"\n"/utf8>>, <<"\r"/utf8>>, <<"\\"/utf8>>, <<"\""/utf8>>] ), splitter:new( [<<"\r\n"/utf8>>, <<"\n"/utf8>>, <<"\r"/utf8>>, <<"'"/utf8>>] ), splitter:new( [<<"\"\"\"\"\""/utf8>>, <<"\"\"\"\""/utf8>>, <<"\"\"\""/utf8>>, <<"\\"/utf8>>] ), splitter:new([<<"'''''"/utf8>>, <<"''''"/utf8>>, <<"'''"/utf8>>])}. -file("src/william.gleam", 575). -spec emit(lexer(), token(), list(token())) -> list(token()). emit(Lexer, Token, Acc) -> case Token of {whitespace, _} -> case erlang:element(2, Lexer) of true -> Acc; false -> [Token | Acc] end; {end_of_line, _} -> case erlang:element(2, Lexer) of true -> Acc; false -> [Token | Acc] end; {comment, _} -> case erlang:element(3, Lexer) of true -> Acc; false -> [Token | Acc] end; _ -> [Token | Acc] end. -file("src/william.gleam", 769). -spec unexpected(lexer(), binary(), binary()) -> {token(), binary()}. unexpected(Lexer, Input, Acc) -> {Unexpected, Rest} = splitter_ffi:split_before( erlang:element(6, Lexer), Input ), {{unexpected, <>}, Rest}. -file("src/william.gleam", 1296). -spec invalid_number(lexer(), binary(), binary()) -> {token(), binary()}. invalid_number(Lexer, Input, Acc) -> {Unexpected, Rest} = splitter_ffi:split_before( erlang:element(5, Lexer), Input ), {{invalid_number, <>}, Rest}. -file("src/william.gleam", 1305). -spec is_value_terminator(binary()) -> boolean(). is_value_terminator(Input) -> case Input of <<""/utf8>> -> true; <<" "/utf8, _/binary>> -> true; <<"\t"/utf8, _/binary>> -> true; <<"\r\n"/utf8, _/binary>> -> true; <<"\n"/utf8, _/binary>> -> true; <<"\r"/utf8, _/binary>> -> true; <<"#"/utf8, _/binary>> -> true; <<","/utf8, _/binary>> -> true; <<"]"/utf8, _/binary>> -> true; <<"}"/utf8, _/binary>> -> true; _ -> false end. -file("src/william.gleam", 1284). -spec number_end(lexer(), binary(), binary(), fun((binary()) -> token())) -> {token(), binary()}. number_end(Lexer, Input, Acc, Token) -> case is_value_terminator(Input) of true -> {Token(Acc), Input}; false -> invalid_number(Lexer, Input, Acc) end. -file("src/william.gleam", 1268). -spec take_digit(binary()) -> {ok, {binary(), binary()}} | {error, nil}. take_digit(Input) -> case Input of <<"0"/utf8, Rest/binary>> -> {ok, {<<"0"/utf8>>, Rest}}; <<"1"/utf8, Rest@1/binary>> -> {ok, {<<"1"/utf8>>, Rest@1}}; <<"2"/utf8, Rest@2/binary>> -> {ok, {<<"2"/utf8>>, Rest@2}}; <<"3"/utf8, Rest@3/binary>> -> {ok, {<<"3"/utf8>>, Rest@3}}; <<"4"/utf8, Rest@4/binary>> -> {ok, {<<"4"/utf8>>, Rest@4}}; <<"5"/utf8, Rest@5/binary>> -> {ok, {<<"5"/utf8>>, Rest@5}}; <<"6"/utf8, Rest@6/binary>> -> {ok, {<<"6"/utf8>>, Rest@6}}; <<"7"/utf8, Rest@7/binary>> -> {ok, {<<"7"/utf8>>, Rest@7}}; <<"8"/utf8, Rest@8/binary>> -> {ok, {<<"8"/utf8>>, Rest@8}}; <<"9"/utf8, Rest@9/binary>> -> {ok, {<<"9"/utf8>>, Rest@9}}; _ -> {error, nil} end. -file("src/william.gleam", 1257). -spec take_two_digits(binary()) -> {ok, {binary(), binary()}} | {error, nil}. take_two_digits(Input) -> case take_digit(Input) of {ok, {First, Rest}} -> case take_digit(Rest) of {ok, {Second, Rest@1}} -> {ok, {<>, Rest@1}}; {error, _} -> {error, nil} end; {error, _} -> {error, nil} end. -file("src/william.gleam", 1245). -spec offset(lexer(), binary(), binary()) -> {token(), binary()}. offset(Lexer, Input, Acc) -> case take_two_digits(Input) of {ok, {Hour, <<":"/utf8, Rest/binary>>}} -> case take_two_digits(Rest) of {ok, {Minute, Rest@1}} -> number_end( Lexer, Rest@1, <<<<<>/binary, ":"/utf8>>/binary, Minute/binary>>, fun(Field@0) -> {date_time, Field@0} end ); _ -> invalid_number(Lexer, Input, Acc) end; _ -> invalid_number(Lexer, Input, Acc) end. -file("src/william.gleam", 1230). -spec date_time_end(lexer(), binary(), binary(), boolean()) -> {token(), binary()}. date_time_end(Lexer, Input, Acc, Allow_offset) -> case Input of <<"Z"/utf8, Rest/binary>> when Allow_offset -> number_end( Lexer, Rest, <>, fun(Field@0) -> {date_time, Field@0} end ); <<"z"/utf8, Rest@1/binary>> when Allow_offset -> number_end( Lexer, Rest@1, <>, fun(Field@0) -> {date_time, Field@0} end ); <<"+"/utf8, Rest@2/binary>> when Allow_offset -> offset(Lexer, Rest@2, <>); <<"-"/utf8, Rest@3/binary>> when Allow_offset -> offset(Lexer, Rest@3, <>); _ -> number_end( Lexer, Input, Acc, fun(Field@0) -> {date_time, Field@0} end ) end. -file("src/william.gleam", 1209). -spec fraction_digits(lexer(), binary(), binary(), boolean()) -> {token(), binary()}. fraction_digits(Lexer, Input, Acc, Allow_offset) -> case Input of <<"0"/utf8, Rest/binary>> -> fraction_digits(Lexer, Rest, <>, Allow_offset); <<"1"/utf8, Rest@1/binary>> -> fraction_digits( Lexer, Rest@1, <>, Allow_offset ); <<"2"/utf8, Rest@2/binary>> -> fraction_digits( Lexer, Rest@2, <>, Allow_offset ); <<"3"/utf8, Rest@3/binary>> -> fraction_digits( Lexer, Rest@3, <>, Allow_offset ); <<"4"/utf8, Rest@4/binary>> -> fraction_digits( Lexer, Rest@4, <>, Allow_offset ); <<"5"/utf8, Rest@5/binary>> -> fraction_digits( Lexer, Rest@5, <>, Allow_offset ); <<"6"/utf8, Rest@6/binary>> -> fraction_digits( Lexer, Rest@6, <>, Allow_offset ); <<"7"/utf8, Rest@7/binary>> -> fraction_digits( Lexer, Rest@7, <>, Allow_offset ); <<"8"/utf8, Rest@8/binary>> -> fraction_digits( Lexer, Rest@8, <>, Allow_offset ); <<"9"/utf8, Rest@9/binary>> -> fraction_digits( Lexer, Rest@9, <>, Allow_offset ); _ -> date_time_end(Lexer, Input, Acc, Allow_offset) end. -file("src/william.gleam", 1188). -spec fraction(lexer(), binary(), binary(), boolean()) -> {token(), binary()}. fraction(Lexer, Input, Acc, Allow_offset) -> case Input of <<"0"/utf8, Rest/binary>> -> fraction_digits(Lexer, Rest, <>, Allow_offset); <<"1"/utf8, Rest@1/binary>> -> fraction_digits( Lexer, Rest@1, <>, Allow_offset ); <<"2"/utf8, Rest@2/binary>> -> fraction_digits( Lexer, Rest@2, <>, Allow_offset ); <<"3"/utf8, Rest@3/binary>> -> fraction_digits( Lexer, Rest@3, <>, Allow_offset ); <<"4"/utf8, Rest@4/binary>> -> fraction_digits( Lexer, Rest@4, <>, Allow_offset ); <<"5"/utf8, Rest@5/binary>> -> fraction_digits( Lexer, Rest@5, <>, Allow_offset ); <<"6"/utf8, Rest@6/binary>> -> fraction_digits( Lexer, Rest@6, <>, Allow_offset ); <<"7"/utf8, Rest@7/binary>> -> fraction_digits( Lexer, Rest@7, <>, Allow_offset ); <<"8"/utf8, Rest@8/binary>> -> fraction_digits( Lexer, Rest@8, <>, Allow_offset ); <<"9"/utf8, Rest@9/binary>> -> fraction_digits( Lexer, Rest@9, <>, Allow_offset ); _ -> invalid_number(Lexer, Input, Acc) end. -file("src/william.gleam", 1173). -spec time_seconds(lexer(), binary(), binary(), boolean()) -> {token(), binary()}. time_seconds(Lexer, Input, Acc, Allow_offset) -> case take_two_digits(Input) of {ok, {Second, <<"."/utf8, Rest/binary>>}} -> fraction( Lexer, Rest, <<<>/binary, "."/utf8>>, Allow_offset ); {ok, {Second@1, Rest@1}} -> date_time_end( Lexer, Rest@1, <>, Allow_offset ); _ -> invalid_number(Lexer, Input, Acc) end. -file("src/william.gleam", 1155). -spec time_minutes(lexer(), binary(), binary(), boolean()) -> {token(), binary()}. time_minutes(Lexer, Input, Acc, Allow_offset) -> case take_two_digits(Input) of {ok, {Minute, Rest}} -> Acc@1 = <>, case Rest of <<":"/utf8, Rest@1/binary>> -> time_seconds( Lexer, Rest@1, <>, Allow_offset ); _ -> date_time_end(Lexer, Rest, Acc@1, Allow_offset) end; _ -> invalid_number(Lexer, Input, Acc) end. -file("src/william.gleam", 1147). -spec date_time(lexer(), binary(), binary()) -> {token(), binary()}. date_time(Lexer, Input, Acc) -> case take_two_digits(Input) of {ok, {Hour, <<":"/utf8, Rest/binary>>}} -> time_minutes( Lexer, Rest, <<<>/binary, ":"/utf8>>, true ); _ -> invalid_number(Lexer, Input, Acc) end. -file("src/william.gleam", 1133). -spec date_tail(lexer(), binary(), binary()) -> {token(), binary()}. date_tail(Lexer, Input, Acc) -> case Input of <<"T"/utf8, Rest/binary>> -> date_time(Lexer, Rest, <>); <<"t"/utf8, Rest@1/binary>> -> date_time(Lexer, Rest@1, <>); <<" "/utf8, Rest@2/binary>> -> case take_two_digits(Rest@2) of {ok, {Hour, <<":"/utf8, Rest@3/binary>>}} -> time_minutes( Lexer, Rest@3, <<<<<>/binary, Hour/binary>>/binary, ":"/utf8>>, true ); _ -> number_end( Lexer, Input, Acc, fun(Field@0) -> {date_time, Field@0} end ) end; _ -> number_end( Lexer, Input, Acc, fun(Field@0) -> {date_time, Field@0} end ) end. -file("src/william.gleam", 1122). -spec date(lexer(), binary(), binary()) -> {token(), binary()}. date(Lexer, Input, Acc) -> case take_two_digits(Input) of {ok, {Month, <<"-"/utf8, Rest/binary>>}} -> case take_two_digits(Rest) of {ok, {Day, Rest@1}} -> date_tail( Lexer, Rest@1, <<<<<>/binary, "-"/utf8>>/binary, Day/binary>> ); _ -> invalid_number(Lexer, Input, Acc) end; _ -> invalid_number(Lexer, Input, Acc) end. -file("src/william.gleam", 1096). -spec exponent(lexer(), binary(), binary()) -> {token(), binary()}. exponent(Lexer, Input, Acc) -> case Input of <<"0"/utf8, Rest/binary>> -> exponent(Lexer, Rest, <>); <<"1"/utf8, Rest@1/binary>> -> exponent(Lexer, Rest@1, <>); <<"2"/utf8, Rest@2/binary>> -> exponent(Lexer, Rest@2, <>); <<"3"/utf8, Rest@3/binary>> -> exponent(Lexer, Rest@3, <>); <<"4"/utf8, Rest@4/binary>> -> exponent(Lexer, Rest@4, <>); <<"5"/utf8, Rest@5/binary>> -> exponent(Lexer, Rest@5, <>); <<"6"/utf8, Rest@6/binary>> -> exponent(Lexer, Rest@6, <>); <<"7"/utf8, Rest@7/binary>> -> exponent(Lexer, Rest@7, <>); <<"8"/utf8, Rest@8/binary>> -> exponent(Lexer, Rest@8, <>); <<"9"/utf8, Rest@9/binary>> -> exponent(Lexer, Rest@9, <>); <<"_0"/utf8, Rest@10/binary>> -> exponent(Lexer, Rest@10, <>); <<"_1"/utf8, Rest@11/binary>> -> exponent(Lexer, Rest@11, <>); <<"_2"/utf8, Rest@12/binary>> -> exponent(Lexer, Rest@12, <>); <<"_3"/utf8, Rest@13/binary>> -> exponent(Lexer, Rest@13, <>); <<"_4"/utf8, Rest@14/binary>> -> exponent(Lexer, Rest@14, <>); <<"_5"/utf8, Rest@15/binary>> -> exponent(Lexer, Rest@15, <>); <<"_6"/utf8, Rest@16/binary>> -> exponent(Lexer, Rest@16, <>); <<"_7"/utf8, Rest@17/binary>> -> exponent(Lexer, Rest@17, <>); <<"_8"/utf8, Rest@18/binary>> -> exponent(Lexer, Rest@18, <>); <<"_9"/utf8, Rest@19/binary>> -> exponent(Lexer, Rest@19, <>); _ -> number_end(Lexer, Input, Acc, fun(Field@0) -> {float, Field@0} end) end. -file("src/william.gleam", 1074). -spec exponent_start(lexer(), binary(), binary(), binary(), binary()) -> {token(), binary()}. exponent_start(Lexer, Before_marker, Input, Acc, Marker) -> case Input of <<"0"/utf8, Rest/binary>> -> exponent( Lexer, Rest, <<<>/binary, "0"/utf8>> ); <<"1"/utf8, Rest@1/binary>> -> exponent( Lexer, Rest@1, <<<>/binary, "1"/utf8>> ); <<"2"/utf8, Rest@2/binary>> -> exponent( Lexer, Rest@2, <<<>/binary, "2"/utf8>> ); <<"3"/utf8, Rest@3/binary>> -> exponent( Lexer, Rest@3, <<<>/binary, "3"/utf8>> ); <<"4"/utf8, Rest@4/binary>> -> exponent( Lexer, Rest@4, <<<>/binary, "4"/utf8>> ); <<"5"/utf8, Rest@5/binary>> -> exponent( Lexer, Rest@5, <<<>/binary, "5"/utf8>> ); <<"6"/utf8, Rest@6/binary>> -> exponent( Lexer, Rest@6, <<<>/binary, "6"/utf8>> ); <<"7"/utf8, Rest@7/binary>> -> exponent( Lexer, Rest@7, <<<>/binary, "7"/utf8>> ); <<"8"/utf8, Rest@8/binary>> -> exponent( Lexer, Rest@8, <<<>/binary, "8"/utf8>> ); <<"9"/utf8, Rest@9/binary>> -> exponent( Lexer, Rest@9, <<<>/binary, "9"/utf8>> ); _ -> invalid_number(Lexer, Before_marker, Acc) end. -file("src/william.gleam", 1042). -spec float(lexer(), binary(), binary()) -> {token(), binary()}. float(Lexer, Input, Acc) -> case Input of <<"0"/utf8, Rest/binary>> -> float(Lexer, Rest, <>); <<"1"/utf8, Rest@1/binary>> -> float(Lexer, Rest@1, <>); <<"2"/utf8, Rest@2/binary>> -> float(Lexer, Rest@2, <>); <<"3"/utf8, Rest@3/binary>> -> float(Lexer, Rest@3, <>); <<"4"/utf8, Rest@4/binary>> -> float(Lexer, Rest@4, <>); <<"5"/utf8, Rest@5/binary>> -> float(Lexer, Rest@5, <>); <<"6"/utf8, Rest@6/binary>> -> float(Lexer, Rest@6, <>); <<"7"/utf8, Rest@7/binary>> -> float(Lexer, Rest@7, <>); <<"8"/utf8, Rest@8/binary>> -> float(Lexer, Rest@8, <>); <<"9"/utf8, Rest@9/binary>> -> float(Lexer, Rest@9, <>); <<"_0"/utf8, Rest@10/binary>> -> float(Lexer, Rest@10, <>); <<"_1"/utf8, Rest@11/binary>> -> float(Lexer, Rest@11, <>); <<"_2"/utf8, Rest@12/binary>> -> float(Lexer, Rest@12, <>); <<"_3"/utf8, Rest@13/binary>> -> float(Lexer, Rest@13, <>); <<"_4"/utf8, Rest@14/binary>> -> float(Lexer, Rest@14, <>); <<"_5"/utf8, Rest@15/binary>> -> float(Lexer, Rest@15, <>); <<"_6"/utf8, Rest@16/binary>> -> float(Lexer, Rest@16, <>); <<"_7"/utf8, Rest@17/binary>> -> float(Lexer, Rest@17, <>); <<"_8"/utf8, Rest@18/binary>> -> float(Lexer, Rest@18, <>); <<"_9"/utf8, Rest@19/binary>> -> float(Lexer, Rest@19, <>); <<"e+"/utf8, Rest@20/binary>> -> exponent_start(Lexer, Input, Rest@20, Acc, <<"e+"/utf8>>); <<"e-"/utf8, Rest@21/binary>> -> exponent_start(Lexer, Input, Rest@21, Acc, <<"e-"/utf8>>); <<"e"/utf8, Rest@22/binary>> -> exponent_start(Lexer, Input, Rest@22, Acc, <<"e"/utf8>>); <<"E+"/utf8, Rest@23/binary>> -> exponent_start(Lexer, Input, Rest@23, Acc, <<"E+"/utf8>>); <<"E-"/utf8, Rest@24/binary>> -> exponent_start(Lexer, Input, Rest@24, Acc, <<"E-"/utf8>>); <<"E"/utf8, Rest@25/binary>> -> exponent_start(Lexer, Input, Rest@25, Acc, <<"E"/utf8>>); _ -> number_end(Lexer, Input, Acc, fun(Field@0) -> {float, Field@0} end) end. -file("src/william.gleam", 988). -spec decimal(lexer(), binary(), binary(), integer(), boolean()) -> {token(), binary()}. decimal(Lexer, Input, Acc, Digits, Date_time) -> case Input of <<"0"/utf8, Rest/binary>> -> decimal( Lexer, Rest, <>, Digits + 1, Date_time ); <<"1"/utf8, Rest@1/binary>> -> decimal( Lexer, Rest@1, <>, Digits + 1, Date_time ); <<"2"/utf8, Rest@2/binary>> -> decimal( Lexer, Rest@2, <>, Digits + 1, Date_time ); <<"3"/utf8, Rest@3/binary>> -> decimal( Lexer, Rest@3, <>, Digits + 1, Date_time ); <<"4"/utf8, Rest@4/binary>> -> decimal( Lexer, Rest@4, <>, Digits + 1, Date_time ); <<"5"/utf8, Rest@5/binary>> -> decimal( Lexer, Rest@5, <>, Digits + 1, Date_time ); <<"6"/utf8, Rest@6/binary>> -> decimal( Lexer, Rest@6, <>, Digits + 1, Date_time ); <<"7"/utf8, Rest@7/binary>> -> decimal( Lexer, Rest@7, <>, Digits + 1, Date_time ); <<"8"/utf8, Rest@8/binary>> -> decimal( Lexer, Rest@8, <>, Digits + 1, Date_time ); <<"9"/utf8, Rest@9/binary>> -> decimal( Lexer, Rest@9, <>, Digits + 1, Date_time ); <<"_0"/utf8, Rest@10/binary>> -> decimal( Lexer, Rest@10, <>, Digits + 1, false ); <<"_1"/utf8, Rest@11/binary>> -> decimal( Lexer, Rest@11, <>, Digits + 1, false ); <<"_2"/utf8, Rest@12/binary>> -> decimal( Lexer, Rest@12, <>, Digits + 1, false ); <<"_3"/utf8, Rest@13/binary>> -> decimal( Lexer, Rest@13, <>, Digits + 1, false ); <<"_4"/utf8, Rest@14/binary>> -> decimal( Lexer, Rest@14, <>, Digits + 1, false ); <<"_5"/utf8, Rest@15/binary>> -> decimal( Lexer, Rest@15, <>, Digits + 1, false ); <<"_6"/utf8, Rest@16/binary>> -> decimal( Lexer, Rest@16, <>, Digits + 1, false ); <<"_7"/utf8, Rest@17/binary>> -> decimal( Lexer, Rest@17, <>, Digits + 1, false ); <<"_8"/utf8, Rest@18/binary>> -> decimal( Lexer, Rest@18, <>, Digits + 1, false ); <<"_9"/utf8, Rest@19/binary>> -> decimal( Lexer, Rest@19, <>, Digits + 1, false ); <<".0"/utf8, Rest@20/binary>> -> float(Lexer, Rest@20, <>); <<".1"/utf8, Rest@21/binary>> -> float(Lexer, Rest@21, <>); <<".2"/utf8, Rest@22/binary>> -> float(Lexer, Rest@22, <>); <<".3"/utf8, Rest@23/binary>> -> float(Lexer, Rest@23, <>); <<".4"/utf8, Rest@24/binary>> -> float(Lexer, Rest@24, <>); <<".5"/utf8, Rest@25/binary>> -> float(Lexer, Rest@25, <>); <<".6"/utf8, Rest@26/binary>> -> float(Lexer, Rest@26, <>); <<".7"/utf8, Rest@27/binary>> -> float(Lexer, Rest@27, <>); <<".8"/utf8, Rest@28/binary>> -> float(Lexer, Rest@28, <>); <<".9"/utf8, Rest@29/binary>> -> float(Lexer, Rest@29, <>); <<"e+"/utf8, Rest@30/binary>> -> exponent_start(Lexer, Input, Rest@30, Acc, <<"e+"/utf8>>); <<"e-"/utf8, Rest@31/binary>> -> exponent_start(Lexer, Input, Rest@31, Acc, <<"e-"/utf8>>); <<"e"/utf8, Rest@32/binary>> -> exponent_start(Lexer, Input, Rest@32, Acc, <<"e"/utf8>>); <<"E+"/utf8, Rest@33/binary>> -> exponent_start(Lexer, Input, Rest@33, Acc, <<"E+"/utf8>>); <<"E-"/utf8, Rest@34/binary>> -> exponent_start(Lexer, Input, Rest@34, Acc, <<"E-"/utf8>>); <<"E"/utf8, Rest@35/binary>> -> exponent_start(Lexer, Input, Rest@35, Acc, <<"E"/utf8>>); <<":"/utf8, Rest@36/binary>> when Date_time andalso (Digits =:= 2) -> time_minutes(Lexer, Rest@36, <>, false); <<"-"/utf8, Rest@37/binary>> when Date_time andalso (Digits =:= 4) -> date(Lexer, Rest@37, <>); _ -> To_token = fun(Value) -> {integer, decimal, Value} end, number_end(Lexer, Input, Acc, To_token) end. -file("src/william.gleam", 972). -spec based_integer_end(lexer(), binary(), binary(), base(), boolean()) -> {token(), binary()}. based_integer_end(Lexer, Input, Acc, Base, Last_was_underscore) -> case Last_was_underscore of false -> To_token = fun(Value) -> {integer, Base, Value} end, number_end(Lexer, Input, Acc, To_token); true -> invalid_number(Lexer, Input, Acc) end. -file("src/william.gleam", 935). -spec hexadecimal(lexer(), binary(), binary(), boolean()) -> {token(), binary()}. hexadecimal(Lexer, Input, Acc, Last_was_underscore) -> case Input of <<"0"/utf8, Rest/binary>> -> hexadecimal(Lexer, Rest, <>, false); <<"1"/utf8, Rest@1/binary>> -> hexadecimal(Lexer, Rest@1, <>, false); <<"2"/utf8, Rest@2/binary>> -> hexadecimal(Lexer, Rest@2, <>, false); <<"3"/utf8, Rest@3/binary>> -> hexadecimal(Lexer, Rest@3, <>, false); <<"4"/utf8, Rest@4/binary>> -> hexadecimal(Lexer, Rest@4, <>, false); <<"5"/utf8, Rest@5/binary>> -> hexadecimal(Lexer, Rest@5, <>, false); <<"6"/utf8, Rest@6/binary>> -> hexadecimal(Lexer, Rest@6, <>, false); <<"7"/utf8, Rest@7/binary>> -> hexadecimal(Lexer, Rest@7, <>, false); <<"8"/utf8, Rest@8/binary>> -> hexadecimal(Lexer, Rest@8, <>, false); <<"9"/utf8, Rest@9/binary>> -> hexadecimal(Lexer, Rest@9, <>, false); <<"A"/utf8, Rest@10/binary>> -> hexadecimal(Lexer, Rest@10, <>, false); <<"B"/utf8, Rest@11/binary>> -> hexadecimal(Lexer, Rest@11, <>, false); <<"C"/utf8, Rest@12/binary>> -> hexadecimal(Lexer, Rest@12, <>, false); <<"D"/utf8, Rest@13/binary>> -> hexadecimal(Lexer, Rest@13, <>, false); <<"E"/utf8, Rest@14/binary>> -> hexadecimal(Lexer, Rest@14, <>, false); <<"F"/utf8, Rest@15/binary>> -> hexadecimal(Lexer, Rest@15, <>, false); <<"a"/utf8, Rest@16/binary>> -> hexadecimal(Lexer, Rest@16, <>, false); <<"b"/utf8, Rest@17/binary>> -> hexadecimal(Lexer, Rest@17, <>, false); <<"c"/utf8, Rest@18/binary>> -> hexadecimal(Lexer, Rest@18, <>, false); <<"d"/utf8, Rest@19/binary>> -> hexadecimal(Lexer, Rest@19, <>, false); <<"e"/utf8, Rest@20/binary>> -> hexadecimal(Lexer, Rest@20, <>, false); <<"f"/utf8, Rest@21/binary>> -> hexadecimal(Lexer, Rest@21, <>, false); <<"_"/utf8, Rest@22/binary>> when not Last_was_underscore -> Acc@1 = <>, hexadecimal(Lexer, Rest@22, Acc@1, true); _ -> based_integer_end( Lexer, Input, Acc, hexadecimal, Last_was_underscore ) end. -file("src/william.gleam", 912). -spec octal(lexer(), binary(), binary(), boolean()) -> {token(), binary()}. octal(Lexer, Input, Acc, Last_was_underscore) -> case Input of <<"0"/utf8, Rest/binary>> -> octal(Lexer, Rest, <>, false); <<"1"/utf8, Rest@1/binary>> -> octal(Lexer, Rest@1, <>, false); <<"2"/utf8, Rest@2/binary>> -> octal(Lexer, Rest@2, <>, false); <<"3"/utf8, Rest@3/binary>> -> octal(Lexer, Rest@3, <>, false); <<"4"/utf8, Rest@4/binary>> -> octal(Lexer, Rest@4, <>, false); <<"5"/utf8, Rest@5/binary>> -> octal(Lexer, Rest@5, <>, false); <<"6"/utf8, Rest@6/binary>> -> octal(Lexer, Rest@6, <>, false); <<"7"/utf8, Rest@7/binary>> -> octal(Lexer, Rest@7, <>, false); <<"_"/utf8, Rest@8/binary>> when not Last_was_underscore -> Acc@1 = <>, octal(Lexer, Rest@8, Acc@1, true); _ -> based_integer_end(Lexer, Input, Acc, octal, Last_was_underscore) end. -file("src/william.gleam", 895). -spec binary(lexer(), binary(), binary(), boolean()) -> {token(), binary()}. binary(Lexer, Input, Acc, Last_was_underscore) -> case Input of <<"0"/utf8, Rest/binary>> -> binary(Lexer, Rest, <>, false); <<"1"/utf8, Rest@1/binary>> -> binary(Lexer, Rest@1, <>, false); <<"_"/utf8, Rest@2/binary>> when not Last_was_underscore -> Acc@1 = <>, binary(Lexer, Rest@2, Acc@1, true); _ -> based_integer_end(Lexer, Input, Acc, binary, Last_was_underscore) end. -file("src/william.gleam", 757). -spec literal_or_unexpected(lexer(), binary(), token(), binary()) -> {token(), binary()}. literal_or_unexpected(Lexer, Rest, Token, Original) -> case is_value_terminator(Rest) of true -> {Token, Rest}; false -> unexpected(Lexer, Original, <<""/utf8>>) end. -file("src/william.gleam", 712). -spec value(lexer(), binary()) -> {token(), binary()}. value(Lexer, Input) -> case Input of <<"true"/utf8, Rest/binary>> -> literal_or_unexpected( Lexer, Rest, {boolean, <<"true"/utf8>>}, Input ); <<"false"/utf8, Rest@1/binary>> -> literal_or_unexpected( Lexer, Rest@1, {boolean, <<"false"/utf8>>}, Input ); <<"inf"/utf8, Rest@2/binary>> -> literal_or_unexpected(Lexer, Rest@2, {float, <<"inf"/utf8>>}, Input); <<"+inf"/utf8, Rest@3/binary>> -> literal_or_unexpected( Lexer, Rest@3, {float, <<"+inf"/utf8>>}, Input ); <<"-inf"/utf8, Rest@4/binary>> -> literal_or_unexpected( Lexer, Rest@4, {float, <<"-inf"/utf8>>}, Input ); <<"nan"/utf8, Rest@5/binary>> -> literal_or_unexpected(Lexer, Rest@5, {float, <<"nan"/utf8>>}, Input); <<"+nan"/utf8, Rest@6/binary>> -> literal_or_unexpected( Lexer, Rest@6, {float, <<"+nan"/utf8>>}, Input ); <<"-nan"/utf8, Rest@7/binary>> -> literal_or_unexpected( Lexer, Rest@7, {float, <<"-nan"/utf8>>}, Input ); <<"+0b"/utf8, _/binary>> -> invalid_number(Lexer, Input, <<""/utf8>>); <<"+0o"/utf8, _/binary>> -> invalid_number(Lexer, Input, <<""/utf8>>); <<"+0x"/utf8, _/binary>> -> invalid_number(Lexer, Input, <<""/utf8>>); <<"-0b"/utf8, _/binary>> -> invalid_number(Lexer, Input, <<""/utf8>>); <<"-0o"/utf8, _/binary>> -> invalid_number(Lexer, Input, <<""/utf8>>); <<"-0x"/utf8, _/binary>> -> invalid_number(Lexer, Input, <<""/utf8>>); <<"+"/utf8, Rest@8/binary>> -> case take_digit(Rest@8) of {ok, {Digit, Rest@9}} -> decimal(Lexer, Rest@9, <<"+"/utf8, Digit/binary>>, 1, false); {error, _} -> invalid_number(Lexer, Rest@8, <<"+"/utf8>>) end; <<"-"/utf8, Rest@10/binary>> -> case take_digit(Rest@10) of {ok, {Digit@1, Rest@11}} -> decimal( Lexer, Rest@11, <<"-"/utf8, Digit@1/binary>>, 1, false ); {error, _} -> invalid_number(Lexer, Rest@10, <<"-"/utf8>>) end; <<"."/utf8, _/binary>> -> invalid_number(Lexer, Input, <<""/utf8>>); <<"0b"/utf8, Rest@12/binary>> -> binary(Lexer, Rest@12, <<"0b"/utf8>>, true); <<"0o"/utf8, Rest@13/binary>> -> octal(Lexer, Rest@13, <<"0o"/utf8>>, true); <<"0x"/utf8, Rest@14/binary>> -> hexadecimal(Lexer, Rest@14, <<"0x"/utf8>>, true); <<"0"/utf8, _/binary>> -> case take_digit(Input) of {ok, {Digit@2, Rest@15}} -> decimal(Lexer, Rest@15, Digit@2, 1, true); {error, _} -> invalid_number(Lexer, Input, <<""/utf8>>) end; <<"1"/utf8, _/binary>> -> case take_digit(Input) of {ok, {Digit@2, Rest@15}} -> decimal(Lexer, Rest@15, Digit@2, 1, true); {error, _} -> invalid_number(Lexer, Input, <<""/utf8>>) end; <<"2"/utf8, _/binary>> -> case take_digit(Input) of {ok, {Digit@2, Rest@15}} -> decimal(Lexer, Rest@15, Digit@2, 1, true); {error, _} -> invalid_number(Lexer, Input, <<""/utf8>>) end; <<"3"/utf8, _/binary>> -> case take_digit(Input) of {ok, {Digit@2, Rest@15}} -> decimal(Lexer, Rest@15, Digit@2, 1, true); {error, _} -> invalid_number(Lexer, Input, <<""/utf8>>) end; <<"4"/utf8, _/binary>> -> case take_digit(Input) of {ok, {Digit@2, Rest@15}} -> decimal(Lexer, Rest@15, Digit@2, 1, true); {error, _} -> invalid_number(Lexer, Input, <<""/utf8>>) end; <<"5"/utf8, _/binary>> -> case take_digit(Input) of {ok, {Digit@2, Rest@15}} -> decimal(Lexer, Rest@15, Digit@2, 1, true); {error, _} -> invalid_number(Lexer, Input, <<""/utf8>>) end; <<"6"/utf8, _/binary>> -> case take_digit(Input) of {ok, {Digit@2, Rest@15}} -> decimal(Lexer, Rest@15, Digit@2, 1, true); {error, _} -> invalid_number(Lexer, Input, <<""/utf8>>) end; <<"7"/utf8, _/binary>> -> case take_digit(Input) of {ok, {Digit@2, Rest@15}} -> decimal(Lexer, Rest@15, Digit@2, 1, true); {error, _} -> invalid_number(Lexer, Input, <<""/utf8>>) end; <<"8"/utf8, _/binary>> -> case take_digit(Input) of {ok, {Digit@2, Rest@15}} -> decimal(Lexer, Rest@15, Digit@2, 1, true); {error, _} -> invalid_number(Lexer, Input, <<""/utf8>>) end; <<"9"/utf8, _/binary>> -> case take_digit(Input) of {ok, {Digit@2, Rest@15}} -> decimal(Lexer, Rest@15, Digit@2, 1, true); {error, _} -> invalid_number(Lexer, Input, <<""/utf8>>) end; _ -> unexpected(Lexer, Input, <<""/utf8>>) end. -file("src/william.gleam", 642). -spec bare_key(binary(), binary()) -> {binary(), binary()}. bare_key(Input, Acc) -> case Input of <<"A"/utf8, Rest/binary>> -> bare_key(Rest, <>); <<"B"/utf8, Rest@1/binary>> -> bare_key(Rest@1, <>); <<"C"/utf8, Rest@2/binary>> -> bare_key(Rest@2, <>); <<"D"/utf8, Rest@3/binary>> -> bare_key(Rest@3, <>); <<"E"/utf8, Rest@4/binary>> -> bare_key(Rest@4, <>); <<"F"/utf8, Rest@5/binary>> -> bare_key(Rest@5, <>); <<"G"/utf8, Rest@6/binary>> -> bare_key(Rest@6, <>); <<"H"/utf8, Rest@7/binary>> -> bare_key(Rest@7, <>); <<"I"/utf8, Rest@8/binary>> -> bare_key(Rest@8, <>); <<"J"/utf8, Rest@9/binary>> -> bare_key(Rest@9, <>); <<"K"/utf8, Rest@10/binary>> -> bare_key(Rest@10, <>); <<"L"/utf8, Rest@11/binary>> -> bare_key(Rest@11, <>); <<"M"/utf8, Rest@12/binary>> -> bare_key(Rest@12, <>); <<"N"/utf8, Rest@13/binary>> -> bare_key(Rest@13, <>); <<"O"/utf8, Rest@14/binary>> -> bare_key(Rest@14, <>); <<"P"/utf8, Rest@15/binary>> -> bare_key(Rest@15, <>); <<"Q"/utf8, Rest@16/binary>> -> bare_key(Rest@16, <>); <<"R"/utf8, Rest@17/binary>> -> bare_key(Rest@17, <>); <<"S"/utf8, Rest@18/binary>> -> bare_key(Rest@18, <>); <<"T"/utf8, Rest@19/binary>> -> bare_key(Rest@19, <>); <<"U"/utf8, Rest@20/binary>> -> bare_key(Rest@20, <>); <<"V"/utf8, Rest@21/binary>> -> bare_key(Rest@21, <>); <<"W"/utf8, Rest@22/binary>> -> bare_key(Rest@22, <>); <<"X"/utf8, Rest@23/binary>> -> bare_key(Rest@23, <>); <<"Y"/utf8, Rest@24/binary>> -> bare_key(Rest@24, <>); <<"Z"/utf8, Rest@25/binary>> -> bare_key(Rest@25, <>); <<"a"/utf8, Rest@26/binary>> -> bare_key(Rest@26, <>); <<"b"/utf8, Rest@27/binary>> -> bare_key(Rest@27, <>); <<"c"/utf8, Rest@28/binary>> -> bare_key(Rest@28, <>); <<"d"/utf8, Rest@29/binary>> -> bare_key(Rest@29, <>); <<"e"/utf8, Rest@30/binary>> -> bare_key(Rest@30, <>); <<"f"/utf8, Rest@31/binary>> -> bare_key(Rest@31, <>); <<"g"/utf8, Rest@32/binary>> -> bare_key(Rest@32, <>); <<"h"/utf8, Rest@33/binary>> -> bare_key(Rest@33, <>); <<"i"/utf8, Rest@34/binary>> -> bare_key(Rest@34, <>); <<"j"/utf8, Rest@35/binary>> -> bare_key(Rest@35, <>); <<"k"/utf8, Rest@36/binary>> -> bare_key(Rest@36, <>); <<"l"/utf8, Rest@37/binary>> -> bare_key(Rest@37, <>); <<"m"/utf8, Rest@38/binary>> -> bare_key(Rest@38, <>); <<"n"/utf8, Rest@39/binary>> -> bare_key(Rest@39, <>); <<"o"/utf8, Rest@40/binary>> -> bare_key(Rest@40, <>); <<"p"/utf8, Rest@41/binary>> -> bare_key(Rest@41, <>); <<"q"/utf8, Rest@42/binary>> -> bare_key(Rest@42, <>); <<"r"/utf8, Rest@43/binary>> -> bare_key(Rest@43, <>); <<"s"/utf8, Rest@44/binary>> -> bare_key(Rest@44, <>); <<"t"/utf8, Rest@45/binary>> -> bare_key(Rest@45, <>); <<"u"/utf8, Rest@46/binary>> -> bare_key(Rest@46, <>); <<"v"/utf8, Rest@47/binary>> -> bare_key(Rest@47, <>); <<"w"/utf8, Rest@48/binary>> -> bare_key(Rest@48, <>); <<"x"/utf8, Rest@49/binary>> -> bare_key(Rest@49, <>); <<"y"/utf8, Rest@50/binary>> -> bare_key(Rest@50, <>); <<"z"/utf8, Rest@51/binary>> -> bare_key(Rest@51, <>); <<"0"/utf8, Rest@52/binary>> -> bare_key(Rest@52, <>); <<"1"/utf8, Rest@53/binary>> -> bare_key(Rest@53, <>); <<"2"/utf8, Rest@54/binary>> -> bare_key(Rest@54, <>); <<"3"/utf8, Rest@55/binary>> -> bare_key(Rest@55, <>); <<"4"/utf8, Rest@56/binary>> -> bare_key(Rest@56, <>); <<"5"/utf8, Rest@57/binary>> -> bare_key(Rest@57, <>); <<"6"/utf8, Rest@58/binary>> -> bare_key(Rest@58, <>); <<"7"/utf8, Rest@59/binary>> -> bare_key(Rest@59, <>); <<"8"/utf8, Rest@60/binary>> -> bare_key(Rest@60, <>); <<"9"/utf8, Rest@61/binary>> -> bare_key(Rest@61, <>); <<"-"/utf8, Rest@62/binary>> -> bare_key(Rest@62, <>); <<"_"/utf8, Rest@63/binary>> -> bare_key(Rest@63, <>); _ -> {Acc, Input} end. -file("src/william.gleam", 600). -spec mode_after_string(mode()) -> mode(). mode_after_string(Mode) -> case Mode of value_mode -> after_value_mode; _ -> Mode end. -file("src/william.gleam", 814). -spec literal_string(lexer(), binary(), binary()) -> {token(), binary()}. literal_string(Lexer, Input, Acc) -> {Before, Delimiter, Rest} = splitter_ffi:split( erlang:element(8, Lexer), Input ), case Delimiter of <<"'"/utf8>> -> {{string, literal_string, <>}, Rest}; <<"\r\n"/utf8>> -> {{unterminated_string, literal_string, <>}, <>}; <<"\n"/utf8>> -> {{unterminated_string, literal_string, <>}, <>}; <<"\r"/utf8>> -> {{unterminated_string, literal_string, <>}, <>}; <<""/utf8>> -> {{unterminated_string, literal_string, <>}, <<""/utf8>>}; _ -> {{unterminated_string, literal_string, <<<>/binary, Delimiter/binary>>}, Rest} end. -file("src/william.gleam", 876). -spec multiline_literal_string(lexer(), binary(), binary()) -> {token(), binary()}. multiline_literal_string(Lexer, Input, Acc) -> {Before, Delimiter, Rest} = splitter_ffi:split( erlang:element(10, Lexer), Input ), case Delimiter of <<"'''''"/utf8>> -> {{string, multiline_literal_string, <<<>/binary, "''"/utf8>>}, Rest}; <<"''''"/utf8>> -> {{string, multiline_literal_string, <<<>/binary, "'"/utf8>>}, Rest}; <<"'''"/utf8>> -> {{string, multiline_literal_string, <>}, Rest}; <<""/utf8>> -> {{unterminated_string, multiline_literal_string, <>}, <<""/utf8>>}; _ -> {{unterminated_string, multiline_literal_string, <<<>/binary, Delimiter/binary>>}, Rest} end. -file("src/william.gleam", 788). -spec basic_string_escape(lexer(), binary(), binary()) -> {token(), binary()}. basic_string_escape(Lexer, Input, Acc) -> case Input of <<""/utf8>> -> {{unterminated_string, basic_string, Acc}, <<""/utf8>>}; <<"\r\n"/utf8, _/binary>> -> {{unterminated_string, basic_string, Acc}, Input}; <<"\n"/utf8, _/binary>> -> {{unterminated_string, basic_string, Acc}, Input}; <<"\r"/utf8, _/binary>> -> {{unterminated_string, basic_string, Acc}, Input}; <<"\""/utf8, Rest/binary>> -> basic_string(Lexer, Rest, <>); <<"\\"/utf8, Rest@1/binary>> -> basic_string(Lexer, Rest@1, <>); _ -> {Escaped, Delimiter, Rest@2} = splitter_ffi:split( erlang:element(7, Lexer), Input ), case {Escaped, Delimiter} of {<<""/utf8>>, <<""/utf8>>} -> {{unterminated_string, basic_string, Acc}, <<""/utf8>>}; {_, <<""/utf8>>} -> {{unterminated_string, basic_string, <>}, <<""/utf8>>}; {<<""/utf8>>, _} -> basic_string( Lexer, Rest@2, <> ); {_, _} -> basic_string( Lexer, <>, <> ) end end. -file("src/william.gleam", 774). -spec basic_string(lexer(), binary(), binary()) -> {token(), binary()}. basic_string(Lexer, Input, Acc) -> {Before, Delimiter, Rest} = splitter_ffi:split( erlang:element(7, Lexer), Input ), case Delimiter of <<"\""/utf8>> -> {{string, basic_string, <>}, Rest}; <<"\r\n"/utf8>> -> {{unterminated_string, basic_string, <>}, <>}; <<"\n"/utf8>> -> {{unterminated_string, basic_string, <>}, <>}; <<"\r"/utf8>> -> {{unterminated_string, basic_string, <>}, <>}; <<"\\"/utf8>> -> basic_string_escape( Lexer, Rest, <<<>/binary, "\\"/utf8>> ); <<""/utf8>> -> {{unterminated_string, basic_string, <>}, <<""/utf8>>}; _ -> {{unterminated_string, basic_string, <<<>/binary, Delimiter/binary>>}, Rest} end. -file("src/william.gleam", 854). -spec multiline_basic_string_escape(lexer(), binary(), binary()) -> {token(), binary()}. multiline_basic_string_escape(Lexer, Input, Acc) -> case Input of <<""/utf8>> -> {{unterminated_string, multiline_basic_string, Acc}, <<""/utf8>>}; <<"\""/utf8, Rest/binary>> -> multiline_basic_string(Lexer, Rest, <>); <<"\\"/utf8, Rest@1/binary>> -> multiline_basic_string(Lexer, Rest@1, <>); _ -> {Escaped, Delimiter, Rest@2} = splitter_ffi:split( erlang:element(9, Lexer), Input ), case {Escaped, Delimiter} of {<<""/utf8>>, <<""/utf8>>} -> {{unterminated_string, multiline_basic_string, Acc}, <<""/utf8>>}; {_, <<""/utf8>>} -> {{unterminated_string, multiline_basic_string, <>}, <<""/utf8>>}; {<<""/utf8>>, _} -> multiline_basic_string( Lexer, Rest@2, <> ); {_, _} -> multiline_basic_string( Lexer, <>, <> ) end end. -file("src/william.gleam", 831). -spec multiline_basic_string(lexer(), binary(), binary()) -> {token(), binary()}. multiline_basic_string(Lexer, Input, Acc) -> {Before, Delimiter, Rest} = splitter_ffi:split( erlang:element(9, Lexer), Input ), case Delimiter of <<"\"\"\"\"\""/utf8>> -> {{string, multiline_basic_string, <<<>/binary, "\"\""/utf8>>}, Rest}; <<"\"\"\"\""/utf8>> -> {{string, multiline_basic_string, <<<>/binary, "\""/utf8>>}, Rest}; <<"\"\"\""/utf8>> -> {{string, multiline_basic_string, <>}, Rest}; <<"\\"/utf8>> -> multiline_basic_string_escape( Lexer, Rest, <<<>/binary, "\\"/utf8>> ); <<""/utf8>> -> {{unterminated_string, multiline_basic_string, <>}, <<""/utf8>>}; _ -> {{unterminated_string, multiline_basic_string, <<<>/binary, Delimiter/binary>>}, Rest} end. -file("src/william.gleam", 621). -spec mode_after_comma(list(container())) -> mode(). mode_after_comma(Containers) -> case Containers of [inline_table_container | _] -> key_mode; [array_container | _] -> value_mode; [] -> value_mode end. -file("src/william.gleam", 614). -spec close_inline_table(list(container())) -> list(container()). close_inline_table(Containers) -> case Containers of [inline_table_container | Containers@1] -> Containers@1; _ -> Containers end. -file("src/william.gleam", 607). -spec close_array(list(container())) -> list(container()). close_array(Containers) -> case Containers of [array_container | Containers@1] -> Containers@1; _ -> Containers end. -file("src/william.gleam", 637). -spec comment(lexer(), binary()) -> {token(), binary()}. comment(Lexer, Input) -> {Body, Rest} = splitter_ffi:split_before(erlang:element(4, Lexer), Input), {{comment, <<"#"/utf8, Body/binary>>}, Rest}. -file("src/william.gleam", 629). -spec whitespace(binary(), binary()) -> {token(), binary()}. whitespace(Input, Acc) -> case Input of <<" "/utf8, Rest/binary>> -> whitespace(Rest, <>); <<"\t"/utf8, Rest@1/binary>> -> whitespace(Rest@1, <>); _ -> {{whitespace, Acc}, Input} end. -file("src/william.gleam", 593). -spec reset_mode_after_newline(mode(), list(container())) -> mode(). reset_mode_after_newline(Mode, Containers) -> case Containers of [] -> key_mode; _ -> Mode end. -file("src/william.gleam", 565). -spec unexpected_token(lexer(), binary(), list(token()), list(container())) -> list(token()). unexpected_token(Lexer, Input, Acc, Containers) -> {Token, Rest} = unexpected(Lexer, Input, <<""/utf8>>), start( Lexer, Rest, emit(Lexer, Token, Acc), after_value_mode, Containers, false ). -file("src/william.gleam", 555). -spec value_token(lexer(), binary(), list(token()), list(container())) -> list(token()). value_token(Lexer, Input, Acc, Containers) -> {Token, Rest} = value(Lexer, Input), start( Lexer, Rest, emit(Lexer, Token, Acc), after_value_mode, Containers, false ). -file("src/william.gleam", 538). -spec key_token(lexer(), binary(), list(token()), mode(), list(container())) -> list(token()). key_token(Lexer, Input, Acc, Mode, Containers) -> {Key, Rest} = bare_key(Input, <<""/utf8>>), case Key of <<""/utf8>> -> unexpected_token(Lexer, Input, Acc, Containers); _ -> Acc@1 = emit(Lexer, {bare_key, Key}, Acc), start(Lexer, Rest, Acc@1, Mode, Containers, false) end. -file("src/william.gleam", 356). -spec start( lexer(), binary(), list(token()), mode(), list(container()), boolean() ) -> list(token()). start(Lexer, Input, Acc, Mode, Containers, At_line_start) -> case Input of <<""/utf8>> -> lists:reverse(Acc); <<"\r\n"/utf8, Rest/binary>> -> Acc@1 = emit(Lexer, {end_of_line, <<"\r\n"/utf8>>}, Acc), Mode@1 = reset_mode_after_newline(Mode, Containers), start(Lexer, Rest, Acc@1, Mode@1, Containers, true); <<"\n"/utf8, Rest@1/binary>> -> Acc@2 = emit(Lexer, {end_of_line, <<"\n"/utf8>>}, Acc), Mode@2 = reset_mode_after_newline(Mode, Containers), start(Lexer, Rest@1, Acc@2, Mode@2, Containers, true); <<"\r"/utf8, Rest@2/binary>> -> Acc@3 = emit(Lexer, {end_of_line, <<"\r"/utf8>>}, Acc), Mode@3 = reset_mode_after_newline(Mode, Containers), start(Lexer, Rest@2, Acc@3, Mode@3, Containers, true); <<" "/utf8, Rest@3/binary>> -> {Token, Rest@4} = whitespace(Rest@3, <<" "/utf8>>), Acc@4 = emit(Lexer, Token, Acc), start(Lexer, Rest@4, Acc@4, Mode, Containers, At_line_start); <<"\t"/utf8, Rest@5/binary>> -> {Token@1, Rest@6} = whitespace(Rest@5, <<"\t"/utf8>>), Acc@5 = emit(Lexer, Token@1, Acc), start(Lexer, Rest@6, Acc@5, Mode, Containers, At_line_start); <<"#"/utf8, Rest@7/binary>> -> {Token@2, Rest@8} = comment(Lexer, Rest@7), Acc@6 = emit(Lexer, Token@2, Acc), start(Lexer, Rest@8, Acc@6, Mode, Containers, At_line_start); <<"[["/utf8, Rest@9/binary>> when At_line_start -> case Containers of [] -> Acc@7 = emit(Lexer, open_array_table, Acc), start(Lexer, Rest@9, Acc@7, table_mode, Containers, false); _ -> Acc@8 = emit(Lexer, open_bracket, Acc), Input@1 = <<"["/utf8, Rest@9/binary>>, Containers@1 = [array_container | Containers], start( Lexer, Input@1, Acc@8, value_mode, Containers@1, false ) end; <<"["/utf8, Rest@10/binary>> when At_line_start -> case Containers of [] -> Acc@9 = emit(Lexer, open_table, Acc), start(Lexer, Rest@10, Acc@9, table_mode, Containers, false); _ -> Acc@10 = emit(Lexer, open_bracket, Acc), Containers@2 = [array_container | Containers], start( Lexer, Rest@10, Acc@10, value_mode, Containers@2, false ) end; <<"]]"/utf8, Rest@11/binary>> -> case Mode of table_mode -> Acc@11 = emit(Lexer, close_array_table, Acc), start( Lexer, Rest@11, Acc@11, after_value_mode, Containers, false ); _ -> Acc@12 = emit(Lexer, close_bracket, Acc), Acc@13 = emit(Lexer, close_bracket, Acc@12), Containers@3 = close_array(Containers), start( Lexer, Rest@11, Acc@13, after_value_mode, Containers@3, false ) end; <<"]"/utf8, Rest@12/binary>> -> case Mode of table_mode -> Acc@14 = emit(Lexer, close_table, Acc), start( Lexer, Rest@12, Acc@14, after_value_mode, Containers, false ); _ -> Acc@15 = emit(Lexer, close_bracket, Acc), Containers@4 = close_array(Containers), start( Lexer, Rest@12, Acc@15, after_value_mode, Containers@4, false ) end; <<"["/utf8, Rest@13/binary>> -> Acc@16 = emit(Lexer, open_bracket, Acc), start( Lexer, Rest@13, Acc@16, value_mode, [array_container | Containers], false ); <<"{"/utf8, Rest@14/binary>> -> Acc@17 = emit(Lexer, open_brace, Acc), Containers@5 = [inline_table_container | Containers], start(Lexer, Rest@14, Acc@17, key_mode, Containers@5, false); <<"}"/utf8, Rest@15/binary>> -> Acc@18 = emit(Lexer, close_brace, Acc), Containers@6 = close_inline_table(Containers), start(Lexer, Rest@15, Acc@18, after_value_mode, Containers@6, false); <<","/utf8, Rest@16/binary>> -> Acc@19 = emit(Lexer, comma, Acc), start( Lexer, Rest@16, Acc@19, mode_after_comma(Containers), Containers, false ); <<"="/utf8, Rest@17/binary>> -> Acc@20 = emit(Lexer, equal, Acc), start(Lexer, Rest@17, Acc@20, value_mode, Containers, false); <<"."/utf8, Rest@18/binary>> -> case Mode of key_mode -> Acc@21 = emit(Lexer, dot, Acc), start(Lexer, Rest@18, Acc@21, Mode, Containers, false); table_mode -> Acc@21 = emit(Lexer, dot, Acc), start(Lexer, Rest@18, Acc@21, Mode, Containers, false); value_mode -> value_token(Lexer, Input, Acc, Containers); after_value_mode -> unexpected_token(Lexer, Input, Acc, Containers) end; <<"\"\"\""/utf8, Rest@19/binary>> -> {Token@3, Rest@20} = multiline_basic_string( Lexer, Rest@19, <<""/utf8>> ), Mode@4 = mode_after_string(Mode), start( Lexer, Rest@20, emit(Lexer, Token@3, Acc), Mode@4, Containers, false ); <<"\""/utf8, Rest@21/binary>> -> {Token@4, Rest@22} = basic_string(Lexer, Rest@21, <<""/utf8>>), Mode@5 = mode_after_string(Mode), start( Lexer, Rest@22, emit(Lexer, Token@4, Acc), Mode@5, Containers, false ); <<"'''"/utf8, Rest@23/binary>> -> {Token@5, Rest@24} = multiline_literal_string( Lexer, Rest@23, <<""/utf8>> ), Mode@6 = mode_after_string(Mode), start( Lexer, Rest@24, emit(Lexer, Token@5, Acc), Mode@6, Containers, false ); <<"'"/utf8, Rest@25/binary>> -> {Token@6, Rest@26} = literal_string(Lexer, Rest@25, <<""/utf8>>), Mode@7 = mode_after_string(Mode), start( Lexer, Rest@26, emit(Lexer, Token@6, Acc), Mode@7, Containers, false ); _ -> case Mode of key_mode -> key_token(Lexer, Input, Acc, Mode, Containers); table_mode -> key_token(Lexer, Input, Acc, Mode, Containers); value_mode -> value_token(Lexer, Input, Acc, Containers); after_value_mode -> unexpected_token(Lexer, Input, Acc, Containers) end end. -file("src/william.gleam", 352). ?DOC(" Parse TOML source code into a list of lexer tokens.\n"). -spec tokenise(lexer(), binary()) -> list(token()). tokenise(Lexer, Input) -> start(Lexer, Input, [], key_mode, [], true). -file("src/william.gleam", 1313). -spec string_delimiter(string_delimiter()) -> binary(). string_delimiter(Delimiter) -> case Delimiter of basic_string -> <<"\""/utf8>>; literal_string -> <<"'"/utf8>>; multiline_basic_string -> <<"\"\"\""/utf8>>; multiline_literal_string -> <<"'''"/utf8>> end. -file("src/william.gleam", 158). -spec highlight_normal_token(token()) -> highlight_token(). highlight_normal_token(Token) -> case Token of {bare_key, Name} -> {highlight_key, Name}; {boolean, Value} -> {highlight_literal, Value}; close_array_table -> {highlight_punctuation, <<"]]"/utf8>>}; close_brace -> {highlight_punctuation, <<"}"/utf8>>}; close_bracket -> {highlight_punctuation, <<"]"/utf8>>}; close_table -> {highlight_punctuation, <<"]"/utf8>>}; comma -> {highlight_punctuation, <<","/utf8>>}; {comment, Str} -> {highlight_comment, Str}; {date_time, Value@1} -> {highlight_date_time, Value@1}; dot -> {highlight_operator, <<"."/utf8>>}; {end_of_line, Str@1} -> {highlight_whitespace, Str@1}; equal -> {highlight_operator, <<"="/utf8>>}; {float, Value@2} -> {highlight_number, Value@2}; {integer, _, Value@3} -> {highlight_number, Value@3}; {invalid_number, Str@2} -> {highlight_error, Str@2}; open_array_table -> {highlight_punctuation, <<"[["/utf8>>}; open_brace -> {highlight_punctuation, <<"{"/utf8>>}; open_bracket -> {highlight_punctuation, <<"["/utf8>>}; open_table -> {highlight_punctuation, <<"["/utf8>>}; {string, Delimiter, Value@4} -> {highlight_string, <<<<(string_delimiter(Delimiter))/binary, Value@4/binary>>/binary, (string_delimiter(Delimiter))/binary>>}; {unexpected, Str@3} -> {highlight_error, Str@3}; {unterminated_string, Delimiter@1, Value@5} -> {highlight_error, <<(string_delimiter(Delimiter@1))/binary, Value@5/binary>>}; {whitespace, Str@4} -> {highlight_whitespace, Str@4} end. -file("src/william.gleam", 138). -spec highlight_token(token(), highlight_context()) -> {highlight_token(), highlight_context()}. highlight_token(Token, Context) -> case {Context, Token} of {_, open_table} -> {{highlight_punctuation, <<"["/utf8>>}, table_header}; {_, open_array_table} -> {{highlight_punctuation, <<"[["/utf8>>}, table_header}; {table_header, close_table} -> {{highlight_punctuation, <<"]"/utf8>>}, normal}; {table_header, close_array_table} -> {{highlight_punctuation, <<"]]"/utf8>>}, normal}; {table_header, {bare_key, Name}} -> {{highlight_table, Name}, table_header}; {table_header, {string, Delimiter, Value}} -> {{highlight_table, <<<<(string_delimiter(Delimiter))/binary, Value/binary>>/binary, (string_delimiter(Delimiter))/binary>>}, table_header}; {_, _} -> {highlight_normal_token(Token), Context} end. -file("src/william.gleam", 42). -spec highlight_loop( list(token()), highlight_context(), list(highlight_token()) ) -> list(highlight_token()). highlight_loop(Tokens, Context, Acc) -> case Tokens of [] -> Acc; [Token | Tokens@1] -> {Highlight, Context@1} = highlight_token(Token, Context), highlight_loop(Tokens@1, Context@1, [Highlight | Acc]) end. -file("src/william.gleam", 36). ?DOC(" Convert a list of lexer tokens into a list of `HighlightToken`.\n"). -spec to_highlight(list(token())) -> list(highlight_token()). to_highlight(Tokens) -> Tokens@1 = highlight_loop(Tokens, normal, []), lists:reverse(Tokens@1). -file("src/william.gleam", 31). ?DOC( " Parse TOML source code into a list of `HighlightToken` using default\n" " settings.\n" "\n" " The resulting token list can be highlighted by using functions like\n" " `to_ansi`, `to_html`, or by pattern matching on it yourself.\n" ). -spec highlight(binary()) -> list(highlight_token()). highlight(Source) -> to_highlight(tokenise(new(), Source)). -file("src/william.gleam", 58). ?DOC( " Format a list of `HighlightToken` into ANSI highlighting for display in a\n" " terminal.\n" ). -spec to_ansi(list(highlight_token())) -> binary(). to_ansi(Tokens) -> gleam@list:fold( Tokens, <<""/utf8>>, fun(Acc, Token) -> Highlighted = case Token of {highlight_comment, Str} -> gleam_community@ansi:italic(gleam_community@ansi:gray(Str)); {highlight_date_time, Str@1} -> gleam_community@ansi:blue(Str@1); {highlight_error, Str@2} -> gleam_community@ansi:bg_bright_red( gleam_community@ansi:white(Str@2) ); {highlight_key, Str@3} -> gleam_community@ansi:yellow(Str@3); {highlight_literal, Str@4} -> gleam_community@ansi:green(Str@4); {highlight_number, Str@5} -> gleam_community@ansi:green(Str@5); {highlight_operator, Str@6} -> gleam_community@ansi:magenta(Str@6); {highlight_punctuation, Str@7} -> Str@7; {highlight_string, Str@8} -> gleam_community@ansi:green(Str@8); {highlight_table, Str@9} -> gleam_community@ansi:cyan(Str@9); {highlight_whitespace, Str@10} -> Str@10 end, <> end ). -file("src/william.gleam", 190). -spec span(binary(), binary()) -> binary(). span(Class, Text) -> <<<<<<<<">/binary, "\">"/utf8>>/binary, (houdini:escape(Text))/binary>>/binary, ""/utf8>>. -file("src/william.gleam", 118). ?DOC( " Format a list of `HighlightToken` as HTML.\n" "\n" " Each non-whitespace token is wrapped inside a `` tag with a class\n" " indicating the type.\n" "\n" " Class names are based on [`contour`](https://hexdocs.pm/contour):\n" "\n" " | Token | CSS class |\n" " | ----------- | -------------- |\n" " | Comment | hl-comment |\n" " | Date/time | hl-function |\n" " | Error | hl-error |\n" " | Key | hl-attribute |\n" " | Literal | hl-literal |\n" " | Number | hl-number |\n" " | Operator | hl-operator |\n" " | Punctuation | hl-punctuation |\n" " | String | hl-string |\n" " | Table name | hl-module |\n" " | Whitespace | no class |\n" "\n" " Place the output within\n" " `
...
` and add styling for\n" " these CSS classes to get highlighting on your website. Here's some CSS you\n" " could use:\n" "\n" " ```css\n" " pre code {\n" " .hl-comment { color: #d4d4d4; font-style: italic }\n" " .hl-function { color: #9ce7ff }\n" " .hl-attribute { color: #ffd596 }\n" " .hl-operator { color: #ffaff3 }\n" " .hl-string { color: #c8ffa7 }\n" " .hl-number { color: #c8ffa7 }\n" " .hl-literal { color: #c8ffa7 }\n" " .hl-module { color: #ffddfa }\n" " .hl-punctuation { color: inherit }\n" " .hl-error { background: red; color: white }\n" " }\n" " ```\n" ). -spec to_html(list(highlight_token())) -> binary(). to_html(Tokens) -> gleam@list:fold( Tokens, <<""/utf8>>, fun(Acc, Token) -> Highlighted = case Token of {highlight_comment, Str} -> span(<<"hl-comment"/utf8>>, Str); {highlight_date_time, Str@1} -> span(<<"hl-function"/utf8>>, Str@1); {highlight_error, Str@2} -> span(<<"hl-error"/utf8>>, Str@2); {highlight_key, Str@3} -> span(<<"hl-attribute"/utf8>>, Str@3); {highlight_literal, Str@4} -> span(<<"hl-literal"/utf8>>, Str@4); {highlight_number, Str@5} -> span(<<"hl-number"/utf8>>, Str@5); {highlight_operator, Str@6} -> span(<<"hl-operator"/utf8>>, Str@6); {highlight_punctuation, Str@7} -> span(<<"hl-punctuation"/utf8>>, Str@7); {highlight_string, Str@8} -> span(<<"hl-string"/utf8>>, Str@8); {highlight_table, Str@9} -> span(<<"hl-module"/utf8>>, Str@9); {highlight_whitespace, Str@10} -> Str@10 end, <> end ). -file("src/william.gleam", 200). -spec token_source(token()) -> binary(). token_source(Token) -> case Token of {bare_key, Name} -> Name; {boolean, Value} -> Value; close_array_table -> <<"]]"/utf8>>; close_brace -> <<"}"/utf8>>; close_bracket -> <<"]"/utf8>>; close_table -> <<"]"/utf8>>; comma -> <<","/utf8>>; {comment, Str} -> Str; {date_time, Value@1} -> Value@1; dot -> <<"."/utf8>>; {end_of_line, Str@1} -> Str@1; equal -> <<"="/utf8>>; {float, Value@2} -> Value@2; {integer, _, Value@3} -> Value@3; {invalid_number, Str@2} -> Str@2; open_array_table -> <<"[["/utf8>>; open_brace -> <<"{"/utf8>>; open_bracket -> <<"["/utf8>>; open_table -> <<"["/utf8>>; {string, Delimiter, Value@4} -> <<<<(string_delimiter(Delimiter))/binary, Value@4/binary>>/binary, (string_delimiter(Delimiter))/binary>>; {unexpected, Str@3} -> Str@3; {unterminated_string, Delimiter@1, Value@5} -> <<(string_delimiter(Delimiter@1))/binary, Value@5/binary>>; {whitespace, Str@4} -> Str@4 end. -file("src/william.gleam", 195). ?DOC(" Convert a list of tokens back into their source representation.\n"). -spec to_source(list(token())) -> binary(). to_source(Tokens) -> gleam@list:fold( Tokens, <<""/utf8>>, fun(Acc, Token) -> <> end ). -file("src/william.gleam", 342). ?DOC(" Skip whitespace and end-of-line tokens in the resulting token list.\n"). -spec ignore_whitespace(lexer()) -> lexer(). ignore_whitespace(Lexer) -> {lexer, true, erlang:element(3, Lexer), erlang:element(4, Lexer), erlang:element(5, Lexer), erlang:element(6, Lexer), erlang:element(7, Lexer), erlang:element(8, Lexer), erlang:element(9, Lexer), erlang:element(10, Lexer)}. -file("src/william.gleam", 347). ?DOC(" Skip comment tokens in the resulting token list.\n"). -spec ignore_comments(lexer()) -> lexer(). ignore_comments(Lexer) -> {lexer, erlang:element(2, Lexer), true, erlang:element(4, Lexer), erlang:element(5, Lexer), erlang:element(6, Lexer), erlang:element(7, Lexer), erlang:element(8, Lexer), erlang:element(9, Lexer), erlang:element(10, Lexer)}.