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@parser.erl
Raw

src/handles@internal@parser.erl

-module(handles@internal@parser).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]).
-export([run/1]).
-export_type([ast/0, parse_result/0]).
-type ast() :: {constant, integer(), binary()} |
{property, integer(), list(binary())} |
{partial, integer(), binary(), list(binary())} |
{block,
integer(),
integer(),
handles@internal@block:kind(),
list(binary()),
list(ast())}.
-type parse_result() :: {eof, list(ast())} |
{block_end,
integer(),
handles@internal@block:kind(),
list(ast()),
list(handles@internal@tokenizer:token())}.
-spec parse(list(handles@internal@tokenizer:token()), list(ast())) -> {ok,
parse_result()} |
{error, handles@error:tokenizer_error()}.
parse(Tokens, Ast) ->
case Tokens of
[] ->
{ok, {eof, lists:reverse(Ast)}};
[{block_end, Index, Kind} | Tail] ->
{ok, {block_end, Index, Kind, lists:reverse(Ast), Tail}};
[{constant, Index@1, Value} | Tail@1] ->
parse(Tail@1, [{constant, Index@1, Value} | Ast]);
[{property, Index@2, Path} | Tail@2] ->
parse(Tail@2, [{property, Index@2, Path} | Ast]);
[{partial, Index@3, Id, Value@1} | Tail@3] ->
parse(Tail@3, [{partial, Index@3, Id, Value@1} | Ast]);
[{block_start, Start_index, Start_kind, Path@1} | Tail@4] ->
case parse(Tail@4, []) of
{error, Err} ->
{error, Err};
{ok, {eof, _}} ->
{error, {unbalanced_block, Start_index}};
{ok, {block_end, End_index, End_kind, Children, Rest}} when End_kind =:= Start_kind ->
parse(
Rest,
[{block,
Start_index,
End_index,
Start_kind,
Path@1,
Children} |
Ast]
);
{ok, {block_end, Index@4, _, _, _}} ->
{error, {unexpected_block_end, Index@4}}
end
end.
-spec run(list(handles@internal@tokenizer:token())) -> {ok, list(ast())} |
{error, handles@error:tokenizer_error()}.
run(Tokens) ->
_pipe = parse(Tokens, []),
gleam@result:'try'(_pipe, fun(It) -> case It of
{eof, Ast} ->
{ok, Ast};
{block_end, Index, _, _, _} ->
{error, {unexpected_block_end, Index}}
end end).