-
Notifications
You must be signed in to change notification settings - Fork 61
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
339 additions
and
362 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,6 +8,7 @@ | |
ppx_expect.config_types | ||
ppx_expect | ||
base | ||
str | ||
ppx_inline_test.config) | ||
(inline_tests | ||
(modes native js)) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,325 @@ | ||
open Import | ||
|
||
module type Str_intf = module type of Str | ||
|
||
module Test_matches (R : Str_intf) = struct | ||
let groups () = | ||
let group i = | ||
try `Found (R.group_beginning i) with | ||
| Not_found -> `Not_found | ||
| Invalid_argument _ -> `Not_exists | ||
in | ||
let rec loop acc i = | ||
match group i with | ||
| `Found p -> loop ((p, R.group_end i) :: acc) (i + 1) | ||
| `Not_found -> loop ((-1, -1) :: acc) (i + 1) | ||
| `Not_exists -> List.rev acc | ||
in | ||
loop [] 0 | ||
;; | ||
|
||
let eq_match ?(pos = 0) ?(case = true) r s = | ||
let pat = if case then R.regexp r else R.regexp_case_fold r in | ||
try | ||
ignore (R.search_forward pat s pos); | ||
Some (groups ()) | ||
with | ||
| Not_found -> None | ||
;; | ||
|
||
let eq_match' ?(pos = 0) ?(case = true) r s = | ||
let pat = if case then R.regexp r else R.regexp_case_fold r in | ||
try | ||
ignore (R.string_match pat s pos); | ||
Some (groups ()) | ||
with | ||
| Not_found -> None | ||
;; | ||
end | ||
|
||
module T_str = Test_matches (Str) | ||
module T_re = Test_matches (Re.Str) | ||
|
||
let test dyn_of_ok str re args = | ||
let run f = | ||
match f () with | ||
| s -> Ok s | ||
| exception exn -> Error exn | ||
in | ||
let str = run (fun () -> str args) in | ||
let re = run (fun () -> re args) in | ||
if not (Poly.equal str re) | ||
then ( | ||
let printer x = | ||
let dyn = | ||
let open Dyn in | ||
result dyn_of_ok (fun x -> string (Printexc.to_string x)) x | ||
in | ||
sexp_of_dyn dyn |> Base.Sexp.to_string_hum | ||
in | ||
Printf.printf "str: %s\n" (printer str); | ||
Printf.printf "re: %s\n" (printer re)) | ||
;; | ||
|
||
let dyn_of_pairs x = | ||
Dyn.option | ||
(fun x -> | ||
List.map x ~f:(fun (start, stop) -> | ||
let open Dyn in | ||
pair (int start) (int stop)) | ||
|> Dyn.list) | ||
x | ||
;; | ||
|
||
let split_result_conv = | ||
List.map ~f:(function | ||
| Str.Delim x -> Re.Str.Delim x | ||
| Str.Text x -> Re.Str.Text x) | ||
;; | ||
|
||
let dyn_split_result_list list = | ||
List.map | ||
list | ||
~f: | ||
(let open Dyn in | ||
function | ||
| Re.Str.Delim x -> variant "Delim" [ string x ] | ||
| Text s -> variant "Text" [ string s ]) | ||
|> Dyn.list | ||
;; | ||
|
||
type ('a, 'b) test = | ||
{ name : string | ||
; dyn_of_ok : 'b -> Dyn.t | ||
; re_str : Re.Str.regexp -> 'a -> 'b | ||
; str : Str.regexp -> 'a -> 'b | ||
} | ||
|
||
let bounded_split_t = | ||
{ name = "bounded_split" | ||
; dyn_of_ok = (fun x -> Dyn.list (List.map x ~f:Dyn.string)) | ||
; re_str = (fun re (s, n) -> Re.Str.bounded_split re s n) | ||
; str = (fun re (s, n) -> Str.bounded_split re s n) | ||
} | ||
;; | ||
|
||
let bounded_full_split_t = | ||
{ name = "bounded_full_split" | ||
; dyn_of_ok = dyn_split_result_list | ||
; re_str = (fun re (s, n) -> Re.Str.bounded_full_split re s n) | ||
; str = (fun re (s, n) -> split_result_conv (Str.bounded_full_split re s n)) | ||
} | ||
;; | ||
|
||
let full_split_t = | ||
{ bounded_full_split_t with | ||
name = "full_split" | ||
; re_str = (fun re s -> Re.Str.full_split re s) | ||
; str = (fun re s -> split_result_conv (Str.full_split re s)) | ||
} | ||
;; | ||
|
||
let split_delim_t = | ||
{ name = "split_delim" | ||
; dyn_of_ok = (fun x -> Dyn.list (List.map x ~f:Dyn.string)) | ||
; re_str = Re.Str.split_delim | ||
; str = Str.split_delim | ||
} | ||
;; | ||
|
||
let split_t = | ||
{ name = "split" | ||
; dyn_of_ok = (fun x -> Dyn.list (List.map x ~f:Dyn.string)) | ||
; re_str = Re.Str.split | ||
; str = Str.split | ||
} | ||
;; | ||
|
||
let global_replace_t = | ||
{ name = "global_replace" | ||
; dyn_of_ok = Dyn.string | ||
; re_str = (fun re (r, s) -> Re.Str.global_replace re r s) | ||
; str = (fun re (r, s) -> Str.global_replace re r s) | ||
} | ||
;; | ||
|
||
let eq_match ?pos ?case re = | ||
test dyn_of_pairs (T_str.eq_match ?pos ?case re) (T_re.eq_match ?pos ?case re) | ||
;; | ||
|
||
let eq_match' ?pos ?case re = | ||
test dyn_of_pairs (T_str.eq_match' ?pos ?case re) (T_re.eq_match' ?pos ?case re) | ||
;; | ||
|
||
let test t re args = | ||
test t.dyn_of_ok (t.re_str (Re.Str.regexp re)) (t.str (Str.regexp re)) args | ||
;; | ||
|
||
let split_delim re s = test split_delim_t re s | ||
let split re s = test split_t re s | ||
let full_split re s = test full_split_t re s | ||
let bounded_split re s n = test bounded_split_t re (s, n) | ||
let bounded_full_split re s n = test bounded_full_split_t re (s, n) | ||
let global_replace re r s = test global_replace_t re (r, s) | ||
|
||
let%expect_test "literal match" = | ||
eq_match "a" "a"; | ||
eq_match "a" "b"; | ||
[%expect {||}] | ||
;; | ||
|
||
let%expect_test "alt" = | ||
eq_match "a\\|b" "a"; | ||
eq_match "a\\|b" "b"; | ||
eq_match "a\\|b" "c"; | ||
[%expect {||}] | ||
;; | ||
|
||
let%expect_test "seq" = | ||
eq_match "ab" "ab"; | ||
eq_match "ab" "ac"; | ||
[%expect {||}] | ||
;; | ||
|
||
let%expect_test "epsilon" = | ||
eq_match "" ""; | ||
eq_match "" "a"; | ||
[%expect {||}] | ||
;; | ||
|
||
let%expect_test "rep" = | ||
eq_match "a*" ""; | ||
eq_match "a*" "a"; | ||
eq_match "a*" "aa"; | ||
eq_match "a*" "b"; | ||
[%expect {||}] | ||
;; | ||
|
||
let%expect_test "rep1" = | ||
eq_match "a+" "a"; | ||
eq_match "a+" "aa"; | ||
eq_match "a+" ""; | ||
eq_match "a+" "b"; | ||
[%expect {| |}] | ||
;; | ||
|
||
let%expect_test "opt" = | ||
eq_match "a?" ""; | ||
eq_match "a?" "a"; | ||
[%expect {| |}] | ||
;; | ||
|
||
let%expect_test "bol" = | ||
eq_match "^a" "ab"; | ||
eq_match "^a" "b\na"; | ||
eq_match "^a" "ba"; | ||
[%expect {| |}] | ||
;; | ||
|
||
let%expect_test "eol" = | ||
eq_match "a$" "ba"; | ||
eq_match "a$" "a\nb"; | ||
eq_match "a$" "ba\n"; | ||
eq_match "a$" "ab"; | ||
[%expect {| |}] | ||
;; | ||
|
||
let%expect_test "start" = | ||
eq_match ~pos:1 "Za" "xab"; | ||
eq_match ~pos:1 "Za" "xb\na"; | ||
eq_match ~pos:1 "Za" "xba"; | ||
[%expect {||}] | ||
;; | ||
|
||
let%expect_test "match semantics" = | ||
eq_match "\\(a\\|b\\)*b" "aabaab"; | ||
eq_match "aa\\|aaa" "aaaa"; | ||
eq_match "aaa\\|aa" "aaaa"; | ||
[%expect {||}] | ||
;; | ||
|
||
let%expect_test "Group (or submatch)" = | ||
eq_match "\\(a\\)\\(a\\)?\\(b\\)" "ab"; | ||
[%expect {| |}] | ||
;; | ||
|
||
let%expect_test "Character set" = | ||
eq_match "[0-9]+" "0123456789"; | ||
eq_match "[0-9]+" "a"; | ||
eq_match "[9-0]+" "2"; | ||
eq_match "[5-5]" "5"; | ||
eq_match "[5-4]" "1"; | ||
eq_match' "[]]" "]"; | ||
eq_match' "[a-]" "-"; | ||
eq_match' "[-a]" "-"; | ||
eq_match' "]" "]"; | ||
eq_match' "[^b-f]" "z"; | ||
eq_match' "[^b-f]" "a"; | ||
[%expect {||}]; | ||
(* These errors aren't correct *) | ||
eq_match' "[]" "x"; | ||
eq_match' "[" "["; | ||
[%expect | ||
{| | ||
str: (Error "Failure(\"[ class not closed by ]\")") | ||
re: (Error Re_private.Emacs.Parse_error) | ||
str: (Error "Failure(\"[ class not closed by ]\")") | ||
re: (Error Re_private.Emacs.Parse_error) | ||
|}] | ||
;; | ||
|
||
let%expect_test "compl" = | ||
eq_match "[^0-9a-z]+" "A:Z+"; | ||
eq_match "[^0-9a-z]+" "0"; | ||
eq_match "[^0-9a-z]+" "a"; | ||
[%expect {||}] | ||
;; | ||
|
||
let%expect_test "Word modifiers" = | ||
eq_match' "\\bfoo" "foo"; | ||
eq_match' "\\<foo" "foo"; | ||
eq_match' "foo\\>" "foo"; | ||
eq_match' "z\\Bfoo" "zfoo"; | ||
eq_match' "\\`foo" "foo"; | ||
eq_match' "foo\\'" "foo"; | ||
[%expect {||}] | ||
;; | ||
|
||
let%expect_test "Case modifiers" = | ||
eq_match ~case:false "abc" "abc"; | ||
eq_match ~case:false "abc" "ABC"; | ||
[%expect {| |}] | ||
;; | ||
|
||
let%expect_test "global_replace" = | ||
global_replace "needle" "test" "needlehaystack"; | ||
global_replace "needle" "" ""; | ||
global_replace "needle" "" "needle"; | ||
global_replace "xxx" "yyy" "zzz"; | ||
global_replace "test\\([0-9]*\\)" "\\1-foo-\\1" "test100 test200 test"; | ||
global_replace "test\\([0-9]*\\)" "'\\-0'" "test100 test200 test"; | ||
(* Regrssion test for #129 *) | ||
global_replace "\\(X+\\)" "A\\1YY" "XXXXXXZZZZ"; | ||
[%expect {||}] | ||
;; | ||
|
||
let%expect_test "bounded_split, bounded_full_split" = | ||
[ ",", "foo,bar,baz", 5 | ||
; ",", "foo,bar,baz", 1 | ||
; ",", "foo,bar,baz", 0 | ||
; ",\\|", "foo,bar|baz", 4 | ||
] | ||
|> List.iter ~f:(fun (re, s, n) -> | ||
bounded_full_split re s n; | ||
bounded_split re s n); | ||
[%expect {||}] | ||
;; | ||
|
||
let%expect_test "split, full_split, split_delim" = | ||
[ "re", ""; " ", "foo bar"; "\b", "one-two three"; "[0-9]", "One3TwoFive" ] | ||
|> List.iter ~f:(fun (re, s) -> | ||
split re s; | ||
full_split re s; | ||
split_delim re s); | ||
[%expect {||}] | ||
;; |
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.