|
66 | 66 |
|
67 | 67 | ## `ppx_tyre` - Syntax Support for Tyre Routes
|
68 | 68 |
|
| 69 | +### Typed regular expressions |
| 70 | + |
69 | 71 | This PPX compiles
|
70 | 72 | ```ocaml
|
71 |
| - [%tyre {|re|}] |
| 73 | +[%tyre {|re|}] |
| 74 | +``` |
| 75 | +into `'a Tyre.t`. |
| 76 | + |
| 77 | +For instance, We can define a pattern that recognize strings of the form "dim:3x5" like so: |
| 78 | + |
| 79 | +```ocaml |
| 80 | +# open Tyre ;; |
| 81 | +# let dim = [%tyre "dim:(?&int)x(?&int)"] ;; |
| 82 | +val dim : (int * int) Tyre.t |
72 | 83 | ```
|
73 |
| -into `'a Tyre.t` and |
| 84 | + |
| 85 | +The syntax `(?&id)` allows to call a typed regular expression named `id` of type `'a Tyre.t`, such as `Tyre.int`. |
| 86 | + |
| 87 | +For convenience, you can also use *named* capture groups to name the captured elements. |
| 88 | +```ocaml |
| 89 | +# let dim = [%tyre "dim:(?<x>(?&int))x(?&y:int)"] ;; |
| 90 | +val dim : < x : int; y : int > Tyre.t |
| 91 | +``` |
| 92 | + |
| 93 | +Names given using the syntax `(?<foo>re)` will be used for the fields |
| 94 | +of the results. `(?&y:int)` is a shortcut for `(?<x>(?&int))`. |
| 95 | +This can also be used for alternatives, for instance: |
| 96 | + |
| 97 | +```ocaml |
| 98 | +# let id_or_name = [%tyre "id:(?&id:int)|name:(?<name>[:alpha:]+)"] ;; |
| 99 | +val id_or_name : [ `id of int | `name of string ] Tyre.t |
| 100 | +``` |
| 101 | + |
| 102 | +Expressions of type `Tyre.t` can then be composed as part of bigger regular |
| 103 | +expressions, or compiled with `Tyre.compile`. |
| 104 | +See [tyre][]'s documentation for details. |
| 105 | + |
| 106 | +### Routes |
| 107 | + |
| 108 | +`ppx_tyre` can also be used for routing, in the style of `ppx_regexp`: |
| 109 | + |
74 | 110 | ```ocaml
|
75 | 111 | function%tyre
|
76 |
| - | {|re1|} as x1 -> e1 |
| 112 | + | {|re1|} -> e1 |
77 | 113 | ...
|
78 |
| - | {|reN|} as x2 -> eN |
| 114 | + | {|reN|} -> eN |
79 | 115 | ```
|
80 |
| -into `'a Type.route`, where `re`, `re1`, ... are regular expressions |
81 |
| -expressed in a slightly extended subset of PCRE. The interpretations are: |
| 116 | + |
| 117 | +is turned into a `'a Type.route`, where `re`, `re1`, ... are regular expressions |
| 118 | +using the same syntax as above. `"re" as v` is considered like `(?<v>re)` and |
| 119 | +`"re1" | "re2"` is turned into a regular expression alternative. |
| 120 | + |
| 121 | +Once routes are defined, matching is done with `Tyre.exec`. |
| 122 | + |
| 123 | +### Details |
| 124 | + |
| 125 | +The syntax follow Perl's syntax: |
82 | 126 |
|
83 | 127 | - `re?` extracts an option of what `re` extracts.
|
84 | 128 | - `re+`, `re*`, `re{n,m}` extracts a list of what `re` extracts.
|
85 |
| -- `(?@qname)` refers to any identifier bound to a typed regular expression |
| 129 | +- `(?&qname)` refers to any identifier bound to a typed regular expression |
86 | 130 | of type `'a Tyre.t`.
|
| 131 | +- Normal parens are *non-capturing*. |
| 132 | +- There are two ways to capture: |
| 133 | + - Anonymous capture `(+re)` |
| 134 | + - Named capture `(?<v>re)` |
87 | 135 | - One or more `(?<v>re)` at the top level can be used to bind variables
|
88 | 136 | instead of `as ...`.
|
89 | 137 | - One or more `(?<v>re)` in a sequence extracts an object where each method
|
|
0 commit comments