diff options
Diffstat (limited to 'lisp/emacs-lisp/rx.el')
| -rw-r--r-- | lisp/emacs-lisp/rx.el | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/lisp/emacs-lisp/rx.el b/lisp/emacs-lisp/rx.el index 386232c6eef..b66f2c6d512 100644 --- a/lisp/emacs-lisp/rx.el +++ b/lisp/emacs-lisp/rx.el | |||
| @@ -1169,6 +1169,62 @@ enclosed in `(and ...)'. | |||
| 1169 | (rx-to-string `(and ,@regexps) t)) | 1169 | (rx-to-string `(and ,@regexps) t)) |
| 1170 | (t | 1170 | (t |
| 1171 | (rx-to-string (car regexps) t)))) | 1171 | (rx-to-string (car regexps) t)))) |
| 1172 | |||
| 1173 | |||
| 1174 | (pcase-defmacro rx (&rest regexps) | ||
| 1175 | "Build a `pcase' pattern matching `rx' regexps. | ||
| 1176 | The REGEXPS are interpreted as by `rx'. The pattern matches if | ||
| 1177 | the regular expression so constructed matches the object, as if | ||
| 1178 | by `string-match'. | ||
| 1179 | |||
| 1180 | In addition to the usual `rx' constructs, REGEXPS can contain the | ||
| 1181 | following constructs: | ||
| 1182 | |||
| 1183 | (let VAR FORM...) creates a new explicitly numbered submatch | ||
| 1184 | that matches FORM and binds the match to | ||
| 1185 | VAR. | ||
| 1186 | (backref VAR) creates a backreference to the submatch | ||
| 1187 | introduced by a previous (let VAR ...) | ||
| 1188 | construct. | ||
| 1189 | |||
| 1190 | The VARs are associated with explicitly numbered submatches | ||
| 1191 | starting from 1. Multiple occurrences of the same VAR refer to | ||
| 1192 | the same submatch. | ||
| 1193 | |||
| 1194 | If a case matches, the match data is modified as usual so you can | ||
| 1195 | use it in the case body, but you still have to pass the correct | ||
| 1196 | string as argument to `match-string'." | ||
| 1197 | (let* ((vars ()) | ||
| 1198 | (rx-constituents | ||
| 1199 | `((let | ||
| 1200 | ,(lambda (form) | ||
| 1201 | (rx-check form) | ||
| 1202 | (let ((var (cadr form))) | ||
| 1203 | (cl-check-type var symbol) | ||
| 1204 | (let ((i (or (cl-position var vars :test #'eq) | ||
| 1205 | (prog1 (length vars) | ||
| 1206 | (setq vars `(,@vars ,var)))))) | ||
| 1207 | (rx-form `(submatch-n ,(1+ i) ,@(cddr form)))))) | ||
| 1208 | 1 nil) | ||
| 1209 | (backref | ||
| 1210 | ,(lambda (form) | ||
| 1211 | (rx-check form) | ||
| 1212 | (rx-backref | ||
| 1213 | `(backref ,(let ((var (cadr form))) | ||
| 1214 | (if (integerp var) var | ||
| 1215 | (1+ (cl-position var vars :test #'eq))))))) | ||
| 1216 | 1 1 | ||
| 1217 | ,(lambda (var) | ||
| 1218 | (cond ((integerp var) (rx-check-backref var)) | ||
| 1219 | ((memq var vars) t) | ||
| 1220 | (t (error "rx `backref' variable must be one of %s: %s" | ||
| 1221 | vars var))))) | ||
| 1222 | ,@rx-constituents)) | ||
| 1223 | (regexp (rx-to-string `(seq ,@regexps) :no-group))) | ||
| 1224 | `(and (pred (string-match ,regexp)) | ||
| 1225 | ,@(cl-loop for i from 1 | ||
| 1226 | for var in vars | ||
| 1227 | collect `(app (match-string ,i) ,var))))) | ||
| 1172 | 1228 | ||
| 1173 | ;; ;; sregex.el replacement | 1229 | ;; ;; sregex.el replacement |
| 1174 | 1230 | ||