Skip to content

Commit 753bc60

Browse files
committed
top level alternations work
1 parent 2e3474f commit 753bc60

File tree

2 files changed

+51
-13
lines changed

2 files changed

+51
-13
lines changed

ppx_regexp/transformations.ml

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -679,22 +679,17 @@ let transform_type ~mode ~loc rec_flag type_name pattern_str _td =
679679

680680
let pp_func_name = "pp_" ^ type_name in
681681

682-
let rec build_pp_expr ~top_lvl (node : _ Location.loc) =
682+
let rec build_pp_expr (node : _ Location.loc) =
683683
match node.txt with
684684
| Regexp_types.Code s -> [%expr Format.pp_print_string ppf [%e estring ~loc @@ unescape_literal s]]
685685
| Seq es ->
686-
let exprs = List.map (build_pp_expr ~top_lvl:false) es in
686+
let exprs = List.map build_pp_expr es in
687687
List.fold_left
688688
(fun acc e ->
689689
[%expr
690690
[%e acc];
691691
[%e e]])
692692
[%expr ()] exprs
693-
| Alt _ when top_lvl ->
694-
Util.error ~loc
695-
"Top-level alternations in type definitions are problematic. Consider wrapping the entire alternation in a capture group, though \
696-
note that the pretty-printer will only be able to reconstruct one branch."
697-
re
698693
| Alt branches ->
699694
(* branch selection based on populated fields *)
700695
build_alt_pp_expr branches
@@ -724,8 +719,8 @@ let transform_type ~mode ~loc rec_flag type_name pattern_str _td =
724719
match find_capture e with
725720
| Some name ->
726721
let field_access = pexp_field ~loc [%expr v] { txt = Lident name; loc } in
727-
[%expr match [%e field_access] with None -> () | Some _ -> [%e build_pp_expr ~top_lvl:false e]]
728-
| None -> build_pp_expr ~top_lvl:false e
722+
[%expr match [%e field_access] with None -> () | Some _ -> [%e build_pp_expr e]]
723+
| None -> build_pp_expr e
729724
end
730725
| Repeat (range, e) ->
731726
let min_reps, max_reps_opt = range.txt in
@@ -736,7 +731,7 @@ let transform_type ~mode ~loc rec_flag type_name pattern_str _td =
736731
[%expr
737732
let count = [%e eint ~loc min_reps] in
738733
for _ = 1 to count do
739-
[%e build_pp_expr ~top_lvl:false e]
734+
[%e build_pp_expr e]
740735
done]
741736
| _ ->
742737
let rec repeat_n n expr =
@@ -747,7 +742,7 @@ let transform_type ~mode ~loc rec_flag type_name pattern_str _td =
747742
[%e expr];
748743
[%e repeat_n (n - 1) expr]]
749744
in
750-
repeat_n min_reps (build_pp_expr ~top_lvl:false e)
745+
repeat_n min_reps (build_pp_expr e)
751746
end
752747
| _ -> [%expr ()]
753748
(* determine branch based on populated fields *)
@@ -778,7 +773,7 @@ let transform_type ~mode ~loc rec_flag type_name pattern_str _td =
778773
| [ cond ] -> cond
779774
| conds -> List.fold_left (fun acc cond -> [%expr [%e acc] || [%e cond]]) (List.hd conds) (List.tl conds) )
780775
in
781-
condition, build_pp_expr ~top_lvl:false branch)
776+
condition, build_pp_expr branch)
782777
branches
783778
in
784779

@@ -791,7 +786,7 @@ let transform_type ~mode ~loc rec_flag type_name pattern_str _td =
791786
build_cascade branch_conditions
792787
in
793788

794-
let pp_body = build_pp_expr ~top_lvl:true r in
789+
let pp_body = build_pp_expr r in
795790

796791
[
797792
pstr_type ~loc rec_flag [ type_decl ];

tests/test_ppx_regexp.ml

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -662,6 +662,47 @@ let test_parse_http_request _ =
662662
assert_bool "Should have POST" (String.starts_with ~prefix:"POST" output);
663663
assert_bool "Should not have query" (not (String.contains output '?'))
664664

665+
(* top-level alternation *)
666+
type ip_address =
667+
{%mikmatch|
668+
(digit{1-3} as o1 : int) '.'
669+
(digit{1-3} as o2 : int) '.'
670+
(digit{1-3} as o3 : int) '.'
671+
(digit{1-3} as o4 : int)
672+
673+
|
674+
675+
((['0'-'9' 'a'-'f' 'A'-'F']{0-4} ':')+ ['0'-'9' 'a'-'f' 'A'-'F']{0-4} as ipv6)
676+
|}
677+
678+
let test_parse_ip1 _ =
679+
let ip1 = "192.168.1.1" in
680+
match parse_ip_address ip1 with
681+
| None -> assert_failure "Should parse ipv4"
682+
| Some t ->
683+
assert_equal t.o1 (Some 192);
684+
assert_equal t.o2 (Some 168);
685+
assert_equal t.o3 (Some 1);
686+
assert_equal t.o4 (Some 1);
687+
assert_equal t.ipv6 None;
688+
assert_equal (Format.asprintf "%a" pp_ip_address t) ip1;
689+
let t' = { o1 = None; o2 = None; o3 = None; o4 = None; ipv6 = Some "2001:db8::8a2e:370:7334" } in
690+
assert_equal (Format.asprintf "%a" pp_ip_address t') "2001:db8::8a2e:370:7334"
691+
692+
let test_parse_ip2 _ =
693+
let ip2 = "2001:db8::8a2e:370:7334" in
694+
match parse_ip_address ip2 with
695+
| None -> assert_failure "Should parse ipv6"
696+
| Some t ->
697+
assert_equal t.o1 None;
698+
assert_equal t.o2 None;
699+
assert_equal t.o3 None;
700+
assert_equal t.o4 None;
701+
assert_equal t.ipv6 (Some "2001:db8::8a2e:370:7334");
702+
assert_equal (Format.asprintf "%a" pp_ip_address t) ip2;
703+
let t' = { o1 = Some 127; o2 = Some 0; o3 = Some 0; o4 = Some 1; ipv6 = None } in
704+
assert_equal (Format.asprintf "%a" pp_ip_address t') "127.0.0.1"
705+
665706
let suite =
666707
"mikmatch_tests"
667708
>::: [
@@ -688,6 +729,8 @@ let suite =
688729
"test_parse_with_neither" >:: test_parse_with_neither;
689730
"test_parse_url" >:: test_parse_url;
690731
"test_parse_http_request" >:: test_parse_http_request;
732+
"test_parse_ip1" >:: test_parse_ip1;
733+
"test_parse_ip2" >:: test_parse_ip2;
691734
]
692735

693736
let () = run_test_tt_main suite

0 commit comments

Comments
 (0)