mirror of
https://github.com/KevinMidboe/linguist.git
synced 2025-10-29 09:40:21 +00:00
- some Erlang and escript files - .escript extension - .erlang extension - shell script with %, ##, name tokens
136 lines
6.3 KiB
Erlang
136 lines
6.3 KiB
Erlang
%% For each header file, it scans thru all records and create helper functions
|
|
%% Helper functions are:
|
|
%% setters, getters, fields, fields_atom, type
|
|
|
|
-module(record_helper).
|
|
|
|
-export([make/1, make/2]).
|
|
|
|
make(HeaderFiles) ->
|
|
make([ atom_to_list(X) || X <- HeaderFiles ], ".").
|
|
|
|
%% .hrl file, relative to current dir
|
|
make(HeaderFiles, OutDir) ->
|
|
ModuleName = "record_utils",
|
|
HeaderComment = "%% This is auto generated file. Please don't edit it\n\n",
|
|
ModuleDeclaration = "-module(" ++ ModuleName ++ ").\n"
|
|
++ "-author(\"trung@mdkt.org\").\n"
|
|
++ "-compile(export_all).\n"
|
|
++ [ "-include(\"" ++ X ++ "\").\n" || X <- HeaderFiles ]
|
|
++ "\n",
|
|
Src = format_src(lists:sort(lists:flatten([read(X) || X <- HeaderFiles] ++ [generate_type_default_function()]))),
|
|
file:write_file(OutDir++"/" ++ ModuleName ++ ".erl", list_to_binary([HeaderComment, ModuleDeclaration, Src])).
|
|
|
|
read(HeaderFile) ->
|
|
try epp:parse_file(HeaderFile,[],[]) of
|
|
{ok, Tree} ->
|
|
parse(Tree);
|
|
{error, Error} ->
|
|
{error, {"Error parsing header file", HeaderFile, Error}}
|
|
catch
|
|
_:Error ->
|
|
{catched_error, {"Error parsing header file", HeaderFile, Error}}
|
|
end.
|
|
|
|
format_src([{_, _, _, Src}|T]) when length(T) == 0 ->
|
|
Src ++ ".\n\n";
|
|
format_src([{Type, _, _, Src}|[{Type, A, B, NSrc}|T]]) ->
|
|
Src ++ ";\n\n" ++ format_src([{Type, A, B, NSrc}|T]);
|
|
format_src([{_Type, _, _, Src}|[{Type1, A, B, NSrc}|T]]) ->
|
|
Src ++ ".\n\n" ++ format_src([{Type1, A, B, NSrc}|T]);
|
|
format_src([{_, _, _, Src}|T]) when length(T) > 0 ->
|
|
Src ++ ";\n\n" ++ format_src(T).
|
|
|
|
parse(Tree) ->
|
|
[ parse_record(X) || X <- Tree ].
|
|
|
|
parse_record({attribute, _, record, RecordInfo}) ->
|
|
{RecordName, RecordFields} = RecordInfo,
|
|
if
|
|
length(RecordFields) == 1 ->
|
|
lists:flatten([ generate_setter_getter_function(RecordName, X) || X <- RecordFields ]
|
|
++ [generate_type_function(RecordName)]);
|
|
true ->
|
|
lists:flatten([generate_fields_function(RecordName, RecordFields)]
|
|
++ [generate_fields_atom_function(RecordName, RecordFields)]
|
|
++ [ generate_setter_getter_function(RecordName, X) || X <- RecordFields ]
|
|
++ [generate_type_function(RecordName)])
|
|
end;
|
|
parse_record(_) -> [].
|
|
|
|
parse_field_name({record_field, _, {atom, _, FieldName}}) ->
|
|
{field, "\"" ++ atom_to_list(FieldName) ++ "\""};
|
|
parse_field_name({record_field, _, {atom, _, _FieldName}, {record, _, ParentRecordName, _}}) ->
|
|
{parent_field, "fields(" ++ atom_to_list(ParentRecordName) ++ ")"};
|
|
parse_field_name({record_field, _, {atom, _, FieldName}, _}) ->
|
|
{field, "\"" ++ atom_to_list(FieldName) ++ "\""}.
|
|
|
|
parse_field_name_atom({record_field, _, {atom, _, FieldName}}) ->
|
|
atom_to_list(FieldName);
|
|
parse_field_name_atom({record_field, _, {atom, _, _FieldName}, {record, _, ParentRecordName, _}}) ->
|
|
"fields_atom(" ++ atom_to_list(ParentRecordName) ++ ")";
|
|
parse_field_name_atom({record_field, _, {atom, _, FieldName}, _}) ->
|
|
atom_to_list(FieldName).
|
|
|
|
concat([], _S) -> [];
|
|
concat([F|T], _S) when length(T) == 0 -> F;
|
|
concat([F|T], S) -> F ++ S ++ concat(T, S).
|
|
|
|
concat_ext([], _S) -> [];
|
|
concat_ext([F|T], S) -> F ++ S ++ concat_ext(T, S).
|
|
|
|
parse_field([], AccFields, AccParentFields) -> concat_ext(AccParentFields, " ++ ") ++ "[" ++ concat(AccFields, ", ") ++ "]";
|
|
%parse_field([F|T], AccFields, AccParentFields) when length(T) == 0 -> parse_field_name(F);
|
|
parse_field([F|T], AccFields, AccParentFields) ->
|
|
case parse_field_name(F) of
|
|
{field, Field} ->
|
|
parse_field(T, AccFields ++ [Field], AccParentFields);
|
|
{parent_field, PField} ->
|
|
parse_field(T, AccFields, AccParentFields ++ [PField])
|
|
end.
|
|
|
|
parse_field_atom([F|T]) when length(T) == 0 -> parse_field_name_atom(F);
|
|
parse_field_atom([F|T]) ->
|
|
parse_field_name_atom(F) ++ ", " ++ parse_field_atom(T).
|
|
|
|
generate_type_default_function() ->
|
|
{type, zzz, 99, "type(_) -> undefined"}.
|
|
|
|
generate_type_function(RecordName) ->
|
|
{type, RecordName, 0, "type(Obj) when is_record(Obj, " ++ atom_to_list(RecordName) ++ ") -> " ++ atom_to_list(RecordName)}.
|
|
|
|
generate_fields_function(RecordName, RecordFields) ->
|
|
Fields = parse_field(RecordFields, [], []),
|
|
{field, RecordName, 1, "fields(" ++ atom_to_list(RecordName) ++ ") -> \n\t" ++ Fields}.
|
|
|
|
generate_fields_atom_function(RecordName, RecordFields) ->
|
|
Fields = parse_field_atom(RecordFields),
|
|
{field_atom, RecordName, 1, "fields_atom(" ++ atom_to_list(RecordName) ++ ") -> \n\tlists:flatten([" ++ Fields ++ "])"}.
|
|
|
|
generate_setter_getter_function(RecordName, {record_field, _, {atom, _, FieldName}, {record, _, ParentRecordName, _}}) ->
|
|
to_setter_getter_function(atom_to_list(RecordName), atom_to_list(FieldName), atom_to_list(ParentRecordName));
|
|
generate_setter_getter_function(RecordName, {record_field, _, {atom, _, FieldName}, _}) ->
|
|
to_setter_getter_function(atom_to_list(RecordName), atom_to_list(FieldName));
|
|
generate_setter_getter_function(RecordName, {record_field, _, {atom, _, FieldName}}) ->
|
|
to_setter_getter_function(atom_to_list(RecordName), atom_to_list(FieldName)).
|
|
|
|
to_setter_getter_function(RecordName, FieldName) ->
|
|
[{setter, RecordName, 1, "set(Obj, " ++ FieldName ++ ", Value) when is_record(Obj, " ++ RecordName ++ ") -> \n"
|
|
++ "\tNewObj = Obj#" ++ RecordName ++ "{" ++ FieldName ++ " = Value},\n"
|
|
++ "\t{ok, NewObj, {" ++ FieldName ++ ", Value}}"},
|
|
{getter, RecordName, 1, "get(Obj, " ++ FieldName ++ ") when is_record(Obj, " ++ RecordName ++ ") -> \n"
|
|
++ "\t{ok, Obj#" ++ RecordName ++ "." ++ FieldName ++ "}"}
|
|
].
|
|
|
|
to_setter_getter_function(RecordName, FieldName, ParentRecordName) ->
|
|
[{setter, RecordName, 2, "set(Obj, " ++ FieldName ++ ", Value) when is_record(Obj, " ++ RecordName ++ ") and is_record(Value, " ++ ParentRecordName ++ ") -> \n"
|
|
++ "\tNewObj = Obj#" ++ RecordName ++ "{" ++ FieldName ++ " = Value},\n"
|
|
++ "\t{ok, NewObj, {" ++ FieldName ++ ", Value}};\n\n"
|
|
++ "set(Obj, ParentProperty, Value) when is_record(Obj, " ++ RecordName ++ ") and is_atom(ParentProperty) -> \n"
|
|
++ "\t{ok, NewParentObject, _} = set(Obj#" ++ RecordName ++ ".parent, ParentProperty, Value),\n"
|
|
++ "\tset(Obj, parent, NewParentObject)"},
|
|
{getter, RecordName, 2, "get(Obj, " ++ FieldName ++ ") when is_record(Obj, " ++ RecordName ++ ") -> \n"
|
|
++ "\t{ok, Obj#" ++ RecordName ++ "." ++ FieldName ++ "};\n\n"
|
|
++ "get(Obj, ParentProperty) when is_record(Obj, " ++ RecordName ++ ") and is_atom(ParentProperty) -> \n"
|
|
++ "\tget(Obj#" ++ RecordName ++ ".parent, ParentProperty)"}
|
|
]. |