-module(glsql@lexer). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/glsql/lexer.gleam"). -export([lex/1]). -file("src/glsql/lexer.gleam", 112). -spec in_range(binary(), binary(), binary()) -> boolean(). in_range(C, Low, High) -> (gleam@string:compare(C, Low) /= lt) andalso (gleam@string:compare(C, High) /= gt). -file("src/glsql/lexer.gleam", 116). -spec is_digit(binary()) -> boolean(). is_digit(C) -> in_range(C, <<"0"/utf8>>, <<"9"/utf8>>). -file("src/glsql/lexer.gleam", 124). -spec is_word_char(binary()) -> boolean(). is_word_char(C) -> (((is_digit(C) orelse in_range(C, <<"a"/utf8>>, <<"z"/utf8>>)) orelse in_range( C, <<"A"/utf8>>, <<"Z"/utf8>> )) orelse (C =:= <<"_"/utf8>>)) orelse (C =:= <<"$"/utf8>>). -file("src/glsql/lexer.gleam", 132). -spec take_while( list(binary()), fun((binary()) -> boolean()), integer(), binary() ) -> {binary(), list(binary()), integer()}. take_while(Chars, Pred, Pos, Acc) -> case Chars of [C | Rest] -> case Pred(C) of true -> take_while(Rest, Pred, Pos + 1, <>); false -> {Acc, Chars, Pos} end; [] -> {Acc, [], Pos} end. -file("src/glsql/lexer.gleam", 120). -spec is_number_char(binary()) -> boolean(). is_number_char(C) -> is_digit(C) orelse (C =:= <<"."/utf8>>). -file("src/glsql/lexer.gleam", 213). -spec starts_with_seq(list(binary()), list(binary())) -> boolean(). starts_with_seq(Chars, Seq) -> case Seq of [] -> true; [S | Srest] -> case Chars of [C | Crest] -> (C =:= S) andalso starts_with_seq(Crest, Srest); [] -> false end end. -file("src/glsql/lexer.gleam", 190). -spec scan_dollar_quote_body(list(binary()), binary(), integer(), binary()) -> {ok, {binary(), list(binary()), integer()}} | {error, nil}. scan_dollar_quote_body(Chars, Tag, Pos, Acc) -> Closer = gleam@string:to_graphemes( <<<<"$"/utf8, Tag/binary>>/binary, "$"/utf8>> ), case Chars of [] -> {error, nil}; _ -> case starts_with_seq(Chars, Closer) of true -> Closer_len = erlang:length(Closer), {ok, {Acc, gleam@list:drop(Chars, Closer_len), Pos + Closer_len}}; false -> {C@1, Rest@1} = case Chars of [C | Rest] -> {C, Rest}; _assert_fail -> erlang:error(#{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, file => <>, module => <<"glsql/lexer"/utf8>>, function => <<"scan_dollar_quote_body"/utf8>>, line => 206, value => _assert_fail, start => 5578, 'end' => 5608, pattern_start => 5589, pattern_end => 5600}) end, scan_dollar_quote_body( Rest@1, Tag, Pos + 1, <> ) end end. -file("src/glsql/lexer.gleam", 170). -spec is_tag_char(binary()) -> boolean(). is_tag_char(C) -> ((is_digit(C) orelse in_range(C, <<"a"/utf8>>, <<"z"/utf8>>)) orelse in_range( C, <<"A"/utf8>>, <<"Z"/utf8>> )) orelse (C =:= <<"_"/utf8>>). -file("src/glsql/lexer.gleam", 174). -spec try_dollar_quote_open(list(binary()), integer()) -> {ok, {binary(), list(binary()), integer()}} | {error, nil}. try_dollar_quote_open(Chars, Pos) -> case Chars of [<<"$"/utf8>> | Rest] -> {Tag, Rest@1, Tag_end} = take_while( Rest, fun is_tag_char/1, Pos + 1, <<""/utf8>> ), case Rest@1 of [<<"$"/utf8>> | Rest@2] -> {ok, {Tag, Rest@2, Tag_end + 1}}; _ -> {error, nil} end; _ -> {error, nil} end. -file("src/glsql/lexer.gleam", 224). -spec take_delimited(list(binary()), binary(), integer(), binary()) -> {ok, {binary(), list(binary()), integer()}} | {error, nil}. take_delimited(Chars, Delim, Pos, Acc) -> case Chars of [] -> {error, nil}; [C | Rest] -> case C =:= Delim of true -> {ok, {Acc, Rest, Pos + 1}}; false -> take_delimited( Rest, Delim, Pos + 1, <> ) end end. -file("src/glsql/lexer.gleam", 159). -spec skip_block_comment(list(binary()), integer()) -> {ok, {list(binary()), integer()}} | {error, glsql@error:error()}. skip_block_comment(Chars, Pos) -> case Chars of [] -> {error, {lex_error, <<"Unterminated block comment"/utf8>>, Pos}}; [<<"*"/utf8>>, <<"/"/utf8>> | Rest] -> {ok, {Rest, Pos + 2}}; [_ | Rest@1] -> skip_block_comment(Rest@1, Pos + 1) end. -file("src/glsql/lexer.gleam", 148). -spec take_until_newline(list(binary()), integer()) -> {nil, list(binary()), integer()}. take_until_newline(Chars, Pos) -> case Chars of [] -> {nil, [], Pos}; [<<"\n"/utf8>> | Rest] -> {nil, Rest, Pos + 1}; [_ | Rest@1] -> take_until_newline(Rest@1, Pos + 1) end. -file("src/glsql/lexer.gleam", 103). -spec punct( glsql@token:token(), list(binary()), integer(), list(glsql@token:positioned()) ) -> {ok, list(glsql@token:positioned())} | {error, glsql@error:error()}. punct(Tok, Rest, Pos, Acc) -> do_lex(Rest, Pos + 1, [{positioned, Tok, Pos, Pos + 1} | Acc]). -file("src/glsql/lexer.gleam", 13). -spec do_lex(list(binary()), integer(), list(glsql@token:positioned())) -> {ok, list(glsql@token:positioned())} | {error, glsql@error:error()}. do_lex(Chars, Pos, Acc) -> case Chars of [] -> {ok, Acc}; [<<" "/utf8>> | Rest] -> do_lex(Rest, Pos + 1, Acc); [<<"\n"/utf8>> | Rest] -> do_lex(Rest, Pos + 1, Acc); [<<"\t"/utf8>> | Rest] -> do_lex(Rest, Pos + 1, Acc); [<<"\r"/utf8>> | Rest] -> do_lex(Rest, Pos + 1, Acc); [<<"\r\n"/utf8>> | Rest@1] -> do_lex(Rest@1, Pos + 1, Acc); [<<"-"/utf8>>, <<"-"/utf8>> | Rest@2] -> {_, Rest@3, Pos@1} = take_until_newline(Rest@2, Pos + 2), do_lex(Rest@3, Pos@1, Acc); [<<"/"/utf8>>, <<"*"/utf8>> | Rest@4] -> case skip_block_comment(Rest@4, Pos + 2) of {ok, {Rest@5, Pos@2}} -> do_lex(Rest@5, Pos@2, Acc); {error, E} -> {error, E} end; [<<"("/utf8>> | Rest@6] -> punct(l_paren, Rest@6, Pos, Acc); [<<")"/utf8>> | Rest@7] -> punct(r_paren, Rest@7, Pos, Acc); [<<","/utf8>> | Rest@8] -> punct(comma, Rest@8, Pos, Acc); [<<";"/utf8>> | Rest@9] -> punct(semicolon, Rest@9, Pos, Acc); [<<"."/utf8>> | Rest@10] -> punct(dot, Rest@10, Pos, Acc); [<<"["/utf8>> | Rest@11] -> punct(l_bracket, Rest@11, Pos, Acc); [<<"]"/utf8>> | Rest@12] -> punct(r_bracket, Rest@12, Pos, Acc); [<<"\""/utf8>> | Rest@13] -> case take_delimited(Rest@13, <<"\""/utf8>>, Pos + 1, <<""/utf8>>) of {ok, {Text, Rest@14, End}} -> do_lex( Rest@14, End, [{positioned, {quoted_ident, Text}, Pos, End} | Acc] ); {error, nil} -> {error, {lex_error, <<"Unterminated quoted identifier"/utf8>>, Pos}} end; [<<"'"/utf8>> | Rest@15] -> case take_delimited(Rest@15, <<"'"/utf8>>, Pos + 1, <<""/utf8>>) of {ok, {Text@1, Rest@16, End@1}} -> do_lex( Rest@16, End@1, [{positioned, {string_lit, Text@1}, Pos, End@1} | Acc] ); {error, nil} -> {error, {lex_error, <<"Unterminated string literal"/utf8>>, Pos}} end; [<<"$"/utf8>> | _] -> case try_dollar_quote_open(Chars, Pos) of {error, nil} -> {Text@2, Rest@17, End@2} = take_while( Chars, fun is_word_char/1, Pos, <<""/utf8>> ), do_lex( Rest@17, End@2, [{positioned, {word, Text@2}, Pos, End@2} | Acc] ); {ok, {Tag, Body, Body_pos}} -> case scan_dollar_quote_body( Body, Tag, Body_pos, <<""/utf8>> ) of {ok, {Text@3, Rest@18, End@3}} -> do_lex( Rest@18, End@3, [{positioned, {string_lit, Text@3}, Pos, End@3} | Acc] ); {error, nil} -> {error, {lex_error, <<"Unterminated dollar-quoted string"/utf8>>, Pos}} end end; [C | Rest@19] -> case is_digit(C) of true -> {Text@4, Rest@20, End@4} = take_while( Chars, fun is_number_char/1, Pos, <<""/utf8>> ), do_lex( Rest@20, End@4, [{positioned, {number, Text@4}, Pos, End@4} | Acc] ); false -> case is_word_char(C) of true -> {Text@5, Rest@21, End@5} = take_while( Chars, fun is_word_char/1, Pos, <<""/utf8>> ), do_lex( Rest@21, End@5, [{positioned, {word, Text@5}, Pos, End@5} | Acc] ); false -> do_lex( Rest@19, Pos + 1, [{positioned, {symbol, C}, Pos, Pos + 1} | Acc] ) end end end. -file("src/glsql/lexer.gleam", 8). -spec lex(binary()) -> {ok, list(glsql@token:positioned())} | {error, glsql@error:error()}. lex(Src) -> _pipe = do_lex(gleam@string:to_graphemes(Src), 0, []), gleam@result:map(_pipe, fun lists:reverse/1).