Packages

JSX-like syntax for gleam

Current section

Files

Jump to
gleamx src gleamx@parser.erl
Raw

src/gleamx@parser.erl

-module(gleamx@parser).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/gleamx/parser.gleam").
-export([error_to_string/1, parse/1]).
-export_type([parsed/1]).
-type parsed(FSL) :: {parsed, binary(), FSL}.
-file("src/gleamx/parser.gleam", 215).
-spec parse_until_scan(binary(), list(binary())) -> binary().
parse_until_scan(Code, Syms) ->
case gleam@string:first(Code) of
{ok, Sym} ->
case gleam@list:contains(Syms, Sym) of
true ->
Code;
false ->
parse_until_scan(
begin
_pipe = Code,
gleam@string:drop_start(_pipe, 1)
end,
Syms
)
end;
_ ->
Code
end.
-file("src/gleamx/parser.gleam", 210).
-spec parse_until(binary(), list(binary())) -> parsed(binary()).
parse_until(Code, Syms) ->
New_code = parse_until_scan(Code, Syms),
{parsed,
New_code,
gleam@string:slice(
Code,
0,
string:length(Code) - string:length(New_code)
)}.
-file("src/gleamx/parser.gleam", 237).
-spec syntax_error(binary(), gleamx@lineinfo:code_meta(), binary()) -> gleamx@ast:syntax_error().
syntax_error(Code, Meta, Msg) ->
{syntax_error, gleamx@lineinfo:line_info(Code, Meta), Msg}.
-file("src/gleamx/parser.gleam", 191).
-spec parse_block_scan(
binary(),
gleamx@lineinfo:code_meta(),
binary(),
binary(),
integer()
) -> {ok, binary()} | {error, gleamx@ast:syntax_error()}.
parse_block_scan(Code, Meta, Open, Close, Depth) ->
Rest = gleam@string:drop_start(Code, 1),
case gleam@string:first(Code) of
{error, _} ->
{error,
syntax_error(
Rest,
Meta,
<<"unexpected EOF before closing the block"/utf8>>
)};
{ok, X} when X =:= Open ->
parse_block_scan(Rest, Meta, Open, Close, Depth + 1);
{ok, X@1} when (X@1 =:= Close) andalso (Depth > 1) ->
parse_block_scan(Rest, Meta, Open, Close, Depth - 1);
{ok, X@2} when X@2 =:= Close ->
{ok, Rest};
_ ->
parse_block_scan(Rest, Meta, Open, Close, Depth)
end.
-file("src/gleamx/parser.gleam", 178).
-spec parse_block(binary(), gleamx@lineinfo:code_meta(), binary(), binary()) -> {ok,
parsed(binary())} |
{error, gleamx@ast:syntax_error()}.
parse_block(Code, Meta, Open, Close) ->
gleam@result:'try'(
parse_block_scan(Code, Meta, Open, Close, 0),
fun(New_code) ->
{ok,
{parsed,
New_code,
gleam@string:slice(
Code,
0,
string:length(Code) - string:length(New_code)
)}}
end
).
-file("src/gleamx/parser.gleam", 241).
-spec error_to_string(gleamx@ast:syntax_error()) -> binary().
error_to_string(Error) ->
erlang:element(3, Error).
-file("src/gleamx/parser.gleam", 246).
-spec map_parse_result(
{ok, parsed(FTL)} | {error, gleamx@ast:syntax_error()},
fun((FTL) -> FTP)
) -> {ok, parsed(FTP)} | {error, gleamx@ast:syntax_error()}.
map_parse_result(Res, F) ->
case Res of
{ok, {parsed, Code, Value}} ->
{ok, {parsed, Code, F(Value)}};
{error, E} ->
{error, E}
end.
-file("src/gleamx/parser.gleam", 226).
-spec skip_spaces(binary()) -> binary().
skip_spaces(Code) ->
case gleam@string:first(Code) of
{ok, Sym} ->
case gleam@list:contains(
[<<" "/utf8>>, <<"\t"/utf8>>, <<"\n"/utf8>>, <<"\r"/utf8>>],
Sym
) of
true ->
skip_spaces(
begin
_pipe = Code,
gleam@string:drop_start(_pipe, 1)
end
);
false ->
Code
end;
_ ->
Code
end.
-file("src/gleamx/parser.gleam", 140).
-spec parse_args(binary(), gleamx@lineinfo:code_meta()) -> {ok,
parsed(list(gleamx@ast:arg()))} |
{error, gleamx@ast:syntax_error()}.
parse_args(Code, Meta) ->
Code@1 = skip_spaces(Code),
case gleam@string:first(Code@1) of
{ok, <<">"/utf8>>} ->
{ok, {parsed, Code@1, []}};
{ok, <<"/"/utf8>>} ->
{ok, {parsed, Code@1, []}};
_ ->
{parsed, Code@2, Name} = parse_until(
Code@1,
[<<"="/utf8>>,
<<"/"/utf8>>,
<<">"/utf8>> |
[<<" "/utf8>>, <<"\t"/utf8>>, <<"\n"/utf8>>, <<"\r"/utf8>>]]
),
Code@3 = skip_spaces(Code@2),
case Code@3 of
<<"="/utf8, Code@4/binary>> ->
Code@5 = skip_spaces(Code@4),
case Code@5 of
<<"\""/utf8, Code@6/binary>> ->
{parsed, Code@7, Value} = parse_until(
Code@6,
[<<"\""/utf8>>]
),
_pipe = parse_args(Code@7, Meta),
map_parse_result(
_pipe,
fun(Args) ->
[{lit_arg,
gleamx@lineinfo:line_info(
Code@7,
Meta
),
Name,
Value} |
Args]
end
);
<<"{"/utf8, _/binary>> ->
gleam@result:'try'(
parse_block(
Code@5,
Meta,
<<"{"/utf8>>,
<<"}"/utf8>>
),
fun(_use0) ->
{parsed, Code@8, Value@1} = _use0,
_pipe@1 = parse_args(Code@8, Meta),
map_parse_result(
_pipe@1,
fun(Args@1) ->
[{expr_arg,
gleamx@lineinfo:line_info(
Code@8,
Meta
),
Name,
Value@1} |
Args@1]
end
)
end
);
_ ->
{error,
syntax_error(
Code@5,
Meta,
<<"invalid argument value"/utf8>>
)}
end;
_ ->
parse_args(Code@3, Meta)
end
end.
-file("src/gleamx/parser.gleam", 112).
-spec parse_children(binary(), binary(), gleamx@lineinfo:code_meta()) -> {ok,
parsed(list(gleamx@ast:ast()))} |
{error, gleamx@ast:syntax_error()}.
parse_children(Code, Parent_tag, Meta) ->
Code@1 = skip_spaces(Code),
case Code@1 of
<<"</"/utf8, Code@2/binary>> ->
Code@3 = skip_spaces(Code@2),
{parsed, Code@4, Tag} = parse_until(Code@3, [<<">"/utf8>>]),
case Tag =:= Parent_tag of
false ->
{error,
syntax_error(
Code@4,
Meta,
<<"closing tag doesn't match opened tag"/utf8>>
)};
true ->
{ok, {parsed, gleam@string:drop_start(Code@4, 1), []}}
end;
_ ->
gleam@result:'try'(
parse_element(Code@1, Meta),
fun(_use0) ->
{parsed, Code@5, Element} = _use0,
gleam@result:'try'(
parse_children(Code@5, Parent_tag, Meta),
fun(_use0@1) ->
{parsed, Code@6, Rest} = _use0@1,
{ok, {parsed, Code@6, [Element | Rest]}}
end
)
end
)
end.
-file("src/gleamx/parser.gleam", 37).
-spec parse_element(binary(), gleamx@lineinfo:code_meta()) -> {ok,
parsed(gleamx@ast:ast())} |
{error, gleamx@ast:syntax_error()}.
parse_element(Code, Meta) ->
Code@1 = skip_spaces(Code),
case Code@1 of
<<""/utf8>> ->
{error, syntax_error(Code@1, Meta, <<"unexpected EOF"/utf8>>)};
<<"<"/utf8, Code@2/binary>> ->
Code@3 = skip_spaces(Code@2),
Pos = gleamx@lineinfo:line_info(Code@3, Meta),
{parsed, Code@4, Tag} = parse_until(
Code@3,
[<<"/"/utf8>>,
<<">"/utf8>> |
[<<" "/utf8>>, <<"\t"/utf8>>, <<"\n"/utf8>>, <<"\r"/utf8>>]]
),
gleam@result:'try'(
parse_args(Code@4, Meta),
fun(_use0) ->
{parsed, Code@5, Args} = _use0,
Code@6 = skip_spaces(Code@5),
case Code@6 of
<<"/>"/utf8, Code@7/binary>> ->
{ok,
{parsed,
Code@7,
{container_element, Pos, Tag, Args, []}}};
<<">"/utf8, Code@8/binary>> ->
case gleam@list:contains(
[<<"area"/utf8>>,
<<"base"/utf8>>,
<<"br"/utf8>>,
<<"col"/utf8>>,
<<"embed"/utf8>>,
<<"hr"/utf8>>,
<<"img"/utf8>>,
<<"input"/utf8>>,
<<"link"/utf8>>,
<<"meta"/utf8>>,
<<"param"/utf8>>,
<<"source"/utf8>>,
<<"track"/utf8>>,
<<"wbr"/utf8>>],
Tag
) of
true ->
{ok,
{parsed,
Code@8,
{void_element, Pos, Tag, Args}}};
false ->
_pipe = parse_children(Code@8, Tag, Meta),
map_parse_result(
_pipe,
fun(Children) ->
{container_element,
gleamx@lineinfo:line_info(
Code@8,
Meta
),
Tag,
Args,
Children}
end
)
end;
_ ->
{error,
syntax_error(
Code@6,
Meta,
<<"expected '>' or '/>'"/utf8>>
)}
end
end
);
<<".."/utf8, Code@9/binary>> ->
_pipe@1 = parse_element(Code@9, Meta),
map_parse_result(
_pipe@1,
fun(Children@1) ->
{spread,
gleamx@lineinfo:line_info(Code@9, Meta),
Children@1}
end
);
<<"{"/utf8, _/binary>> ->
_pipe@2 = parse_block(Code@1, Meta, <<"{"/utf8>>, <<"}"/utf8>>),
map_parse_result(
_pipe@2,
fun(Gleam_code) ->
{code_block,
gleamx@lineinfo:line_info(Code@1, Meta),
Gleam_code}
end
);
_ ->
{parsed, Code@10, Name} = parse_until(
Code@1,
[<<"("/utf8>> |
[<<" "/utf8>>, <<"\t"/utf8>>, <<"\n"/utf8>>, <<"\r"/utf8>>]]
),
case Code@10 of
<<"("/utf8, _/binary>> ->
_pipe@3 = parse_block(
Code@10,
Meta,
<<"("/utf8>>,
<<")"/utf8>>
),
map_parse_result(
_pipe@3,
fun(Params) ->
{code_block,
gleamx@lineinfo:line_info(Code@10, Meta),
<<Name/binary, Params/binary>>}
end
);
_ ->
{ok,
{parsed,
Code@10,
{code_block,
gleamx@lineinfo:line_info(Code@10, Meta),
Name}}}
end
end.
-file("src/gleamx/parser.gleam", 17).
-spec parse_loop(binary(), gleamx@lineinfo:code_meta()) -> {ok,
list(gleamx@ast:chunk())} |
{error, gleamx@ast:syntax_error()}.
parse_loop(Code, Meta) ->
Pos = gleamx@lineinfo:line_info(Code, Meta),
Rest = gleam_stdlib:crop_string(Code, <<"<?"/utf8>>),
case string:length(Rest) =:= string:length(Code) of
true ->
{ok, [{gleam_code, Pos, Code}]};
false ->
Gleam_code = gleam@string:slice(
Code,
0,
string:length(Code) - string:length(Rest)
),
gleam@result:'try'(
begin
_pipe = Rest,
_pipe@1 = gleam@string:drop_start(_pipe, 2),
parse_element(_pipe@1, Meta)
end,
fun(_use0) ->
{parsed, Code@1, Glx_ast} = _use0,
gleam@result:'try'(
parse_loop(Code@1, Meta),
fun(Rest@1) ->
{ok,
[{gleam_code, Pos, Gleam_code},
{glx_code, Glx_ast} |
Rest@1]}
end
)
end
)
end.
-file("src/gleamx/parser.gleam", 13).
-spec parse(binary()) -> {ok, list(gleamx@ast:chunk())} |
{error, gleamx@ast:syntax_error()}.
parse(Code) ->
parse_loop(Code, gleamx@lineinfo:analyze_code(Code)).