Skip to content

Commit 2e3474f

Browse files
committed
update README, remove unused fn
1 parent 0e3b113 commit 2e3474f

File tree

3 files changed

+67
-8
lines changed

3 files changed

+67
-8
lines changed

README.md

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,72 @@ The patterns are plain strings of the form accepted by `Re.Pcre`, with the follo
121121
A variable is allowed for the universal case and is bound to the matched
122122
string.
123123

124+
### Type definitions from patterns
125+
You can generate record types from regex patterns:
126+
127+
```ocaml
128+
type url = {%mikmatch|
129+
(("http" | "https") as scheme) "://"
130+
((alnum+ ('.' alnum+)*) as host)
131+
(':' (digit+ as port : int))?
132+
('/' ([^'?' '#']* as path))?
133+
('?' ([^'#']* as query))?
134+
('#' (any* as fragment))?
135+
|}
136+
```
137+
This generates:
138+
- A record type with fields for each named capture
139+
- `parse_url : string -> url option` - parses strings into the type
140+
- `pp_url : Format.formatter -> url -> unit` - pretty-prints back to string format
141+
142+
> [!WARNING]
143+
> When printing, repetitions will be executed the minimum required amount of times.
144+
> `*` prints nothing
145+
146+
#### Smart reconstruction
147+
The pretty-printer intelligently handles alternations and optional fields:
148+
```ocaml
149+
let%mikmatch date_format = {| digit{4} '-' digit{2} '-' digit{2} ' ' digit{2} ':' digit{2} ':' digit{2} |}
150+
151+
type date = {%mikmatch| (date_format as date) |}
152+
153+
type mode =
154+
[ `A
155+
| `B
156+
| `Other
157+
]
158+
159+
let mk_mode = function "a" -> `A | "b" -> `B | _ -> `Other
160+
let pp_mode fmt mode = Format.fprintf fmt @@ match mode with `A -> "a" | `B -> "b" | `Other -> "other"
161+
162+
type log = {%mikmatch|
163+
(date_format as date)
164+
" [" (upper+ as level) "]"
165+
((" pid=" (digit+ as pid : int))? | (" name=" ([a-z]+ as name))?)
166+
' '{2-3}
167+
('a'|'b'|"other" as mode := mk_mode : mode)
168+
": "
169+
(any+ as message)
170+
|}
171+
172+
let input = "2025-06-13 12:42:12 [INFO] pid=123 a: something happened" in
173+
match parse_log input with
174+
| Some log ->
175+
(* Prints: "2025-06-13 12:42:12 [INFO] pid=123 a: something happened" *)
176+
Format.printf "%a@." pp_log log;
177+
178+
(* Change from pid to name variant *)
179+
let log' = { log with pid = None; name = Some "server" } in
180+
(* Prints: "2025-06-13 12:42:12 [INFO] name=server a: something happened" *)
181+
Format.printf "%a@." pp_log log'
182+
```
183+
The pretty-printer detects which alternation branch to use based on field population - if `pid` is `Some _`, it prints the `pid` branch; if `name` is `Some _`, it prints the `name` branch.
184+
185+
##### Type conversions and custom parsers
186+
- For function application you are required to pass the return type.
187+
- If the return type is itself an application (e.g. `string list`), then you must provide a type alias.
188+
- The type must have an associated `pp` function. (Notice, in the example, the `mode` type and its associated functions)
189+
124190
### Example
125191

126192
The following prints out times and hosts for SMTP connections to the Postfix daemon:

ppx_mikmatch.opam

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ matched substring available in the right-hand side of match cases
4545
- `let%pcre name = {|re|}` defines reusable patterns for use within `(?U/N<name>)` patterns
4646
- `match%mikmatch` supports mikmatch-style syntax with typed captures and pattern
4747
composition, along with `let%mikmatch` for defining reusable patterns
48+
- `type name = {%mikmatch| re |}` generates record types with parse/pp functions from patterns
4849
- let destructuring via `let%pcre/mikmatch {| regex |} = s`, where `regex` binds values and `s` is the input string
4950
- `/regex/flags` for providing compiler flags. `i` for caseless, `a` (%pcre) anchored, `u` (%mikmatch) unanchored
5051
- Caseless groups via `(?i:regex)` for %pcre, and the `~` operator for %mikmatch

ppx_regexp/transformations.ml

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -793,13 +793,6 @@ let transform_type ~mode ~loc rec_flag type_name pattern_str _td =
793793

794794
let pp_body = build_pp_expr ~top_lvl:true r in
795795

796-
let reconstruct_func_name = "reconstruct_" ^ type_name in
797-
let reconstruct_func =
798-
value_binding ~loc
799-
~pat:(ppat_var ~loc { txt = reconstruct_func_name; loc })
800-
~expr:[%expr fun v -> Format.asprintf "%a" [%e pexp_ident ~loc { txt = Longident.parse pp_func_name; loc }] v]
801-
in
802-
803796
[
804797
pstr_type ~loc rec_flag [ type_decl ];
805798
pstr_value ~loc Nonrecursive [ parse_binding ];
@@ -816,5 +809,4 @@ let transform_type ~mode ~loc rec_flag type_name pattern_str _td =
816809
];
817810
pstr_value ~loc Nonrecursive
818811
[ value_binding ~loc ~pat:(ppat_var ~loc { txt = pp_func_name; loc }) ~expr:[%expr fun ppf v -> [%e pp_body]] ];
819-
pstr_value ~loc Nonrecursive [ reconstruct_func ];
820812
]

0 commit comments

Comments
 (0)