open Re
open Re_emacs

let eq_re r s = Fort.expect_equal_app ~msg:s id r re s
;;

(* 
 * Tests based on description of emacs regular expressions given at
 *   http://www.gnu.org/manual/elisp-manual-20-2.5/html_chapter/elisp_34.html
 *)

expect_pass "ordinary characters" (fun () ->
  eq_re (char 'a')                      "a";
);

expect_pass "concatenation" (fun () ->
  eq_re (seq [char 'a'; char 'b'])      "ab";
);

expect_pass "escaping special characters" (fun () ->
  eq_re (char '.')                      "\.";
  eq_re (char '*')                      "\*";
  eq_re (char '+')                      "\+";
  eq_re (char '?')                      "\?";
  eq_re (char '[')                      "\[";
  eq_re (char ']')                      "\]";
  eq_re (char '^')                      "\^";
  eq_re (char '$')                      "\$";
  eq_re (char '\\')                     "\\\\";
);

expect_pass "special characters" (fun () ->
  eq_re notnl                           ".";
  eq_re (rep (char 'a'))                "a*";
  eq_re (rep1 (char 'a'))               "a+";
  eq_re (opt (char 'a'))                "a?";
  eq_re (alt [char 'b'; char 'a'])      "[ab]";
  eq_re (rg 'a' 'z')                    "[a-z]";
  eq_re (alt [char '.'; char '%'; char '$'; rg 'a' 'z'])
                                        "[a-z$%.]";
  eq_re (alt [char 'a'; char ']'])      "[]a]";
  eq_re (alt [char ']'; char '-'])      "[]-]";
  eq_re (alt [char '^'; char 'a'])      "[a^]";
  eq_re (compl [rg 'a' 'z'])            "[^a-z]";
  eq_re (compl [char '$'; rg 'a' 'z'])  "[^a-z$]";
  eq_re bol                             "^";
  eq_re eol                             "$";
);

expect_pass "historical compatibility (not supported)" (fun () ->
  expect_equal_app
    (fun () -> raise Parse_error) ()
    re "*ab";
  expect_equal_app
    (fun () -> raise Parse_error) ()
    re "+ab";
  expect_equal_app
    (fun () -> raise Parse_error) ()
    re "?ab";
);

expect_pass "alternative" (fun () ->
  eq_re (alt [char 'a'; char 'b'])      "a\|b";
  eq_re (alt [seq [char 'a'; char 'a']; seq [char 'b'; char 'b']])
                                        "aa\|bb";
);

expect_pass "grouping" (fun () ->
  eq_re (group (char 'a'))              "\(a\)";
  eq_re (seq [group (alt [char 'a'; char 'b']); char 'c'])
                                        "\(a\|b\)c"
);

expect_pass "backreferences" (fun () ->
  expect_equal_app
    (fun () -> raise Not_supported) ()
    re "\0"
);

expect_pass "word-constituent" (fun () ->
  eq_re (alt [alnum; char '_'])         "\w";
  eq_re (compl [alnum; char '_'])       "\W";
);

(* syntax codes... ? *)

expect_pass "contexts" (fun () ->
  eq_re bos                             "\`";
  eq_re eos                             "\'";
  eq_re start                           "\=";
  eq_re (alt [bow; eow])                "\\b";
  eq_re not_boundary                    "\B";
  eq_re bow                             "\<";
  eq_re eow                             "\>";
);
