Map parsing

This commit is contained in:
Jarvis Carroll 2026-01-16 05:46:27 +00:00
parent 3f1c9bd626
commit 56e63051bc

View File

@ -100,9 +100,26 @@ parse_expression2(Type, Tk, String, {integer, S, Row, Start, End}) ->
end;
parse_expression2(Type, Tk, String, {character, "[", Row, Start, _}) ->
parse_list(Type, Tk, String, Row, Start);
parse_expression2(Type, Tk, String, {character, "{", Row, Start, _}) ->
parse_record_or_map(Type, Tk, String, Row, Start);
parse_expression2(_, _, _, {_, S, Row, Start, End}) ->
{error, {unexpected_token, S, Row, Start, End}}.
unknown_type() ->
{unknown_type, already_normalized, unknown_type}.
expect_tokens([], Tk, String) ->
{ok, {Tk, String}};
expect_tokens([Str | Rest], Tk, String) ->
case next_token(Tk, String) of
{ok, {{_, Str, _, _, _}, NewTk, NewString}} ->
expect_tokens(Rest, NewTk, NewString);
{ok, {{_, Actual, Row, Start, End}}} ->
{error, {unexpected_token, Actual, Row, Start, End}}
end.
%%% List Parsing
parse_list({_, _, {list, [Inner]}}, Tk, String, Row, Start) ->
parse_list_loop(Inner, Tk, String, Row, Start, []);
parse_list({_, _, unknown_type}, Tk, String, Row, Start) ->
@ -137,8 +154,75 @@ parse_list_loop3(Inner, Tk, String, Row, Start, Acc) ->
{error, Reason}
end.
unknown_type() ->
{unknown_type, already_normalized, unknown_type}.
%%% Record parsing
parse_record_or_map({_, _, {map, [KeyType, ValueType]}}, Tk, String, _, _) ->
parse_map(KeyType, ValueType, Tk, String, #{});
parse_record_or_map({_, _, {record, Fields}}, Tk, String, _, _) ->
parse_record(Fields, Tk, String);
parse_record_or_map({_, _, unknown_type}, Tk, String, _, _) ->
case next_token(Tk, String) of
{ok, {{character, "}", _, _, _}, NewTk, NewString}} ->
{ok, {#{}, NewTk, NewString}};
{ok, {{character, "[", _, _, _}, NewTk, NewString}} ->
parse_map2(unknown_type(), unknown_type(), NewTk, NewString, #{});
{ok, {{alphanum, _, Row, Start, End}, _, _}} ->
{error, {unresolved_record, Row, Start, End}};
{ok, {{_, S, Row, Start, End}, _, _}} ->
{error, {unexpected_token, S, Row, Start, End}}
end;
parse_record_or_map({O, N, _}, _, _, Row, Start) ->
{error, {wrong_type, O, N, map, Row, Start, Start}}.
parse_record(Fields, Tk, String) ->
{error, not_yet_implemented}.
%%% Map Parsing
parse_map(KeyType, ValueType, Tk, String, Acc) ->
case next_token(Tk, String) of
{ok, {{character, "[", _, _, _}, NewTk, NewString}} ->
parse_map2(KeyType, ValueType, NewTk, NewString, Acc);
{ok, {{character, "}", _, _, _}, NewTk, NewString}} ->
{ok, {Acc, NewTk, NewString}};
{ok, {{_, S, Row, Start, End}}} ->
{error, {unexpected_token, S, Row, Start, End}}
end.
parse_map2(KeyType, ValueType, Tk, String, Acc) ->
case parse_expression(KeyType, Tk, String) of
{ok, {Result, NewTk, NewString}} ->
parse_map3(KeyType, ValueType, NewTk, NewString, Acc, Result);
{error, Reason} ->
wrap_error(Reason, {map_key, maps:size(Acc)})
end.
parse_map3(KeyType, ValueType, Tk, String, Acc, Key) ->
case expect_tokens(["]", "="], Tk, String) of
{ok, {NewTk, NewString}} ->
parse_map4(KeyType, ValueType, NewTk, NewString, Acc, Key);
{error, Reason} ->
{error, Reason}
end.
parse_map4(KeyType, ValueType, Tk, String, Acc, Key) ->
case parse_expression(ValueType, Tk, String) of
{ok, {Result, NewTk, NewString}} ->
NewAcc = maps:put(Key, Result, Acc),
parse_map5(KeyType, ValueType, NewTk, NewString, NewAcc);
{error, Reason} ->
{error, Reason}
end.
parse_map5(KeyType, ValueType, Tk, String, Acc) ->
case next_token(Tk, String) of
{ok, {{character, ",", _, _, _}, NewTk, NewString}} ->
parse_map(KeyType, ValueType, NewTk, NewString, Acc);
{ok, {{character, "}", _, _, _}, NewTk, NewString}} ->
{ok, {Acc, NewTk, NewString}};
{ok, {{_, S, Row, Start, End}}} ->
{error, {unexpected_token, S, Row, Start, End}}
end.
% TODO
wrap_error(Reason, _) -> Reason.
@ -175,3 +259,9 @@ int_test() ->
list_test() ->
check_parser("[1, 2, 3]", [1, 2, 3]).
list_of_lists_test() ->
check_parser("[[], [1], [2, 3]]", [[], [1], [2, 3]]).
maps_test() ->
check_parser("{[1] = 2, [3] = 4}", #{1 => 2, 3 => 4}).