-module(datadog_query@parse). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/datadog_query/parse.gleam"). -export([filter/1]). -export_type([parse_error/0, separator/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 parse_error() :: unexpected_end | {unexpected, binary()} | empty_input. -type separator() :: sep_colon | {sep_compare, datadog_query@ast:comparison_op()} | sep_regex | sep_in | sep_not_in. -file("src/datadog_query/parse.gleam", 359). -spec skip_whitespace(list(binary())) -> list(binary()). skip_whitespace(Chars) -> case Chars of [<<" "/utf8>> | Rest] -> skip_whitespace(Rest); [<<"\t"/utf8>> | Rest] -> skip_whitespace(Rest); [<<"\n"/utf8>> | Rest] -> skip_whitespace(Rest); [<<"\r"/utf8>> | Rest] -> skip_whitespace(Rest); _ -> Chars end. -file("src/datadog_query/parse.gleam", 305). -spec is_bare_value_char(binary()) -> boolean(). is_bare_value_char(C) -> case C of <<" "/utf8>> -> false; <<"\t"/utf8>> -> false; <<"\n"/utf8>> -> false; <<"\r"/utf8>> -> false; <<","/utf8>> -> false; <<"("/utf8>> -> false; <<")"/utf8>> -> false; <<"}"/utf8>> -> false; _ -> true end. -file("src/datadog_query/parse.gleam", 411). -spec do_take_while( list(binary()), fun((binary()) -> boolean()), list(binary()) ) -> {list(binary()), list(binary())}. do_take_while(Chars, Pred, Acc) -> case Chars of [C | Rest] -> case Pred(C) of true -> do_take_while(Rest, Pred, [C | Acc]); false -> {lists:reverse(Acc), Chars} end; [] -> {lists:reverse(Acc), Chars} end. -file("src/datadog_query/parse.gleam", 404). -spec take_while(list(binary()), fun((binary()) -> boolean())) -> {list(binary()), list(binary())}. take_while(Chars, Pred) -> do_take_while(Chars, Pred, []). -file("src/datadog_query/parse.gleam", 314). -spec parse_quoted(list(binary()), list(binary())) -> {ok, {binary(), list(binary())}} | {error, parse_error()}. parse_quoted(Chars, Acc) -> case Chars of [] -> {error, unexpected_end}; [<<"\\"/utf8>>, <<"\""/utf8>> | Rest] -> parse_quoted(Rest, [<<"\""/utf8>> | Acc]); [<<"\\"/utf8>>, C | Rest@1] -> parse_quoted(Rest@1, [C, <<"\\"/utf8>> | Acc]); [<<"\""/utf8>> | Rest@2] -> {ok, {erlang:list_to_binary(lists:reverse(Acc)), Rest@2}}; [C@1 | Rest@3] -> parse_quoted(Rest@3, [C@1 | Acc]) end. -file("src/datadog_query/parse.gleam", 288). -spec parse_value(list(binary())) -> {ok, {binary(), list(binary())}} | {error, parse_error()}. parse_value(Chars) -> case Chars of [<<"\""/utf8>> | Rest] -> parse_quoted(Rest, []); _ -> case take_while(Chars, fun is_bare_value_char/1) of {[], _} -> case Chars of [] -> {error, unexpected_end}; [C | _] -> {error, {unexpected, C}} end; {Taken, Rest@1} -> {ok, {erlang:list_to_binary(Taken), Rest@1}} end end. -file("src/datadog_query/parse.gleam", 338). -spec collect_values(list(binary()), list(binary())) -> {ok, {list(binary()), list(binary())}} | {error, parse_error()}. collect_values(Acc, Chars) -> case Chars of [<<")"/utf8>> | Rest] -> {ok, {lists:reverse(Acc), Rest}}; _ -> gleam@result:'try'( parse_value(Chars), fun(_use0) -> {Value, Rest@1} = _use0, Rest@2 = skip_whitespace(Rest@1), case Rest@2 of [<<","/utf8>> | Tail] -> collect_values([Value | Acc], skip_whitespace(Tail)); [<<")"/utf8>> | Tail@1] -> {ok, {lists:reverse([Value | Acc]), Tail@1}}; [] -> {error, unexpected_end}; [C | _] -> {error, {unexpected, C}} end end ) end. -file("src/datadog_query/parse.gleam", 327). -spec parse_value_list(list(binary())) -> {ok, {list(binary()), list(binary())}} | {error, parse_error()}. parse_value_list(Chars) -> Chars@1 = skip_whitespace(Chars), case Chars@1 of [<<"("/utf8>> | Rest] -> collect_values([], skip_whitespace(Rest)); [] -> {error, unexpected_end}; [C | _] -> {error, {unexpected, C}} end. -file("src/datadog_query/parse.gleam", 426). -spec is_alnum(binary()) -> boolean(). is_alnum(C) -> case C 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; <<"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; _ -> false end. -file("src/datadog_query/parse.gleam", 279). -spec is_ident_char(binary()) -> boolean(). is_ident_char(C) -> case C of <<"."/utf8>> -> true; <<"_"/utf8>> -> true; <<"-"/utf8>> -> true; <<"@"/utf8>> -> true; _ -> is_alnum(C) end. -file("src/datadog_query/parse.gleam", 389). -spec strip_prefix(list(binary()), list(binary())) -> {ok, list(binary())} | {error, nil}. strip_prefix(Chars, Prefix) -> case {Prefix, Chars} of {[], _} -> {ok, Chars}; {[_ | _], []} -> {error, nil}; {[P | Ps], [C | Cs]} -> case P =:= C of true -> strip_prefix(Cs, Ps); false -> {error, nil} end end. -file("src/datadog_query/parse.gleam", 370). ?DOC( " Consumes `keyword` from `chars` only if (a) it appears verbatim AND\n" " (b) the character immediately after isn't an ident continuation\n" " (so `OR` matches but `ORder` does not).\n" ). -spec match_keyword(list(binary()), binary()) -> {ok, list(binary())} | {error, nil}. match_keyword(Chars, Keyword) -> Kw_chars = gleam@string:to_graphemes(Keyword), case strip_prefix(Chars, Kw_chars) of {ok, Rest} -> case Rest of [] -> {ok, Rest}; [C | _] -> case is_ident_char(C) of true -> {error, nil}; false -> {ok, Rest} end end; {error, _} -> {error, nil} end. -file("src/datadog_query/parse.gleam", 231). ?DOC( " Looks for a separator immediately after the tag name (`tight`, no space)\n" " or after intervening whitespace (`loose`, for `IN`/`NOT IN`).\n" ). -spec parse_separator(list(binary()), list(binary())) -> {ok, {separator(), list(binary())}} | {error, parse_error()}. parse_separator(Tight, Loose) -> case Tight of [<<":"/utf8>>, <<">"/utf8>>, <<"="/utf8>> | Rest] -> {ok, {{sep_compare, gte}, Rest}}; [<<":"/utf8>>, <<"<"/utf8>>, <<"="/utf8>> | Rest@1] -> {ok, {{sep_compare, lte}, Rest@1}}; [<<":"/utf8>>, <<">"/utf8>> | Rest@2] -> {ok, {{sep_compare, gt}, Rest@2}}; [<<":"/utf8>>, <<"<"/utf8>> | Rest@3] -> {ok, {{sep_compare, lt}, Rest@3}}; [<<":"/utf8>>, <<"~"/utf8>> | Rest@4] -> {ok, {sep_regex, Rest@4}}; [<<":"/utf8>> | Rest@5] -> {ok, {sep_colon, Rest@5}}; _ -> case match_keyword(Loose, <<"NOT"/utf8>>) of {ok, After_not} -> After_not_ws = skip_whitespace(After_not), case match_keyword(After_not_ws, <<"IN"/utf8>>) of {ok, Rest@6} -> {ok, {sep_not_in, skip_whitespace(Rest@6)}}; {error, _} -> {error, {unexpected, <<"NOT without IN after tag name"/utf8>>}} end; {error, _} -> case match_keyword(Loose, <<"IN"/utf8>>) of {ok, Rest@7} -> {ok, {sep_in, skip_whitespace(Rest@7)}}; {error, _} -> case Loose of [] -> {error, unexpected_end}; [C | _] -> {error, {unexpected, C}} end end end end. -file("src/datadog_query/parse.gleam", 266). -spec parse_ident(list(binary())) -> {ok, {binary(), list(binary())}} | {error, parse_error()}. parse_ident(Chars) -> case take_while(Chars, fun is_ident_char/1) of {[], _} -> case Chars of [] -> {error, unexpected_end}; [C | _] -> {error, {unexpected, C}} end; {Taken, Rest} -> {ok, {erlang:list_to_binary(Taken), Rest}} end. -file("src/datadog_query/parse.gleam", 166). -spec parse_simple_filter(list(binary())) -> {ok, {datadog_query@ast:filter(), list(binary())}} | {error, parse_error()}. parse_simple_filter(Chars) -> {Negated, Chars@1} = case Chars of [<<"!"/utf8>> | Rest] -> {true, Rest}; _ -> {false, Chars} end, gleam@result:'try'( parse_ident(Chars@1), fun(_use0) -> {Name, Rest@1} = _use0, Rest_ws = skip_whitespace(Rest@1), case parse_separator(Rest@1, Rest_ws) of {ok, {sep_colon, After}} -> gleam@result:'try'( parse_value(After), fun(_use0@1) -> {Value, After@1} = _use0@1, case Negated of true -> {ok, {{negated_tag, Name, Value}, After@1}}; false -> {ok, {{tag, Name, Value}, After@1}} end end ); {ok, {{sep_compare, Op}, After@2}} -> gleam@result:'try'( parse_value(After@2), fun(_use0@2) -> {Value@1, After@3} = _use0@2, Node = {tag_comparison, Name, Op, Value@1}, case Negated of true -> {ok, {{'not', Node}, After@3}}; false -> {ok, {Node, After@3}} end end ); {ok, {sep_regex, After@4}} -> gleam@result:'try'( parse_value(After@4), fun(_use0@3) -> {Value@2, After@5} = _use0@3, Node@1 = {tag_regex, Name, Value@2}, case Negated of true -> {ok, {{'not', Node@1}, After@5}}; false -> {ok, {Node@1, After@5}} end end ); {ok, {sep_in, After@6}} -> gleam@result:'try'( parse_value_list(After@6), fun(_use0@4) -> {Values, After@7} = _use0@4, Node@2 = {tag_in, Name, Values}, case Negated of true -> {ok, {{'not', Node@2}, After@7}}; false -> {ok, {Node@2, After@7}} end end ); {ok, {sep_not_in, After@8}} -> gleam@result:'try'( parse_value_list(After@8), fun(_use0@5) -> {Values@1, After@9} = _use0@5, Node@3 = {tag_not_in, Name, Values@1}, case Negated of true -> {ok, {{'not', Node@3}, After@9}}; false -> {ok, {Node@3, After@9}} end end ); {error, E} -> {error, E} end end ). -file("src/datadog_query/parse.gleam", 150). -spec is_filter_terminator(list(binary())) -> boolean(). is_filter_terminator(Chars) -> case Chars of [] -> true; [<<")"/utf8>> | _] -> true; _ -> case match_keyword(Chars, <<"AND"/utf8>>) of {ok, _} -> true; {error, _} -> case match_keyword(Chars, <<"OR"/utf8>>) of {ok, _} -> true; {error, _} -> false end end end. -file("src/datadog_query/parse.gleam", 135). -spec parse_simple_or_wildcard(list(binary())) -> {ok, {datadog_query@ast:filter(), list(binary())}} | {error, parse_error()}. parse_simple_or_wildcard(Chars) -> case Chars of [<<"*"/utf8>> | Rest] -> case is_filter_terminator(skip_whitespace(Rest)) of true -> {ok, {wildcard, Rest}}; false -> parse_simple_filter(Chars) end; _ -> parse_simple_filter(Chars) end. -file("src/datadog_query/parse.gleam", 118). -spec parse_atom(list(binary())) -> {ok, {datadog_query@ast:filter(), list(binary())}} | {error, parse_error()}. parse_atom(Chars) -> case Chars of [<<"("/utf8>> | Rest] -> gleam@result:'try'( parse_or(skip_whitespace(Rest)), fun(_use0) -> {Inner, Rest@1} = _use0, Rest@2 = skip_whitespace(Rest@1), case Rest@2 of [<<")"/utf8>> | Tail] -> {ok, {Inner, Tail}}; [] -> {error, unexpected_end}; [C | _] -> {error, {unexpected, C}} end end ); _ -> parse_simple_or_wildcard(Chars) end. -file("src/datadog_query/parse.gleam", 95). -spec parse_primary(list(binary())) -> {ok, {datadog_query@ast:filter(), list(binary())}} | {error, parse_error()}. parse_primary(Chars) -> Chars@1 = skip_whitespace(Chars), case match_keyword(Chars@1, <<"NOT"/utf8>>) of {ok, Rest} -> After_ws = skip_whitespace(Rest), case match_keyword(After_ws, <<"IN"/utf8>>) of {ok, _} -> parse_atom(Chars@1); {error, _} -> gleam@result:'try'( parse_primary(After_ws), fun(_use0) -> {Inner, Rest@1} = _use0, {ok, {{'not', Inner}, Rest@1}} end ) end; {error, _} -> parse_atom(Chars@1) end. -file("src/datadog_query/parse.gleam", 77). -spec collect_and(list(datadog_query@ast:filter()), list(binary())) -> {ok, {datadog_query@ast:filter(), list(binary())}} | {error, parse_error()}. collect_and(Acc, Chars) -> Chars@1 = skip_whitespace(Chars), case match_keyword(Chars@1, <<"AND"/utf8>>) of {ok, Rest} -> gleam@result:'try'( parse_primary(skip_whitespace(Rest)), fun(_use0) -> {Next, Rest@1} = _use0, collect_and([Next | Acc], Rest@1) end ); {error, _} -> case Acc of [Single] -> {ok, {Single, Chars@1}}; Many -> {ok, {{'and', lists:reverse(Many)}, Chars@1}} end end. -file("src/datadog_query/parse.gleam", 72). -spec parse_and(list(binary())) -> {ok, {datadog_query@ast:filter(), list(binary())}} | {error, parse_error()}. parse_and(Chars) -> gleam@result:'try'( parse_primary(Chars), fun(_use0) -> {First, Rest} = _use0, collect_and([First], Rest) end ). -file("src/datadog_query/parse.gleam", 54). -spec collect_or(list(datadog_query@ast:filter()), list(binary())) -> {ok, {datadog_query@ast:filter(), list(binary())}} | {error, parse_error()}. collect_or(Acc, Chars) -> Chars@1 = skip_whitespace(Chars), case match_keyword(Chars@1, <<"OR"/utf8>>) of {ok, Rest} -> gleam@result:'try'( parse_and(skip_whitespace(Rest)), fun(_use0) -> {Next, Rest@1} = _use0, collect_or([Next | Acc], Rest@1) end ); {error, _} -> case Acc of [Single] -> {ok, {Single, Chars@1}}; Many -> {ok, {{'or', lists:reverse(Many)}, Chars@1}} end end. -file("src/datadog_query/parse.gleam", 49). -spec parse_or(list(binary())) -> {ok, {datadog_query@ast:filter(), list(binary())}} | {error, parse_error()}. parse_or(Chars) -> gleam@result:'try'( parse_and(Chars), fun(_use0) -> {First, Rest} = _use0, collect_or([First], Rest) end ). -file("src/datadog_query/parse.gleam", 32). -spec filter(binary()) -> {ok, datadog_query@ast:filter()} | {error, parse_error()}. filter(Input) -> Chars = gleam@string:to_graphemes(Input), Chars@1 = skip_whitespace(Chars), case Chars@1 of [] -> {error, empty_input}; _ -> gleam@result:'try'( parse_or(Chars@1), fun(_use0) -> {Parsed, Rest} = _use0, case skip_whitespace(Rest) of [] -> {ok, Parsed}; Leftover -> {error, {unexpected, erlang:list_to_binary(Leftover)}} end end ) end.