-module(sqlode@internal@lexer). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/sqlode/internal/lexer.gleam"). -export([tokenize/2, tokens_to_string/2]). -export_type([token_render_options/0, 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 token_render_options() :: {token_render_options, boolean(), boolean(), gleam@option:option(sqlode@internal@model:engine())}. -type token() :: {keyword, binary()} | {ident, binary()} | {quoted_ident, binary()} | {string_lit, binary()} | {number_lit, binary()} | {placeholder, binary()} | {operator, binary()} | l_paren | r_paren | comma | semicolon | dot | star. -file("src/sqlode/internal/lexer.gleam", 286). ?DOC(false). -spec skip_line_comment(list(binary())) -> list(binary()). skip_line_comment(Input) -> case Input of [] -> []; [<<"\n"/utf8>> | Rest] -> Rest; [_ | Rest@1] -> skip_line_comment(Rest@1) end. -file("src/sqlode/internal/lexer.gleam", 298). ?DOC(false). -spec skip_block_comment_loop(list(binary()), integer()) -> list(binary()). skip_block_comment_loop(Input, Depth) -> case Input of [] -> []; _ -> case Depth =< 0 of true -> Input; false -> case Input of [<<"*"/utf8>>, <<"/"/utf8>> | Rest] -> skip_block_comment_loop(Rest, Depth - 1); [<<"/"/utf8>>, <<"*"/utf8>> | Rest@1] -> skip_block_comment_loop(Rest@1, Depth + 1); [_ | Rest@2] -> skip_block_comment_loop(Rest@2, Depth); [] -> [] end end end. -file("src/sqlode/internal/lexer.gleam", 294). ?DOC(false). -spec skip_block_comment(list(binary())) -> list(binary()). skip_block_comment(Input) -> skip_block_comment_loop(Input, 1). -file("src/sqlode/internal/lexer.gleam", 317). ?DOC(false). -spec read_single_quoted_string(list(binary()), list(binary())) -> {binary(), list(binary())}. read_single_quoted_string(Input, Acc) -> case Input of [] -> {begin _pipe = Acc, _pipe@1 = lists:reverse(_pipe), erlang:list_to_binary(_pipe@1) end, []}; [<<"'"/utf8>>, <<"'"/utf8>> | Rest] -> read_single_quoted_string(Rest, [<<"'"/utf8>> | Acc]); [<<"'"/utf8>> | Rest@1] -> {begin _pipe@2 = Acc, _pipe@3 = lists:reverse(_pipe@2), erlang:list_to_binary(_pipe@3) end, Rest@1}; [G | Rest@2] -> read_single_quoted_string(Rest@2, [G | Acc]) end. -file("src/sqlode/internal/lexer.gleam", 363). ?DOC(false). -spec read_dollar_tag_chars_lex(list(binary()), list(binary())) -> {ok, {binary(), list(binary())}} | {error, nil}. read_dollar_tag_chars_lex(Chars, Acc) -> case Chars of [] -> {error, nil}; [<<"$"/utf8>> | Rest] -> Tag = begin _pipe = Acc, _pipe@1 = lists:reverse(_pipe), erlang:list_to_binary(_pipe@1) end, {ok, {Tag, Rest}}; [C | Rest@1] -> case sqlode@internal@char_utils:is_alnum_or_underscore(C) of true -> read_dollar_tag_chars_lex(Rest@1, [C | Acc]); false -> {error, nil} end end. -file("src/sqlode/internal/lexer.gleam", 349). ?DOC(false). -spec try_dollar_tag_lex(list(binary())) -> {ok, {binary(), list(binary())}} | {error, nil}. try_dollar_tag_lex(Chars) -> case Chars of [<<"$"/utf8>> | Rest] -> {ok, {<<""/utf8>>, Rest}}; [C | Rest@1] -> case sqlode@internal@char_utils:is_alpha_or_underscore(C) of true -> read_dollar_tag_chars_lex(Rest@1, [C]); false -> {error, nil} end; [] -> {error, nil} end. -file("src/sqlode/internal/lexer.gleam", 389). ?DOC(false). -spec match_tag_then_dollar_lex(list(binary()), list(binary())) -> {ok, list(binary())} | {error, nil}. match_tag_then_dollar_lex(Chars, Tag_chars) -> case Tag_chars of [] -> case Chars of [<<"$"/utf8>> | Rest] -> {ok, Rest}; _ -> {error, nil} end; [Expected | Tag_rest] -> case Chars of [Actual | Chars_rest] when Actual =:= Expected -> match_tag_then_dollar_lex(Chars_rest, Tag_rest); _ -> {error, nil} end end. -file("src/sqlode/internal/lexer.gleam", 381). ?DOC(false). -spec try_match_closing_dollar_tag_lex(list(binary()), binary()) -> {ok, list(binary())} | {error, nil}. try_match_closing_dollar_tag_lex(Chars, Tag) -> Tag_chars = gleam@string:to_graphemes(Tag), match_tag_then_dollar_lex(Chars, Tag_chars). -file("src/sqlode/internal/lexer.gleam", 333). ?DOC(false). -spec read_dollar_quoted_string(list(binary()), binary(), list(binary())) -> {binary(), list(binary())}. read_dollar_quoted_string(Input, Tag, Acc) -> case Input of [] -> {begin _pipe = Acc, _pipe@1 = lists:reverse(_pipe), erlang:list_to_binary(_pipe@1) end, []}; [<<"$"/utf8>> | Rest] -> case try_match_closing_dollar_tag_lex(Rest, Tag) of {ok, Remaining} -> {begin _pipe@2 = Acc, _pipe@3 = lists:reverse(_pipe@2), erlang:list_to_binary(_pipe@3) end, Remaining}; {error, _} -> read_dollar_quoted_string(Rest, Tag, [<<"$"/utf8>> | Acc]) end; [G | Rest@1] -> read_dollar_quoted_string(Rest@1, Tag, [G | Acc]) end. -file("src/sqlode/internal/lexer.gleam", 408). ?DOC(false). -spec read_quoted(list(binary()), binary(), list(binary())) -> {binary(), list(binary())}. read_quoted(Input, Closer, Acc) -> case Input of [] -> {begin _pipe = Acc, _pipe@1 = lists:reverse(_pipe), erlang:list_to_binary(_pipe@1) end, []}; [G, G2 | Rest] when ((G =:= Closer) andalso (G2 =:= Closer)) andalso (Closer =/= <<"]"/utf8>>) -> read_quoted(Rest, Closer, [G | Acc]); [G@1 | Rest@1] -> case G@1 =:= Closer of true -> {begin _pipe@2 = Acc, _pipe@3 = lists:reverse(_pipe@2), erlang:list_to_binary(_pipe@3) end, Rest@1}; false -> read_quoted(Rest@1, Closer, [G@1 | Acc]) end end. -file("src/sqlode/internal/lexer.gleam", 431). ?DOC(false). -spec detect_string_literal_prefix(binary(), list(binary())) -> gleam@option:option({list(binary()), binary()}). detect_string_literal_prefix(G, Rest) -> case {G, Rest} of {P, [<<"'"/utf8>> | After]} when (P =:= <<"E"/utf8>>) orelse (P =:= <<"e"/utf8>>) -> {some, {After, <<"escape"/utf8>>}}; {P@1, [<<"'"/utf8>> | After@1]} when (P@1 =:= <<"B"/utf8>>) orelse (P@1 =:= <<"b"/utf8>>) -> {some, {After@1, <<"bit"/utf8>>}}; {P@2, [<<"'"/utf8>> | After@2]} when (P@2 =:= <<"X"/utf8>>) orelse (P@2 =:= <<"x"/utf8>>) -> {some, {After@2, <<"hex"/utf8>>}}; {P@3, [<<"'"/utf8>> | After@3]} when (P@3 =:= <<"N"/utf8>>) orelse (P@3 =:= <<"n"/utf8>>) -> {some, {After@3, <<"national"/utf8>>}}; {P@4, [<<"&"/utf8>>, <<"'"/utf8>> | After@4]} when (P@4 =:= <<"U"/utf8>>) orelse (P@4 =:= <<"u"/utf8>>) -> {some, {After@4, <<"unicode"/utf8>>}}; {_, _} -> none end. -file("src/sqlode/internal/lexer.gleam", 461). ?DOC(false). -spec is_hex_digit(binary()) -> boolean(). is_hex_digit(G) -> case G 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/sqlode/internal/lexer.gleam", 447). ?DOC(false). -spec read_hex_digits(list(binary()), list(binary())) -> {binary(), list(binary())}. read_hex_digits(Input, Acc) -> case Input of [G | Rest] -> case is_hex_digit(G) of true -> read_hex_digits(Rest, [G | Acc]); false -> {begin _pipe = Acc, _pipe@1 = lists:reverse(_pipe), erlang:list_to_binary(_pipe@1) end, Input} end; [] -> {begin _pipe@2 = Acc, _pipe@3 = lists:reverse(_pipe@2), erlang:list_to_binary(_pipe@3) end, []} end. -file("src/sqlode/internal/lexer.gleam", 472). ?DOC(false). -spec read_word(list(binary()), list(binary())) -> {binary(), list(binary())}. read_word(Input, Acc) -> case Input of [G | Rest] -> case sqlode@internal@char_utils:is_alnum_or_underscore(G) of true -> read_word(Rest, [G | Acc]); false -> {begin _pipe = Acc, _pipe@1 = lists:reverse(_pipe), erlang:list_to_binary(_pipe@1) end, Input} end; [] -> {begin _pipe@2 = Acc, _pipe@3 = lists:reverse(_pipe@2), erlang:list_to_binary(_pipe@3) end, []} end. -file("src/sqlode/internal/lexer.gleam", 495). ?DOC(false). -spec is_sqlode_marker(binary()) -> boolean(). is_sqlode_marker(Word) -> (gleam_stdlib:string_starts_with(Word, <<"__sqlode_param_"/utf8>>) orelse gleam_stdlib:string_starts_with( Word, <<"__sqlode_slice_"/utf8>> )) andalso gleam_stdlib:string_ends_with(Word, <<"__"/utf8>>). -file("src/sqlode/internal/lexer.gleam", 503). ?DOC(false). -spec is_sql_keyword(binary()) -> boolean(). is_sql_keyword(Word) -> case Word of <<"select"/utf8>> -> true; <<"from"/utf8>> -> true; <<"where"/utf8>> -> true; <<"and"/utf8>> -> true; <<"or"/utf8>> -> true; <<"not"/utf8>> -> true; <<"in"/utf8>> -> true; <<"is"/utf8>> -> true; <<"null"/utf8>> -> true; <<"as"/utf8>> -> true; <<"on"/utf8>> -> true; <<"join"/utf8>> -> true; <<"inner"/utf8>> -> true; <<"left"/utf8>> -> true; <<"right"/utf8>> -> true; <<"full"/utf8>> -> true; <<"outer"/utf8>> -> true; <<"cross"/utf8>> -> true; <<"natural"/utf8>> -> true; <<"using"/utf8>> -> true; <<"order"/utf8>> -> true; <<"by"/utf8>> -> true; <<"group"/utf8>> -> true; <<"rollup"/utf8>> -> true; <<"cube"/utf8>> -> true; <<"sets"/utf8>> -> true; <<"having"/utf8>> -> true; <<"limit"/utf8>> -> true; <<"offset"/utf8>> -> true; <<"union"/utf8>> -> true; <<"intersect"/utf8>> -> true; <<"except"/utf8>> -> true; <<"all"/utf8>> -> true; <<"distinct"/utf8>> -> true; <<"insert"/utf8>> -> true; <<"into"/utf8>> -> true; <<"values"/utf8>> -> true; <<"update"/utf8>> -> true; <<"set"/utf8>> -> true; <<"delete"/utf8>> -> true; <<"create"/utf8>> -> true; <<"table"/utf8>> -> true; <<"view"/utf8>> -> true; <<"index"/utf8>> -> true; <<"alter"/utf8>> -> true; <<"add"/utf8>> -> true; <<"column"/utf8>> -> true; <<"drop"/utf8>> -> true; <<"if"/utf8>> -> true; <<"exists"/utf8>> -> true; <<"primary"/utf8>> -> true; <<"key"/utf8>> -> true; <<"foreign"/utf8>> -> true; <<"references"/utf8>> -> true; <<"unique"/utf8>> -> true; <<"check"/utf8>> -> true; <<"default"/utf8>> -> true; <<"constraint"/utf8>> -> true; <<"cascade"/utf8>> -> true; <<"restrict"/utf8>> -> true; <<"no"/utf8>> -> true; <<"action"/utf8>> -> true; <<"autoincrement"/utf8>> -> true; <<"serial"/utf8>> -> true; <<"bigserial"/utf8>> -> true; <<"smallserial"/utf8>> -> true; <<"returning"/utf8>> -> true; <<"case"/utf8>> -> true; <<"when"/utf8>> -> true; <<"then"/utf8>> -> true; <<"else"/utf8>> -> true; <<"end"/utf8>> -> true; <<"cast"/utf8>> -> true; <<"between"/utf8>> -> true; <<"like"/utf8>> -> true; <<"ilike"/utf8>> -> true; <<"with"/utf8>> -> true; <<"recursive"/utf8>> -> true; <<"temporary"/utf8>> -> true; <<"temp"/utf8>> -> true; <<"unlogged"/utf8>> -> true; <<"true"/utf8>> -> true; <<"false"/utf8>> -> true; <<"asc"/utf8>> -> true; <<"desc"/utf8>> -> true; <<"nulls"/utf8>> -> true; <<"first"/utf8>> -> true; <<"last"/utf8>> -> true; <<"over"/utf8>> -> true; <<"partition"/utf8>> -> true; <<"window"/utf8>> -> true; <<"row"/utf8>> -> true; <<"rows"/utf8>> -> true; <<"range"/utf8>> -> true; <<"preceding"/utf8>> -> true; <<"following"/utf8>> -> true; <<"current"/utf8>> -> true; <<"unbounded"/utf8>> -> true; <<"enum"/utf8>> -> true; <<"replace"/utf8>> -> true; <<"conflict"/utf8>> -> true; <<"do"/utf8>> -> true; <<"nothing"/utf8>> -> true; <<"begin"/utf8>> -> true; <<"commit"/utf8>> -> true; <<"rollback"/utf8>> -> true; <<"transaction"/utf8>> -> true; <<"for"/utf8>> -> true; <<"each"/utf8>> -> true; <<"trigger"/utf8>> -> true; <<"execute"/utf8>> -> true; <<"procedure"/utf8>> -> true; <<"function"/utf8>> -> true; <<"returns"/utf8>> -> true; <<"language"/utf8>> -> true; <<"volatile"/utf8>> -> true; <<"stable"/utf8>> -> true; <<"immutable"/utf8>> -> true; <<"security"/utf8>> -> true; <<"definer"/utf8>> -> true; <<"invoker"/utf8>> -> true; <<"grant"/utf8>> -> true; <<"revoke"/utf8>> -> true; <<"to"/utf8>> -> true; <<"schema"/utf8>> -> true; <<"database"/utf8>> -> true; <<"extension"/utf8>> -> true; <<"only"/utf8>> -> true; <<"lateral"/utf8>> -> true; <<"any"/utf8>> -> true; <<"some"/utf8>> -> true; <<"array"/utf8>> -> true; <<"of"/utf8>> -> true; <<"collate"/utf8>> -> true; <<"ignore"/utf8>> -> true; <<"abort"/utf8>> -> true; <<"fail"/utf8>> -> true; _ -> false end. -file("src/sqlode/internal/lexer.gleam", 483). ?DOC(false). -spec classify_word(binary()) -> token(). classify_word(Word) -> Lowered = string:lowercase(Word), case is_sqlode_marker(Word) of true -> {placeholder, Word}; false -> case is_sql_keyword(Lowered) of true -> {keyword, Lowered}; false -> {ident, Word} end end. -file("src/sqlode/internal/lexer.gleam", 666). ?DOC(false). -spec read_number(list(binary()), list(binary())) -> {binary(), list(binary())}. read_number(Input, Acc) -> case Input of [G | Rest] -> case sqlode@internal@char_utils:is_digit(G) orelse (G =:= <<"."/utf8>>) of true -> read_number(Rest, [G | Acc]); false -> case (G =:= <<"e"/utf8>>) orelse (G =:= <<"E"/utf8>>) of true -> case Rest of [<<"+"/utf8>> | _] -> read_number( gleam@list:drop(Rest, 1), [case Rest of [S | _] -> S; _ -> <<""/utf8>> end, G | Acc] ); [<<"-"/utf8>> | _] -> read_number( gleam@list:drop(Rest, 1), [case Rest of [S | _] -> S; _ -> <<""/utf8>> end, G | Acc] ); _ -> read_number(Rest, [G | Acc]) end; false -> {begin _pipe = Acc, _pipe@1 = lists:reverse(_pipe), erlang:list_to_binary(_pipe@1) end, Input} end end; [] -> {begin _pipe@2 = Acc, _pipe@3 = lists:reverse(_pipe@2), erlang:list_to_binary(_pipe@3) end, []} end. -file("src/sqlode/internal/lexer.gleam", 698). ?DOC(false). -spec read_placeholder_or_ident(list(binary())) -> {token(), list(binary())}. read_placeholder_or_ident(Input) -> case Input of [<<"$"/utf8>> | Rest] -> {Word, Remaining} = read_word(Rest, [<<"$"/utf8>>]), {{placeholder, Word}, Remaining}; _ -> {{operator, <<"$"/utf8>>}, Input} end. -file("src/sqlode/internal/lexer.gleam", 708). ?DOC(false). -spec read_placeholder_question(list(binary()), list(binary())) -> {binary(), list(binary())}. read_placeholder_question(Input, Acc) -> case Input of [G | Rest] -> case sqlode@internal@char_utils:is_digit(G) of true -> read_placeholder_question(Rest, [G | Acc]); false -> {begin _pipe = Acc, _pipe@1 = lists:reverse(_pipe), erlang:list_to_binary(_pipe@1) end, Input} end; [] -> {begin _pipe@2 = Acc, _pipe@3 = lists:reverse(_pipe@2), erlang:list_to_binary(_pipe@3) end, []} end. -file("src/sqlode/internal/lexer.gleam", 724). ?DOC(false). -spec read_operator(list(binary())) -> {binary(), list(binary())}. read_operator(Input) -> case Input of [<<"<"/utf8>>, <<">"/utf8>> | Rest] -> {<<"<>"/utf8>>, Rest}; [<<"<"/utf8>>, <<"="/utf8>> | Rest@1] -> {<<"<="/utf8>>, Rest@1}; [<<"<"/utf8>>, <<"@"/utf8>> | Rest@2] -> {<<"<@"/utf8>>, Rest@2}; [<<">"/utf8>>, <<"="/utf8>> | Rest@3] -> {<<">="/utf8>>, Rest@3}; [<<"!"/utf8>>, <<"="/utf8>> | Rest@4] -> {<<"!="/utf8>>, Rest@4}; [<<"|"/utf8>>, <<"|"/utf8>> | Rest@5] -> {<<"||"/utf8>>, Rest@5}; [<<"&"/utf8>>, <<"&"/utf8>> | Rest@6] -> {<<"&&"/utf8>>, Rest@6}; [<<"-"/utf8>>, <<">"/utf8>>, <<">"/utf8>> | Rest@7] -> {<<"->>"/utf8>>, Rest@7}; [<<"-"/utf8>>, <<">"/utf8>> | Rest@8] -> {<<"->"/utf8>>, Rest@8}; [G | Rest@9] -> {G, Rest@9}; [] -> {<<""/utf8>>, []} end. -file("src/sqlode/internal/lexer.gleam", 54). ?DOC(false). -spec do_tokenize(list(binary()), sqlode@internal@model:engine(), list(token())) -> list(token()). do_tokenize(Input, Engine, Acc) -> case Input of [] -> Acc; [G | Rest] -> case G of <<" "/utf8>> -> do_tokenize(Rest, Engine, Acc); <<"\t"/utf8>> -> do_tokenize(Rest, Engine, Acc); <<"\n"/utf8>> -> do_tokenize(Rest, Engine, Acc); <<"\r"/utf8>> -> do_tokenize(Rest, Engine, Acc); <<"-"/utf8>> -> case Rest of [<<"-"/utf8>> | After_dash] -> Remaining = skip_line_comment(After_dash), do_tokenize(Remaining, Engine, Acc); _ -> {Op, Remaining@1} = read_operator([G | Rest]), do_tokenize( Remaining@1, Engine, [{operator, Op} | Acc] ) end; <<"/"/utf8>> -> case Rest of [<<"*"/utf8>> | After_star] -> Remaining@2 = skip_block_comment(After_star), do_tokenize(Remaining@2, Engine, Acc); _ -> do_tokenize( Rest, Engine, [{operator, <<"/"/utf8>>} | Acc] ) end; <<"#"/utf8>> -> case Engine of my_s_q_l -> Remaining@3 = skip_line_comment(Rest), do_tokenize(Remaining@3, Engine, Acc); _ -> case Rest of [<<">"/utf8>>, <<">"/utf8>> | After] -> do_tokenize( After, Engine, [{operator, <<"#>>"/utf8>>} | Acc] ); [<<">"/utf8>> | After@1] -> do_tokenize( After@1, Engine, [{operator, <<"#>"/utf8>>} | Acc] ); _ -> {Op@1, Remaining@4} = read_operator( [G | Rest] ), do_tokenize( Remaining@4, Engine, [{operator, Op@1} | Acc] ) end end; <<"'"/utf8>> -> {Content, Remaining@5} = read_single_quoted_string(Rest, []), do_tokenize( Remaining@5, Engine, [{string_lit, Content} | Acc] ); <<"$"/utf8>> -> case Engine of postgre_s_q_l -> case try_dollar_tag_lex(Rest) of {ok, {Tag, After_tag}} -> {Content@1, Remaining@6} = read_dollar_quoted_string( After_tag, Tag, [] ), do_tokenize( Remaining@6, Engine, [{string_lit, Content@1} | Acc] ); {error, _} -> {Token, Remaining@7} = read_placeholder_or_ident( [<<"$"/utf8>> | Rest] ), do_tokenize( Remaining@7, Engine, [Token | Acc] ) end; _ -> {Token@1, Remaining@8} = read_placeholder_or_ident( [<<"$"/utf8>> | Rest] ), do_tokenize(Remaining@8, Engine, [Token@1 | Acc]) end; <<"\""/utf8>> -> case Engine of my_s_q_l -> {Content@2, Remaining@9} = read_quoted( Rest, <<"\""/utf8>>, [] ), do_tokenize( Remaining@9, Engine, [{string_lit, Content@2} | Acc] ); _ -> {Content@3, Remaining@10} = read_quoted( Rest, <<"\""/utf8>>, [] ), do_tokenize( Remaining@10, Engine, [{quoted_ident, Content@3} | Acc] ) end; <<"`"/utf8>> -> {Content@4, Remaining@11} = read_quoted( Rest, <<"`"/utf8>>, [] ), do_tokenize( Remaining@11, Engine, [{quoted_ident, Content@4} | Acc] ); <<"["/utf8>> -> case Engine of s_q_lite -> {Content@5, Remaining@12} = read_quoted( Rest, <<"]"/utf8>>, [] ), do_tokenize( Remaining@12, Engine, [{quoted_ident, Content@5} | Acc] ); _ -> {Op@2, Remaining@13} = read_operator([G | Rest]), do_tokenize( Remaining@13, Engine, [{operator, Op@2} | Acc] ) end; <<"("/utf8>> -> do_tokenize(Rest, Engine, [l_paren | Acc]); <<")"/utf8>> -> do_tokenize(Rest, Engine, [r_paren | Acc]); <<","/utf8>> -> do_tokenize(Rest, Engine, [comma | Acc]); <<";"/utf8>> -> do_tokenize(Rest, Engine, [semicolon | Acc]); <<"*"/utf8>> -> do_tokenize(Rest, Engine, [star | Acc]); <<"."/utf8>> -> case Rest of [Next | _] -> case sqlode@internal@char_utils:is_digit(Next) of true -> {Num, Remaining@14} = read_number(Rest, [G]), do_tokenize( Remaining@14, Engine, [{number_lit, Num} | Acc] ); false -> do_tokenize(Rest, Engine, [dot | Acc]) end; _ -> do_tokenize(Rest, Engine, [dot | Acc]) end; <<"?"/utf8>> -> case Rest of [<<"|"/utf8>> | After@2] -> do_tokenize( After@2, Engine, [{operator, <<"?|"/utf8>>} | Acc] ); [<<"&"/utf8>> | After@3] -> do_tokenize( After@3, Engine, [{operator, <<"?&"/utf8>>} | Acc] ); _ -> {Ph, Remaining@15} = read_placeholder_question( Rest, [G] ), do_tokenize( Remaining@15, Engine, [{placeholder, Ph} | Acc] ) end; <<":"/utf8>> -> case Rest of [<<":"/utf8>> | After_colon] -> do_tokenize( After_colon, Engine, [{operator, <<"::"/utf8>>} | Acc] ); [Next@1 | _] -> case sqlode@internal@char_utils:is_alpha_or_underscore( Next@1 ) of true -> {Ph@1, Remaining@16} = read_word(Rest, [G]), do_tokenize( Remaining@16, Engine, [{placeholder, Ph@1} | Acc] ); false -> do_tokenize( Rest, Engine, [{operator, <<":"/utf8>>} | Acc] ) end; _ -> do_tokenize( Rest, Engine, [{operator, <<":"/utf8>>} | Acc] ) end; <<"@"/utf8>> -> case Rest of [<<">"/utf8>> | After@4] -> do_tokenize( After@4, Engine, [{operator, <<"@>"/utf8>>} | Acc] ); [Next@2 | _] -> case sqlode@internal@char_utils:is_alpha_or_underscore( Next@2 ) of true -> {Ph@2, Remaining@17} = read_word(Rest, [G]), do_tokenize( Remaining@17, Engine, [{placeholder, Ph@2} | Acc] ); false -> do_tokenize( Rest, Engine, [{operator, <<"@"/utf8>>} | Acc] ) end; _ -> do_tokenize( Rest, Engine, [{operator, <<"@"/utf8>>} | Acc] ) end; _ -> case sqlode@internal@char_utils:is_digit(G) of true -> case {G, Rest} of {<<"0"/utf8>>, [X | Hex_rest]} when (X =:= <<"x"/utf8>>) orelse (X =:= <<"X"/utf8>>) -> {Digits, Remaining@18} = read_hex_digits( Hex_rest, [] ), do_tokenize( Remaining@18, Engine, [{number_lit, <<<<"0"/utf8, X/binary>>/binary, Digits/binary>>} | Acc] ); {_, _} -> {Num@1, Remaining@19} = read_number( Rest, [G] ), do_tokenize( Remaining@19, Engine, [{number_lit, Num@1} | Acc] ) end; false -> case sqlode@internal@char_utils:is_alpha_or_underscore( G ) of true -> case detect_string_literal_prefix(G, Rest) of {some, {After_prefix, _}} -> {Content@6, Remaining@20} = read_single_quoted_string( After_prefix, [] ), do_tokenize( Remaining@20, Engine, [{string_lit, Content@6} | Acc] ); none -> {Word, Remaining@21} = read_word( Rest, [G] ), Token@2 = classify_word(Word), do_tokenize( Remaining@21, Engine, [Token@2 | Acc] ) end; false -> {Op@3, Remaining@22} = read_operator( [G | Rest] ), do_tokenize( Remaining@22, Engine, [{operator, Op@3} | Acc] ) end end end end. -file("src/sqlode/internal/lexer.gleam", 48). ?DOC(false). -spec tokenize(binary(), sqlode@internal@model:engine()) -> list(token()). tokenize(Sql, Engine) -> Graphemes = gleam@string:to_graphemes(Sql), _pipe = do_tokenize(Graphemes, Engine, []), lists:reverse(_pipe). -file("src/sqlode/internal/lexer.gleam", 777). ?DOC(false). -spec token_to_string(token(), token_render_options()) -> binary(). token_to_string(Token, Options) -> case Token of {keyword, K} -> case erlang:element(2, Options) of true -> string:uppercase(K); false -> K end; {ident, Name} -> Name; {quoted_ident, Name@1} -> case erlang:element(3, Options) of true -> case erlang:element(4, Options) of {some, my_s_q_l} -> <<<<"`"/utf8, Name@1/binary>>/binary, "`"/utf8>>; _ -> <<<<"\""/utf8, Name@1/binary>>/binary, "\""/utf8>> end; false -> Name@1 end; {string_lit, Value} -> case erlang:element(3, Options) of true -> <<<<"'"/utf8, (gleam@string:replace( Value, <<"'"/utf8>>, <<"''"/utf8>> ))/binary>>/binary, "'"/utf8>>; false -> <<<<"'"/utf8, Value/binary>>/binary, "'"/utf8>> end; {number_lit, N} -> N; {placeholder, P} -> P; {operator, Op} -> Op; l_paren -> <<"("/utf8>>; r_paren -> <<")"/utf8>>; comma -> <<","/utf8>>; semicolon -> <<";"/utf8>>; dot -> <<"."/utf8>>; star -> <<"*"/utf8>> end. -file("src/sqlode/internal/lexer.gleam", 752). ?DOC(false). -spec tokens_to_string_loop( list(token()), list(binary()), token_render_options() ) -> list(binary()). tokens_to_string_loop(Tokens, Acc, Options) -> case Tokens of [] -> Acc; [Token | Rest] -> Token_text = token_to_string(Token, Options), With_space = case {Acc, Token} of {_, comma} -> [Token_text | Acc]; {_, semicolon} -> [Token_text | Acc]; {_, l_paren} -> [Token_text | Acc]; {_, r_paren} -> [Token_text | Acc]; {_, dot} -> [Token_text | Acc]; {_, star} -> [Token_text | Acc]; {[<<"("/utf8>> | _], _} -> [Token_text | Acc]; {[<<"."/utf8>> | _], _} -> [Token_text | Acc]; {_, {operator, <<"["/utf8>>}} -> [Token_text | Acc]; {[<<"]"/utf8>> | _], _} -> [Token_text | Acc]; {[<<"["/utf8>> | _], _} -> [Token_text | Acc]; {[], _} -> [Token_text]; {_, _} -> [Token_text, <<" "/utf8>> | Acc] end, tokens_to_string_loop(Rest, With_space, Options) end. -file("src/sqlode/internal/lexer.gleam", 743). ?DOC(false). -spec tokens_to_string(list(token()), token_render_options()) -> binary(). tokens_to_string(Tokens, Options) -> _pipe = tokens_to_string_loop(Tokens, [], Options), _pipe@1 = lists:reverse(_pipe), erlang:list_to_binary(_pipe@1).