Skip to content

Commit 3ef51f0

Browse files
committed
added $match(..) operator
1 parent 205e4b5 commit 3ef51f0

File tree

5 files changed

+301
-32
lines changed

5 files changed

+301
-32
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ At the time of writing, this library supports a minimum set of functionality of
4747
| $keys | Supported |
4848
| $length | Supported |
4949
| $map | Supported |
50+
| $match | Supported |
5051
| $millis | Supported - including the requirement that multiple calls produce the same value |
5152
| $now | Supported - including passing value, e.g., `$now($millis())` |
5253
| $pad | Supported |

src/erlang_red_jsonata.erl

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,58 @@ handle_local_function(
273273
[Str, Start, Len]
274274
) when is_binary(Str), is_integer(Start), is_integer(Len) ->
275275
handle_local_function(jsonata_substring, [binary_to_list(Str), Start, Len]);
276+
%% ---> $match(...)
277+
handle_local_function(
278+
jsonata_match,
279+
[Str, RegExp]
280+
) ->
281+
{ok, R} = re:compile(
282+
any_to_list(RegExp),
283+
[dotall, dollar_endonly, caseless]
284+
),
285+
Args = [global],
286+
case re:run(any_to_list(Str), R, [{capture, all, binary} | Args]) of
287+
nomatch ->
288+
undefined;
289+
{match, CaptureBinary} ->
290+
{match, CaptureIdx} =
291+
re:run(any_to_list(Str), R, [{capture, all, index} | Args]),
292+
match_capture_objects(CaptureBinary, CaptureIdx, [])
293+
end;
294+
handle_local_function(
295+
jsonata_match,
296+
[Str, RegExp, MatchLimit]
297+
) when is_integer(MatchLimit) =:= false ->
298+
handle_local_function(
299+
jsonata_match,
300+
[
301+
Str,
302+
RegExp,
303+
list_to_integer(any_to_list(MatchLimit))
304+
]
305+
);
306+
handle_local_function(
307+
jsonata_match,
308+
[_Str, _RegExp, MatchLimit] = Args
309+
) when is_integer(MatchLimit), MatchLimit < 0 ->
310+
erlang:error(
311+
"Invalid JSONata expression: Third argument of match function must evaluate to a positive number",
312+
[{"$match", Args}]
313+
);
314+
handle_local_function(
315+
jsonata_match,
316+
[_Str, _RegExp, MatchLimit]
317+
) when is_integer(MatchLimit), MatchLimit =:= 0 ->
318+
undefined;
319+
handle_local_function(
320+
jsonata_match,
321+
[Str, RegExp, MatchLimit]
322+
) when is_integer(MatchLimit), MatchLimit > 0 ->
323+
match_capture_limit(
324+
handle_local_function(jsonata_match, [Str, RegExp]),
325+
MatchLimit,
326+
[]
327+
);
276328
%% -------> fall through to unsupported
277329
handle_local_function(FunctionName, Args) ->
278330
erlang:error(jsonata_unsupported, [{FunctionName, Args}]).
@@ -347,3 +399,33 @@ iso_8601_datestamp(Timestamp) ->
347399
[Year, Month, Day, Hour, Min, Sec]
348400
)
349401
).
402+
403+
%%
404+
%% See test id : #d206746f9f2594a6 for more format details
405+
%% --> https://flows.red-erik.org/f/d206746f9f2594a6
406+
%%
407+
match_capture_objects([], [], [Hd | []] = _Acc) ->
408+
Hd;
409+
match_capture_objects([], [], Acc) ->
410+
lists:reverse(Acc);
411+
match_capture_objects(
412+
[[Matched | RestMatched] | RestBinary],
413+
[[{MatchedIdx, _} | _RestMatched] | RestIndicies],
414+
Acc
415+
) ->
416+
CapHsh = #{
417+
<<"match">> => Matched,
418+
<<"index">> => MatchedIdx,
419+
<<"groups">> => RestMatched
420+
},
421+
match_capture_objects(RestBinary, RestIndicies, [CapHsh | Acc]).
422+
%%
423+
%%
424+
match_capture_limit(undefined, _, _) ->
425+
undefined;
426+
match_capture_limit(_Result, 0, [Hd | []] = _Acc) ->
427+
Hd;
428+
match_capture_limit(_Result, 0, Acc) ->
429+
lists:reverse(Acc);
430+
match_capture_limit([HD | Rest], MatchLimit, Acc) ->
431+
match_capture_limit(Rest, MatchLimit - 1, [HD | Acc]).

src/erlang_red_jsonata_parser.erl

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,8 @@ args_to_string([{string, _LineNo, String}|T], Acc) ->
209209
args_to_string(T, io_lib:format("~s, ~s", [Acc, String]));
210210
args_to_string([{name, _LineNo, String}|T], Acc) ->
211211
args_to_string(T, io_lib:format("~s, ~s", [Acc, String]));
212+
args_to_string([{regexp, _LineNo, String}|T], Acc) ->
213+
args_to_string(T, io_lib:format("~s, ~s", [Acc, String]));
212214
args_to_string([H|T], Acc) ->
213215
args_to_string(T, io_lib:format("~s, ~s", [Acc, H])).
214216

@@ -265,6 +267,9 @@ convert_funct({funct,_LineNo,FunctName}, Expr) ->
265267
substring ->
266268
list_to_binary(io_lib:format("jsonata_substring(~s)",
267269
[args_to_string(Expr)]));
270+
match ->
271+
list_to_binary(io_lib:format("jsonata_match(~s)",
272+
[args_to_string(Expr)]));
268273
sum ->
269274
list_to_binary(io_lib:format("lists:sum(~s)",
270275
[args_to_string(Expr)]));
@@ -602,7 +607,7 @@ yecctoken2string1(Other) ->
602607

603608

604609

605-
-file("/code/src/erlang_red_jsonata_parser.erl", 605).
610+
-file("/code/src/erlang_red_jsonata_parser.erl", 610).
606611

607612
-dialyzer({nowarn_function, yeccpars2/7}).
608613
-compile({nowarn_unused_function, yeccpars2/7}).
@@ -4324,4 +4329,4 @@ yeccpars2_148_(__Stack0) ->
43244329
end | __Stack].
43254330

43264331

4327-
-file("/code/src/erlang_red_jsonata_parser.yrl", 637).
4332+
-file("/code/src/erlang_red_jsonata_parser.yrl", 642).

src/erlang_red_jsonata_parser.yrl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,8 @@ args_to_string([{string, _LineNo, String}|T], Acc) ->
430430
args_to_string(T, io_lib:format("~s, ~s", [Acc, String]));
431431
args_to_string([{name, _LineNo, String}|T], Acc) ->
432432
args_to_string(T, io_lib:format("~s, ~s", [Acc, String]));
433+
args_to_string([{regexp, _LineNo, String}|T], Acc) ->
434+
args_to_string(T, io_lib:format("~s, ~s", [Acc, String]));
433435
args_to_string([H|T], Acc) ->
434436
args_to_string(T, io_lib:format("~s, ~s", [Acc, H])).
435437

@@ -486,6 +488,9 @@ convert_funct({funct,_LineNo,FunctName}, Expr) ->
486488
substring ->
487489
list_to_binary(io_lib:format("jsonata_substring(~s)",
488490
[args_to_string(Expr)]));
491+
match ->
492+
list_to_binary(io_lib:format("jsonata_match(~s)",
493+
[args_to_string(Expr)]));
489494
sum ->
490495
list_to_binary(io_lib:format("lists:sum(~s)",
491496
[args_to_string(Expr)]));

0 commit comments

Comments
 (0)