Current section

Files

Jump to
erlang_behaviour_trees src bt_engine yaml_parser yaml_parser_utils.erl
Raw

src/bt_engine/yaml_parser/yaml_parser_utils.erl

-module(yaml_parser_utils).
-export([
read_file/1,
get_decorator/2,
get_decorators/2,
get_context/3,
parse_args/2
]).
-include("bt_nodes.hrl").
%% convert yaml file to dictionary
%% TODO: parse in detailed mode so better errors can be reported, which include line numbers
read_file(YAMLFilePath) ->
[YAMLList] = yamerl_constr:file(YAMLFilePath),
maps:from_list(YAMLList).
%% merge local bb keys with rest of context
%% local bb key => get_bb_key(local bb key)
get_context(Context, _Namespace, []) ->
Context;
get_context(PartialContext, Namespace, [LocalBBKey | Rest]) ->
NewPartialContext = maps:put(LocalBBKey, bt_blackboard:get_bb_key(Namespace, LocalBBKey), PartialContext),
get_context(NewPartialContext, Namespace, Rest).
get_decorator(DecoratorList, Context) ->
Module = proplists:get_value("module", DecoratorList),
UnparsedArgs = proplists:get_value("args", DecoratorList),
Name = proplists:get_value("name", DecoratorList, Module),
% Params = proplists:get_value("params", DecoratorList, []),
ModuleAtom = list_to_atom(Module),
Params = ModuleAtom:get_params(),
bt_parser_utils:throw_error_if_args_and_params_dont_match(Module, UnparsedArgs, Params),
ArgsAsMap = parse_args(UnparsedArgs, Context),
#decorator{
name = Name,
module = ModuleAtom,
args = ArgsAsMap
}.
get_decorators(undefined, _Context) ->
[];
get_decorators(DecoratorsList, Context) ->
[get_decorator(DecoratorList, Context) || DecoratorList <- DecoratorsList].
parse_args(Args, Context) ->
parse_args(Args, #{}, Context).
parse_args([], NewContext, _Context) ->
NewContext;
parse_args([{ArgKey, ArgVal} | Rest], NewContext, Context) ->
%% check if arg val is in context; if so, then replace.
ValToPut = parse_argval(ArgVal, Context),
NewNewContext = maps:put(ArgKey, ValToPut, NewContext),
parse_args(Rest, NewNewContext, Context).
parse_argval(ArgVal, Context) ->
case maps:is_key(ArgVal, Context) of
true -> maps:get(ArgVal, Context);
false -> parse_argval_basic(ArgVal, Context)
end.
%% can be deeply nested!
%% flawed logic because can't really detect if a list is string or not... but maybe don't need to?
parse_argval_basic(ArgVal, _Context) when is_atom(ArgVal); is_number(ArgVal); is_binary(ArgVal) ->
ArgVal;
parse_argval_basic(ArgVal, Context) when is_tuple(ArgVal) ->
%% split
L = tuple_to_list(ArgVal),
list_to_tuple(parse_argval_basic(L, Context));
parse_argval_basic(ArgVal, Context) when is_list(ArgVal) ->
[parse_argval(X, Context) || X <- ArgVal].