Packages

KDL v2 parser, serializer, normalizer, and document builder for Gleam

Current section

Files

Jump to
kdleam src kdleam@parse.erl
Raw

src/kdleam@parse.erl

-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
).