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