Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ A variable is allowed for the universal case and is bound to the matched
string. A regular alias is currently not allowed for patterns, since it is
not obvious whether is should bind the full string or group 0.

### Case-Insensitive Match

An extension, `%pcre_i`, is available for case-insensitive matching.

### Example

The following prints out times and hosts for SMTP connections to the Postfix
Expand Down
16 changes: 11 additions & 5 deletions ppx_regexp/ppx_regexp.ml
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,11 @@ let rec wrap_group_bindings ~loc rhs offG = function
let [%p ppat_var ~loc varG] = [%e eG] in
[%e wrap_group_bindings ~loc rhs offG bs]]

let transform_cases ~loc cases =
let rec create_opts ~loc = function
| [] -> [%expr []]
| `Caseless :: xs -> [%expr `Caseless :: [%e create_opts ~loc xs]]

let transform_cases ~loc ~opts cases =
let aux case =
if case.pc_guard <> None then
error ~loc "Guards are not implemented for match%%pcre."
Expand Down Expand Up @@ -172,8 +176,9 @@ let transform_cases ~loc cases =
in
let cases = List.rev_map aux cases in
let res = pexp_array ~loc (List.map (fun (re, _, _, _) -> re) cases) in
let opts_expr = create_opts ~loc opts in
let comp = [%expr
let a = Array.map (fun s -> Re.mark (Re.Perl.re s)) [%e res] in
let a = Array.map (fun s -> Re.mark (Re.Perl.re ~opts:[%e opts_expr] s)) [%e res] in
let marks = Array.map fst a in
let re = Re.compile (Re.alt (Array.to_list (Array.map snd a))) in
(re, marks)
Expand Down Expand Up @@ -208,14 +213,15 @@ let transformation = object
let e_ext, acc = super#expression e_ext acc in
(match e_ext.pexp_desc with
| Pexp_extension
({txt = "pcre"; _}, PStr [{pstr_desc = Pstr_eval (e, _); _}]) ->
({txt = ("pcre" | "pcre_i") as ext; _}, PStr [{pstr_desc = Pstr_eval (e, _); _}]) ->
let opts = if String.ends_with ~suffix:"_i" ext then [`Caseless] else [] in
let loc = e.pexp_loc in
(match e.pexp_desc with
| Pexp_match (e, cases) ->
let cases, binding = transform_cases ~loc cases in
let cases, binding = transform_cases ~loc ~opts cases in
([%expr let _ppx_regexp_v = [%e e] in [%e cases]], binding :: acc)
| Pexp_function (cases) ->
let cases, binding = transform_cases ~loc cases in
let cases, binding = transform_cases ~loc ~opts cases in
([%expr fun _ppx_regexp_v -> [%e cases]], binding :: acc)
| _ ->
error ~loc "[%%pcre] only applies to match an function.")
Expand Down