-module(kdleam@parse). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/kdleam/parse.gleam"). -export([parse/1]). -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). -file("src/kdleam/parse.gleam", 132). ?DOC(false). -spec skip_node_terminator( kdleam@scanner:scanner(), kdleam@scanner:node_context() ) -> {ok, kdleam@scanner:scanner()} | {error, kdleam@error:kdl_error()}. skip_node_terminator(S, Ctx) -> gleam@result:'try'( kdleam@comment:skip_node_space(S), fun(Space) -> {_, S@1} = Space, case kdleam@scanner:peek(S@1) of {some, <<";"/utf8>>} -> {_, Next} = kdleam@scanner:advance(S@1), {ok, Next}; {some, <<"/"/utf8>>} -> case kdleam@scanner:peek_next(S@1) of {some, <<"/"/utf8>>} -> {_, S1} = kdleam@scanner:advance(S@1), {_, S2} = kdleam@scanner:advance(S1), gleam@result:'try'( kdleam@comment:skip_single_line_comment(S2), fun(S3) -> {_, S4} = kdleam@scanner:consume_newline(S3), {ok, S4} end ); _ -> {error, kdleam@scanner:make_error( S@1, {unexpected_char, <<"/"/utf8>>} )} end; {some, Ch} -> case kdleam@scanner:is_newline(Ch) of true -> {_, Next@1} = kdleam@scanner:consume_newline(S@1), {ok, Next@1}; false -> case (Ch =:= <<"}"/utf8>>) andalso (Ctx =:= in_children) of true -> {ok, S@1}; false -> {error, kdleam@scanner:make_error( S@1, {unexpected_char, Ch} )} end end; none -> {ok, S@1} end end ). -file("src/kdleam/parse.gleam", 509). ?DOC(false). -spec try_parse_keyword(kdleam@scanner:scanner()) -> {gleam@option:option(kdleam@document:kdl_value()), kdleam@scanner:scanner()}. try_parse_keyword(S) -> Candidates = [{<<"#true"/utf8>>, {kdl_bool, true}}, {<<"#false"/utf8>>, {kdl_bool, false}}, {<<"#null"/utf8>>, kdl_null}], kdleam@scanner:try_tokens(S, Candidates). -file("src/kdleam/parse.gleam", 487). ?DOC(false). -spec parse_value(kdleam@scanner:scanner()) -> {ok, {kdleam@document:kdl_value(), kdleam@scanner:scanner()}} | {error, kdleam@error:kdl_error()}. parse_value(S) -> gleam@result:'try'( kdleam@number:parse_keyword_number(S), fun(Kn) -> case Kn of {{some, N}, S1} -> {ok, {{kdl_number_value, N}, S1}}; {none, _} -> case try_parse_keyword(S) of {{some, Value}, S1@1} -> {ok, {Value, S1@1}}; {none, _} -> gleam@result:'try'( kdleam@number:parse_number(S), fun(Num) -> case Num of {{some, N@1}, S1@2} -> {ok, {{kdl_number_value, N@1}, S1@2}}; {none, _} -> gleam@result:'try'( kdleam@string:parse_string(S), fun(Parsed) -> {Value@1, S1@3} = Parsed, {ok, {{kdl_string, Value@1}, S1@3}} end ) end end ) end end end ). -file("src/kdleam/parse.gleam", 384). ?DOC(false). -spec skip_type_node_space(kdleam@scanner:scanner()) -> {ok, kdleam@scanner:scanner()} | {error, kdleam@error:kdl_error()}. skip_type_node_space(S) -> gleam@result:'try'( kdleam@comment:skip_node_space(S), fun(Space) -> {_, Next} = Space, {ok, Next} end ). -file("src/kdleam/parse.gleam", 365). ?DOC(false). -spec try_parse_type_annotation(kdleam@scanner:scanner()) -> {ok, {gleam@option:option(binary()), kdleam@scanner:scanner()}} | {error, kdleam@error:kdl_error()}. try_parse_type_annotation(S) -> case kdleam@scanner:peek(S) of {some, <<"("/utf8>>} -> {_, S1} = kdleam@scanner:advance(S), gleam@result:'try'( kdleam@comment:skip_node_space(S1), fun(Space1) -> {_, S2} = Space1, gleam@result:'try'( kdleam@string:parse_string(S2), fun(Parsed) -> {Ty, S3} = Parsed, gleam@result:'try'( kdleam@comment:skip_node_space(S3), fun(Space2) -> {_, S4} = Space2, gleam@result:'try'( kdleam@scanner:expect(S4, <<")"/utf8>>), fun(S5) -> {ok, {{some, Ty}, S5}} end ) end ) end ) end ); _ -> {ok, {none, S}} end. -file("src/kdleam/parse.gleam", 452). ?DOC(false). -spec finish_string_entry( kdleam@scanner:scanner(), binary(), gleam@option:option(binary()) ) -> {ok, {gleam@option:option(kdleam@document:kdl_entry()), kdleam@scanner:scanner()}} | {error, kdleam@error:kdl_error()}. finish_string_entry(S, Value, Ty) -> gleam@result:'try'( kdleam@comment:skip_ws(S), fun(S1) -> case kdleam@scanner:peek(S1) of {some, <<"="/utf8>>} -> case Ty of {some, _} -> {error, kdleam@scanner:make_error( S1, {unexpected_char, <<"="/utf8>>} )}; none -> {_, S2} = kdleam@scanner:advance(S1), gleam@result:'try'( kdleam@comment:skip_ws(S2), fun(S3) -> gleam@result:'try'( try_parse_type_annotation(S3), fun(Val_ty) -> {Vty, S4} = Val_ty, gleam@result:'try'(case Vty of {some, _} -> skip_type_node_space(S4); none -> {ok, S4} end, fun(S5) -> gleam@result:'try'( parse_value(S5), fun(Val) -> {Parsed_value, S6} = Val, {ok, {{some, {kdl_property, Value, Vty, Parsed_value}}, S6}} end ) end) end ) end ) end; _ -> {ok, {{some, {kdl_argument, Ty, {kdl_string, Value}}}, S}} end end ). -file("src/kdleam/parse.gleam", 441). ?DOC(false). -spec parse_string_entry( kdleam@scanner:scanner(), gleam@option:option(binary()) ) -> {ok, {gleam@option:option(kdleam@document:kdl_entry()), kdleam@scanner:scanner()}} | {error, kdleam@error:kdl_error()}. parse_string_entry(S, Ty) -> gleam@result:'try'( kdleam@string:parse_string_if_available(S), fun(Parsed) -> case Parsed of {{some, Value}, S1} -> finish_string_entry(S1, Value, Ty); {none, _} -> {ok, {none, S}} end end ). -file("src/kdleam/parse.gleam", 415). ?DOC(false). -spec parse_hash_entry(kdleam@scanner:scanner(), gleam@option:option(binary())) -> {ok, {gleam@option:option(kdleam@document:kdl_entry()), kdleam@scanner:scanner()}} | {error, kdleam@error:kdl_error()}. parse_hash_entry(S, Ty) -> gleam@result:'try'( kdleam@string:parse_raw_string(S), fun(Raw) -> case Raw of {{some, Value}, S1} -> finish_string_entry(S1, Value, Ty); {none, _} -> gleam@result:'try'( kdleam@number:parse_keyword_number(S), fun(Kn) -> case Kn of {{some, N}, S1@1} -> {ok, {{some, {kdl_argument, Ty, {kdl_number_value, N}}}, S1@1}}; {none, _} -> case try_parse_keyword(S) of {{some, Value@1}, S1@2} -> {ok, {{some, {kdl_argument, Ty, Value@1}}, S1@2}}; {none, _} -> {ok, {none, S}} end end end ) end end ). -file("src/kdleam/parse.gleam", 390). ?DOC(false). -spec try_parse_entry(kdleam@scanner:scanner()) -> {ok, {gleam@option:option(kdleam@document:kdl_entry()), kdleam@scanner:scanner()}} | {error, kdleam@error:kdl_error()}. try_parse_entry(S) -> gleam@result:'try'( try_parse_type_annotation(S), fun(Ty_result) -> {Ty, S1} = Ty_result, gleam@result:'try'(case Ty of {some, _} -> skip_type_node_space(S1); none -> {ok, S1} end, fun(S2) -> case kdleam@scanner:peek(S2) of {some, <<"#"/utf8>>} -> parse_hash_entry(S2, Ty); _ -> gleam@result:'try'( kdleam@number:parse_number(S2), fun(Num) -> case Num of {{some, N}, S3} -> {ok, {{some, {kdl_argument, Ty, {kdl_number_value, N}}}, S3}}; {none, _} -> parse_string_entry(S2, Ty) end end ) end end) end ). -file("src/kdleam/parse.gleam", 348). ?DOC(false). -spec try_consume_entry_slashdash(kdleam@scanner:scanner()) -> {ok, {boolean(), kdleam@scanner:scanner()}} | {error, kdleam@error:kdl_error()}. try_consume_entry_slashdash(S) -> {Ok, S1} = kdleam@scanner:consume_token(S, <<"/-"/utf8>>), case Ok of false -> {ok, {false, S}}; true -> gleam@result:'try'( kdleam@comment:skip_line_space(S1), fun(S2) -> case kdleam@scanner:peek(S2) of {some, <<"}"/utf8>>} -> {error, kdleam@scanner:make_error(S2, invalid_slashdash)}; {some, <<";"/utf8>>} -> {error, kdleam@scanner:make_error(S2, invalid_slashdash)}; none -> {error, kdleam@scanner:make_error(S2, invalid_slashdash)}; _ -> {ok, {true, S2}} end end ) end. -file("src/kdleam/parse.gleam", 121). ?DOC(false). -spec try_consume_slashdash(kdleam@scanner:scanner()) -> {ok, {boolean(), kdleam@scanner:scanner()}} | {error, kdleam@error:kdl_error()}. try_consume_slashdash(S) -> {Ok, S1} = kdleam@scanner:consume_token(S, <<"/-"/utf8>>), case Ok of true -> gleam@result:'try'( kdleam@comment:skip_line_space(S1), fun(S2) -> {ok, {true, S2}} end ); false -> {ok, {false, S}} end. -file("src/kdleam/parse.gleam", 283). ?DOC(false). -spec consume_slashdash_children(kdleam@scanner:scanner()) -> {ok, kdleam@scanner:scanner()} | {error, kdleam@error:kdl_error()}. consume_slashdash_children(S) -> gleam@result:'try'( kdleam@comment:skip_node_space(S), fun(Space) -> {_, S1} = Space, {Ok, S2} = kdleam@scanner:consume_token(S1, <<"/-"/utf8>>), case Ok of false -> {ok, S}; true -> gleam@result:'try'( kdleam@comment:skip_line_space(S2), fun(S3) -> case kdleam@scanner:peek(S3) of {some, <<"{"/utf8>>} -> {_, S4} = kdleam@scanner:advance(S3), gleam@result:'try'( parse_nodes(S4, in_children), fun(Parsed) -> {_, S5} = Parsed, gleam@result:'try'( kdleam@scanner:expect( S5, <<"}"/utf8>> ), fun(S6) -> consume_slashdash_children( S6 ) end ) end ); _ -> {ok, S} end end ) end end ). -file("src/kdleam/parse.gleam", 261). ?DOC(false). -spec parse_children( kdleam@scanner:scanner(), binary(), gleam@option:option(binary()), list(kdleam@document:kdl_entry()) ) -> {ok, {gleam@option:option(kdleam@document:kdl_node()), kdleam@scanner:scanner()}} | {error, kdleam@error:kdl_error()}. parse_children(S, Name, Ty, Entries) -> {_, S1} = kdleam@scanner:advance(S), gleam@result:'try'( parse_nodes(S1, in_children), fun(Result) -> {Kids, S2} = Result, gleam@result:'try'( kdleam@scanner:expect(S2, <<"}"/utf8>>), fun(S3) -> gleam@result:'try'( consume_slashdash_children(S3), fun(S4) -> {ok, {{some, {kdl_node, Ty, Name, lists:reverse(Entries), {some, Kids}}}, S4}} end ) end ) end ). -file("src/kdleam/parse.gleam", 305). ?DOC(false). -spec parse_discarded_children( kdleam@scanner:scanner(), binary(), gleam@option:option(binary()), list(kdleam@document:kdl_entry()), gleam@option:option(list(kdleam@document:kdl_node())) ) -> {ok, {gleam@option:option(kdleam@document:kdl_node()), kdleam@scanner:scanner()}} | {error, kdleam@error:kdl_error()}. parse_discarded_children(S, Name, Ty, Entries, Children) -> {_, S1} = kdleam@scanner:advance(S), gleam@result:'try'( parse_nodes(S1, in_children), fun(Result) -> {_, S2} = Result, gleam@result:'try'( kdleam@scanner:expect(S2, <<"}"/utf8>>), fun(S3) -> gleam@result:'try'( kdleam@comment:skip_node_space(S3), fun(Space) -> {_, S4} = Space, case kdleam@scanner:peek(S4) of {some, <<"{"/utf8>>} -> parse_children(S4, Name, Ty, Entries); {some, <<"/"/utf8>>} -> parse_node_tail( S4, Name, Ty, Entries, Children ); {some, <<";"/utf8>>} -> {ok, {{some, {kdl_node, Ty, Name, lists:reverse(Entries), Children}}, S4}}; {some, <<"}"/utf8>>} -> {ok, {{some, {kdl_node, Ty, Name, lists:reverse(Entries), Children}}, S4}}; none -> {ok, {{some, {kdl_node, Ty, Name, lists:reverse(Entries), Children}}, S4}}; {some, Ch} -> case kdleam@scanner:is_newline(Ch) of true -> {ok, {{some, {kdl_node, Ty, Name, lists:reverse( Entries ), Children}}, S4}}; false -> {error, kdleam@scanner:make_error( S4, invalid_slashdash )} end end end ) end ) end ). -file("src/kdleam/parse.gleam", 217). ?DOC(false). -spec parse_entry_or_child( kdleam@scanner:scanner(), binary(), gleam@option:option(binary()), list(kdleam@document:kdl_entry()), gleam@option:option(list(kdleam@document:kdl_node())) ) -> {ok, {gleam@option:option(kdleam@document:kdl_node()), kdleam@scanner:scanner()}} | {error, kdleam@error:kdl_error()}. parse_entry_or_child(S, Name, Ty, Entries, Children) -> gleam@result:'try'( try_consume_entry_slashdash(S), fun(Sd) -> {Slashdash, S1} = Sd, case kdleam@scanner:peek(S1) of {some, <<"{"/utf8>>} -> case Slashdash of true -> parse_discarded_children( S1, Name, Ty, Entries, Children ); false -> parse_children(S1, Name, Ty, Entries) end; _ -> gleam@result:'try'( try_parse_entry(S1), fun(Parsed) -> case Parsed of {{some, Entry}, S2} -> parse_node_tail( S2, Name, Ty, case Slashdash of true -> Entries; false -> [Entry | Entries] end, Children ); {none, _} -> {ok, {{some, {kdl_node, Ty, Name, lists:reverse(Entries), Children}}, S1}} end end ) end end ). -file("src/kdleam/parse.gleam", 190). ?DOC(false). -spec parse_node_tail( kdleam@scanner:scanner(), binary(), gleam@option:option(binary()), list(kdleam@document:kdl_entry()), gleam@option:option(list(kdleam@document:kdl_node())) ) -> {ok, {gleam@option:option(kdleam@document:kdl_node()), kdleam@scanner:scanner()}} | {error, kdleam@error:kdl_error()}. parse_node_tail(S, Name, Ty, Entries, Children) -> gleam@result:'try'( kdleam@comment:skip_node_space(S), fun(Space) -> {Had_space, S1} = Space, case {Had_space, kdleam@scanner:peek(S1), kdleam@scanner:peek_next(S1)} of {false, {some, <<"{"/utf8>>}, _} -> parse_children(S1, Name, Ty, Entries); {false, {some, <<"/"/utf8>>}, {some, <<"-"/utf8>>}} -> parse_entry_or_child(S1, Name, Ty, Entries, Children); {false, _, _} -> {ok, {{some, {kdl_node, Ty, Name, lists:reverse(Entries), Children}}, S1}}; {_, _, _} -> parse_entry_or_child(S1, Name, Ty, Entries, Children) end end ). -file("src/kdleam/parse.gleam", 170). ?DOC(false). -spec parse_base_node(kdleam@scanner:scanner()) -> {ok, {gleam@option:option(kdleam@document:kdl_node()), kdleam@scanner:scanner()}} | {error, kdleam@error:kdl_error()}. parse_base_node(S) -> gleam@result:'try'( try_parse_type_annotation(S), fun(Ty_result) -> {Ty, S1} = Ty_result, gleam@result:'try'(case Ty of {some, _} -> skip_type_node_space(S1); none -> {ok, S1} end, fun(S2) -> gleam@result:'try'( kdleam@string:parse_string_if_available(S2), fun(Name_result) -> case Name_result of {{some, Name}, S3} -> parse_node_tail(S3, Name, Ty, [], none); {none, _} -> case Ty of {some, _} -> {error, kdleam@scanner:make_error( S2, unexpected_eof )}; none -> {ok, {none, S}} end end end ) end) end ). -file("src/kdleam/parse.gleam", 78). ?DOC(false). -spec parse_nodes_loop( kdleam@scanner:scanner(), kdleam@scanner:node_context(), list(kdleam@document:kdl_node()) ) -> {ok, {list(kdleam@document:kdl_node()), kdleam@scanner:scanner()}} | {error, kdleam@error:kdl_error()}. parse_nodes_loop(S, Ctx, Acc) -> gleam@result:'try'( kdleam@comment:skip_line_space(S), fun(S1) -> case {Ctx, kdleam@scanner:peek(S1), kdleam@scanner:is_eof(S1)} of {in_children, {some, <<"}"/utf8>>}, _} -> {ok, {lists:reverse(Acc), S1}}; {_, _, true} -> {ok, {lists:reverse(Acc), S1}}; {_, _, _} -> gleam@result:'try'( try_consume_slashdash(S1), fun(Sd) -> {Slashdash, S2} = Sd, gleam@result:'try'( kdleam@comment:skip_line_space(S2), fun(S3) -> case {Ctx, kdleam@scanner:peek(S3), kdleam@scanner:is_eof(S3), Slashdash} of {in_children, {some, <<"}"/utf8>>}, _, true} -> {error, kdleam@scanner:make_error( S3, invalid_slashdash )}; {_, _, true, true} -> {error, kdleam@scanner:make_error( S3, invalid_slashdash )}; {_, _, _, _} -> gleam@result:'try'( parse_base_node(S3), fun(Parsed) -> {Maybe_node, S4} = Parsed, Acc2 = case {Maybe_node, Slashdash} of {{some, Node}, false} -> [Node | Acc]; {_, _} -> Acc end, case {Maybe_node, kdleam@scanner:peek(S4)} of {none, {some, <<";"/utf8>>}} -> {error, kdleam@scanner:make_error( S4, {unexpected_char, <<";"/utf8>>} )}; {_, _} -> case {Ctx, kdleam@scanner:peek( S4 )} of {in_children, {some, <<"}"/utf8>>}} -> parse_nodes_loop( S4, Ctx, Acc2 ); {_, _} -> gleam@result:'try'( skip_node_terminator( S4, Ctx ), fun(S5) -> parse_nodes_loop( S5, Ctx, Acc2 ) end ) end end end ) end end ) end ) end end ). -file("src/kdleam/parse.gleam", 71). ?DOC(false). -spec parse_nodes(kdleam@scanner:scanner(), kdleam@scanner:node_context()) -> {ok, {list(kdleam@document:kdl_node()), kdleam@scanner:scanner()}} | {error, kdleam@error:kdl_error()}. parse_nodes(S, Ctx) -> parse_nodes_loop(S, Ctx, []). -file("src/kdleam/parse.gleam", 48). ?DOC(false). -spec finish_version_marker(kdleam@scanner:scanner()) -> {ok, kdleam@scanner:scanner()} | {error, kdleam@error:kdl_error()}. finish_version_marker(S) -> case kdleam@scanner:peek(S) of {some, <<"2"/utf8>>} -> {_, After_version} = kdleam@scanner:advance(S), gleam@result:'try'( kdleam@comment:skip_ws(After_version), fun(After_ws) -> case kdleam@scanner:peek(After_ws) of none -> {ok, After_ws}; {some, Ch} -> case kdleam@scanner:is_newline(Ch) of true -> {_, After_newline} = kdleam@scanner:consume_newline( After_ws ), {ok, After_newline}; false -> {error, kdleam@scanner:make_error( After_ws, {unexpected_char, Ch} )} end end end ); {some, Ch@1} -> {error, kdleam@scanner:make_error(S, {unexpected_char, Ch@1})}; none -> {error, kdleam@scanner:make_error(S, unexpected_eof)} end. -file("src/kdleam/parse.gleam", 26). ?DOC(false). -spec skip_version_marker(kdleam@scanner:scanner()) -> {ok, kdleam@scanner:scanner()} | {error, kdleam@error:kdl_error()}. skip_version_marker(S) -> {Ok1, S1} = kdleam@scanner:consume_token(S, <<"/-"/utf8>>), case Ok1 of false -> {ok, S}; true -> gleam@result:'try'( kdleam@comment:skip_ws(S1), fun(S2) -> {Ok2, S3} = kdleam@scanner:consume_token( S2, <<"kdl-version"/utf8>> ), case Ok2 of false -> {ok, S}; true -> gleam@result:'try'( kdleam@comment:skip_node_space(S3), fun(Result) -> {Had_space, Version_start} = Result, case Had_space of true -> finish_version_marker(Version_start); false -> {ok, S} end end ) end end ) end. -file("src/kdleam/parse.gleam", 14). ?DOC(false). -spec parse(binary()) -> {ok, kdleam@document:kdl_document()} | {error, kdleam@error:kdl_error()}. parse(Input) -> S = begin _pipe = kdleam@scanner:new(Input), kdleam@scanner:skip_bom(_pipe) end, gleam@result:'try'( skip_version_marker(S), fun(S1) -> gleam@result:'try'( parse_nodes(S1, top_level), fun(Result) -> {Nodes, S2} = Result, gleam@result:'try'( kdleam@comment:skip_line_space(S2), fun(S3) -> case kdleam@scanner:peek(S3) of none -> {ok, {kdl_document, Nodes}}; {some, Ch} -> {error, kdleam@scanner:make_error( S3, {unexpected_char, Ch} )} end end ) end ) end ).