-module(handles@internal@tokenizer). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). -export([do_run/3, run/1]). -export_type([token/0, action/0]). -type token() :: {constant, integer(), binary()} | {property, integer(), list(binary())} | {partial, integer(), binary(), list(binary())} | {block_start, integer(), handles@internal@block:kind(), list(binary())} | {block_end, integer(), handles@internal@block:kind()}. -type action() :: {add_token, binary(), integer(), token()} | {stop, handles@error:tokenizer_error()} | done. -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 tokenize(binary(), integer()) -> action(). tokenize(Input, Index) -> case Input of <<""/utf8>> -> done; <<"{{>"/utf8, Rest/binary>> -> case capture_tag_body(Rest, Index) of {error, Err} -> {stop, Err}; {ok, {Body, Rest@1}} -> case split_body(Body) of [] -> {stop, {missing_partial_id, Index + 2}}; [_] -> {stop, {missing_argument, Index + 2}}; [Id, Arg] -> {add_token, Rest@1, (Index + 5) + gleam@string:length(Body), {partial, Index + 2, Id, split_arg(Arg)}}; _ -> {stop, {unexpected_multiple_arguments, Index + 2}} end end; <<"{{#"/utf8, Rest@2/binary>> -> case capture_tag_body(Rest@2, Index) of {error, Err@1} -> {stop, Err@1}; {ok, {Body@1, Rest@3}} -> case split_body(Body@1) of [] -> {stop, {missing_block_kind, Index + 2}}; [_] -> {stop, {missing_argument, Index + 2}}; [<<"if"/utf8>>, Arg@1] -> {add_token, Rest@3, (Index + 5) + gleam@string:length(Body@1), {block_start, Index + 2, 'if', split_arg(Arg@1)}}; [<<"unless"/utf8>>, Arg@2] -> {add_token, Rest@3, (Index + 5) + gleam@string:length(Body@1), {block_start, Index + 2, unless, split_arg(Arg@2)}}; [<<"each"/utf8>>, Arg@3] -> {add_token, Rest@3, (Index + 5) + gleam@string:length(Body@1), {block_start, Index + 2, each, split_arg(Arg@3)}}; [_, _] -> {stop, {unexpected_block_kind, Index + 2}}; _ -> {stop, {unexpected_multiple_arguments, Index + 2}} end end; <<"{{/"/utf8, Rest@4/binary>> -> case capture_tag_body(Rest@4, Index) of {error, Err@2} -> {stop, Err@2}; {ok, {Body@2, Rest@5}} -> case split_body(Body@2) of [] -> {stop, {missing_block_kind, Index + 2}}; [_, _] -> {stop, {unexpected_argument, Index + 2}}; [<<"if"/utf8>>] -> {add_token, Rest@5, (Index + 5) + gleam@string:length(Body@2), {block_end, Index + 2, 'if'}}; [<<"unless"/utf8>>] -> {add_token, Rest@5, (Index + 5) + gleam@string:length(Body@2), {block_end, Index + 2, unless}}; [<<"each"/utf8>>] -> {add_token, Rest@5, (Index + 5) + gleam@string:length(Body@2), {block_end, Index + 2, each}}; [_] -> {stop, {unexpected_block_kind, Index + 2}}; _ -> {stop, {unexpected_argument, Index + 2}} end end; <<"{{"/utf8, Rest@6/binary>> -> case capture_tag_body(Rest@6, Index) of {error, Err@3} -> {stop, Err@3}; {ok, {Body@3, Rest@7}} -> case split_body(Body@3) of [] -> {stop, {missing_argument, Index + 2}}; [Arg@4] -> {add_token, Rest@7, (Index + 4) + gleam@string:length(Body@3), {property, Index + 2, split_arg(Arg@4)}}; _ -> {stop, {unexpected_multiple_arguments, Index + 2}} end end; _ -> case begin _pipe = Input, _pipe@1 = gleam@string:split_once(_pipe, <<"{{"/utf8>>), gleam@result:map( _pipe@1, fun(_capture) -> gleam@pair:map_second( _capture, fun(It) -> <<"{{"/utf8, It/binary>> end ) end ) end of {ok, {Str, Rest@8}} -> {add_token, Rest@8, Index + gleam@string:length(Str), {constant, Index, Str}}; _ -> {add_token, <<""/utf8>>, Index + gleam@string:length(Input), {constant, Index, Input}} end end. -spec do_run(binary(), integer(), list(token())) -> {ok, list(token())} | {error, handles@error:tokenizer_error()}. do_run(Input, Index, Tokens) -> case tokenize(Input, Index) of done -> {ok, lists:reverse(Tokens)}; {stop, Err} -> {error, Err}; {add_token, Rest, Index@1, Token} -> do_run(Rest, Index@1, [Token | Tokens]) end. -spec run(binary()) -> {ok, list(token())} | {error, handles@error:tokenizer_error()}. run(Input) -> do_run(Input, 0, []).