Packages

Handles is a templating language written in pure Gleam. Heavily inspired by Mustache and Handlebars.js

Current section

Files

Jump to
handles src handles@internal@tokenizer.erl
Raw

src/handles@internal@tokenizer.erl

-module(handles@internal@tokenizer).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]).
-export([run/3]).
-export_type([token/0]).
-type token() :: {constant, integer(), binary()} |
{property, integer(), list(binary())} |
{partial, integer(), binary(), list(binary())} |
{if_block_start, integer(), list(binary())} |
{if_block_end, integer()} |
{unless_block_start, integer(), list(binary())} |
{unless_block_end, integer()} |
{each_block_start, integer(), list(binary())} |
{each_block_end, integer()}.
-spec split_body(binary()) -> list(binary()).
split_body(Body) ->
_pipe = Body,
_pipe@1 = gleam@string:trim(_pipe),
_pipe@2 = gleam@string:split(_pipe@1, <<" "/utf8>>),
gleam@list:filter(
_pipe@2,
fun(It) ->
begin
_pipe@3 = It,
_pipe@4 = gleam@string:trim(_pipe@3),
gleam@string:length(_pipe@4)
end
> 0
end
).
-spec split_arg(binary()) -> list(binary()).
split_arg(Arg) ->
case begin
_pipe = Arg,
gleam@string:trim(_pipe)
end of
<<"."/utf8>> ->
[];
Arg@1 ->
gleam@string:split(Arg@1, <<"."/utf8>>)
end.
-spec capture_tag_body(binary(), integer()) -> {ok, {binary(), binary()}} |
{error, handles@error:tokenizer_error()}.
capture_tag_body(Input, Index) ->
_pipe = Input,
_pipe@1 = gleam@string:split_once(_pipe, <<"}}"/utf8>>),
gleam@result:map_error(_pipe@1, fun(_) -> {unbalanced_tag, Index + 2} end).
-spec run(binary(), integer(), list(token())) -> {ok, list(token())} |
{error, handles@error:tokenizer_error()}.
run(Input, Index, Tokens) ->
case Input of
<<"{{>"/utf8, Rest/binary>> ->
gleam@result:'try'(
capture_tag_body(Rest, Index),
fun(_use0) ->
{Body, Rest@1} = _use0,
case split_body(Body) of
[] ->
{error, {missing_partial_id, Index + 2}};
[_] ->
{error, {missing_argument, Index + 2}};
[Id, Arg] ->
run(
Rest@1,
(Index + gleam@string:length(<<"{{>}}"/utf8>>))
+ gleam@string:length(Body),
[{partial, Index + 2, Id, split_arg(Arg)} |
Tokens]
);
_ ->
{error, {unexpected_multiple_arguments, Index + 2}}
end
end
);
<<"{{#"/utf8, Rest@2/binary>> ->
gleam@result:'try'(
capture_tag_body(Rest@2, Index),
fun(_use0@1) ->
{Body@1, Rest@3} = _use0@1,
case split_body(Body@1) of
[] ->
{error, {missing_block_kind, Index + 2}};
[_] ->
{error, {missing_argument, Index + 2}};
[Kind, Arg@1] ->
case Kind of
<<"if"/utf8>> ->
run(
Rest@3,
(Index + 5) + gleam@string:length(
Body@1
),
[{if_block_start,
Index + 2,
split_arg(Arg@1)} |
Tokens]
);
<<"unless"/utf8>> ->
run(
Rest@3,
(Index + 5) + gleam@string:length(
Body@1
),
[{unless_block_start,
Index + 2,
split_arg(Arg@1)} |
Tokens]
);
<<"each"/utf8>> ->
run(
Rest@3,
(Index + 5) + gleam@string:length(
Body@1
),
[{each_block_start,
Index + 2,
split_arg(Arg@1)} |
Tokens]
);
_ ->
{error, {unexpected_block_kind, Index}}
end;
_ ->
{error, {unexpected_multiple_arguments, Index + 2}}
end
end
);
<<"{{/"/utf8, Rest@4/binary>> ->
gleam@result:'try'(
capture_tag_body(Rest@4, Index),
fun(_use0@2) ->
{Body@2, Rest@5} = _use0@2,
case split_body(Body@2) of
[] ->
{error, {missing_block_kind, Index + 2}};
[_, _] ->
{error, {unexpected_argument, Index + 2}};
[Kind@1] ->
case Kind@1 of
<<"if"/utf8>> ->
run(
Rest@5,
(Index + 5) + gleam@string:length(
Body@2
),
[{if_block_end, Index + 2} | Tokens]
);
<<"unless"/utf8>> ->
run(
Rest@5,
(Index + 5) + gleam@string:length(
Body@2
),
[{unless_block_end, Index + 2} | Tokens]
);
<<"each"/utf8>> ->
run(
Rest@5,
(Index + 5) + gleam@string:length(
Body@2
),
[{each_block_end, Index + 2} | Tokens]
);
_ ->
{error, {unexpected_block_kind, Index}}
end;
_ ->
{error, {unexpected_argument, Index + 2}}
end
end
);
<<"{{"/utf8, Rest@6/binary>> ->
gleam@result:'try'(
capture_tag_body(Rest@6, Index),
fun(_use0@3) ->
{Body@3, Rest@7} = _use0@3,
case split_body(Body@3) of
[] ->
{error, {missing_argument, Index + 2}};
[Arg@2] ->
run(
Rest@7,
(Index + 4) + gleam@string:length(Body@3),
[{property, Index + 2, split_arg(Arg@2)} |
Tokens]
);
_ ->
{error, {unexpected_multiple_arguments, Index + 2}}
end
end
);
_ ->
case begin
_pipe = Input,
gleam@string:split_once(_pipe, <<"{{"/utf8>>)
end of
{ok, {Str, Rest@8}} ->
run(
<<"{{"/utf8, Rest@8/binary>>,
Index + gleam@string:length(Str),
[{constant, Index, Str} | Tokens]
);
_ ->
case Input of
<<""/utf8>> ->
{ok, lists:reverse(Tokens)};
Str@1 ->
{ok,
lists:reverse(
[{constant, Index, Str@1} | Tokens]
)}
end
end
end.