Skip to content

Commit

Permalink
Handle parsing of reserved erlang terms
Browse files Browse the repository at this point in the history
  • Loading branch information
expelledboy committed Nov 16, 2023
1 parent a7658eb commit 6f6d211
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 7 deletions.
59 changes: 55 additions & 4 deletions src/erl2json.erl
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,6 @@ encode_nested(Map) when is_map(Map) ->
%% --

abstract_to_json({json, Type, Value}) ->
% io:format("abstract_to_json: ~p~n", [{json, Type, Value}]),
case Type of
atom -> wrap("atom", format("\"~s\"", [Value]));
boolean -> wrap("boolean", Value);
Expand Down Expand Up @@ -144,7 +143,11 @@ tuple_to_json(Tuple) ->
from_string(Str) when is_binary(Str) ->
from_string(binary_to_list(Str));
from_string(Str) when is_list(Str) ->
abstract_to_json(encode(eval_erl(pre_encode(Str)))).
abstract_to_json(
encode(
eval_erl(pre_encode(Str))
)
).

%% --

Expand Down Expand Up @@ -173,7 +176,7 @@ pre_encode_pids(Str) when is_list(Str) ->
re:replace(Str, "(<[0-9]+\.[0-9]+\.[0-9]+>)", "{pid,\"\\1\"}", [{return, list}, global]).

pre_encode_r26_pids(Str) when is_list(Str) ->
re:replace(Str, "(<.*@.*\.[0-9]+\.[0-9]+>)", "{pid,\"\\1\"}", [{return, list}, global]).
re:replace(Str, "(<.*@.*\.[0-9]+\.[0-9]+>)", "{pid,\"\\1\"}", [{return, list}, global]).

pre_encode_bit_strings(Str) when is_list(Str) ->
re:replace(Str, "<<([0-9 ,]*)>>", "{bit_string,[\\1]}", [{return, list}, global]).
Expand All @@ -185,9 +188,57 @@ pre_encode(Str) ->
fun pre_encode_bit_strings/1
]).

%% --

is_reserved(K) ->
lists:member(K, [
'after',
'and',
'andalso',
'band',
'begin',
'bnot',
'bor',
'bsl',
'bsr',
'bxor',
'case',
'catch',
'cond',
'div',
'end',
'fun',
'if',
'let',
'maybe',
'not',
'of',
'or',
'orelse',
'receive',
'rem',
'try',
'when',
'xor'
]).
unreserve(Form = {Reserved, LineNr}) when is_atom(Reserved) ->
case is_reserved(Reserved) of
true ->
{'atom', LineNr, Reserved};
false ->
Form
end;
unreserve(Form = {_F, _LineNr}) ->
Form;
unreserve({Type, Value, _LineNr}) ->
{Type, Value, _LineNr}.

%% --

eval_erl(Expression) when is_list(Expression) ->
{ok, Tokens, _} = erl_scan:string(format("~s.", [Expression])),
{ok, Parsed} = erl_parse:parse_exprs(Tokens),
UnreservedTokens = [unreserve(T) || T <- Tokens],
{ok, Parsed} = erl_parse:parse_exprs(UnreservedTokens),
{value, Result, _} = erl_eval:exprs(Parsed, []),
Result.

Expand Down
9 changes: 7 additions & 2 deletions test/fixture/complex_erlang_object.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,13 @@
},
{
"type": "tuple",
"record":"erlang_26_pid",
"values": [{ "type": "pid", "value": "<core1@alpha.local.1775.0>"}]
"record": "erlang_26_pid",
"values": [{ "type": "pid", "value": "<core1@alpha.local.1775.0>" }]
},
{
"type": "tuple",
"record": "reserved_words",
"values": [{ "type": "atom", "value": "receive" }]
}
]
]
Expand Down
3 changes: 2 additions & 1 deletion test/fixture/complex_erlang_object.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@
{my_record, "STRING", <7217.891.0>, undefined, 0, false, [{key1, "value"}, {key2, 123}]},
{"data", 1234, undefined},
#{<<"key1">> => <<"value">>, <<"key2">> => <<2>>},
{erlang_26_pid, <core1@alpha.local.1775.0>}
{erlang_26_pid, <core1@alpha.local.1775.0>},
{reserved_words, receive}
]}

0 comments on commit 6f6d211

Please sign in to comment.