61 |
;; "^content-transfer-encoding:\\(\n?[\t ]\\)*quoted-printable\\(\n?[\t ]\\)*" |
;; "^content-transfer-encoding:\\(\n?[\t ]\\)*quoted-printable\\(\n?[\t ]\\)*" |
62 |
;; (rx (and line-start |
;; (rx (and line-start |
63 |
;; "content-transfer-encoding:" |
;; "content-transfer-encoding:" |
64 |
;; (+ (? ?\n) blank) |
;; (+ (? ?\n)) blank |
65 |
;; "quoted-printable" |
;; "quoted-printable" |
66 |
;; (+ (? ?\n) blank)) |
;; (+ (? ?\n)) blank)) |
67 |
;; |
;; |
68 |
;; (concat "^\\(?:" something-else "\\)") |
;; (concat "^\\(?:" something-else "\\)") |
69 |
;; (rx (and line-start (eval something-else))), statically or |
;; (rx (and line-start (eval something-else))), statically or |
78 |
;; (and line-start ?\n))) |
;; (and line-start ?\n))) |
79 |
;; |
;; |
80 |
;; "\\$[I]d: [^ ]+ \\([^ ]+\\) " |
;; "\\$[I]d: [^ ]+ \\([^ ]+\\) " |
81 |
;; (rx (and "$Id": " |
;; (rx (and " " |
82 |
;; (1+ (not (in " "))) |
;; (1+ (not (in " "))) |
83 |
;; " " |
;; " " |
84 |
;; (submatch (1+ (not (in " ")))) |
;; (submatch (1+ (not (in " ")))) |
85 |
;; " "))) |
;; " ")) |
86 |
;; |
;; |
87 |
;; "\\\\\\\\\\[\\w+" |
;; "\\\\\\\\\\[\\w+" |
88 |
;; (rx (and ?\\ ?\\ ?\[ (1+ word))) |
;; (rx (and ?\\ ?\\ ?\[ (1+ word))) |
90 |
;; etc. |
;; etc. |
91 |
|
|
92 |
;;; History: |
;;; History: |
93 |
;; |
;; |
94 |
|
|
95 |
;;; Code: |
;;; Code: |
96 |
|
|
244 |
(while (and (not (null op)) (symbolp op)) |
(while (and (not (null op)) (symbolp op)) |
245 |
(setq op (cdr (assq op rx-constituents)))) |
(setq op (cdr (assq op rx-constituents)))) |
246 |
op) |
op) |
247 |
|
|
248 |
|
|
249 |
(defun rx-check (form) |
(defun rx-check (form) |
250 |
"Check FORM according to its car's parsing info." |
"Check FORM according to its car's parsing info." |
272 |
"Parse and produce code from FORM. |
"Parse and produce code from FORM. |
273 |
FORM is of the form `(and FORM1 ...)'." |
FORM is of the form `(and FORM1 ...)'." |
274 |
(rx-check form) |
(rx-check form) |
275 |
(mapconcat #'rx-to-string (cdr form) nil)) |
(concat "\\(?:" |
276 |
|
(mapconcat |
277 |
|
(function (lambda (x) (rx-to-string x 'no-group))) |
278 |
|
(cdr form) nil) |
279 |
|
"\\)")) |
280 |
|
|
281 |
|
|
282 |
(defun rx-or (form) |
(defun rx-or (form) |
388 |
|
|
389 |
(defun rx-submatch (form) |
(defun rx-submatch (form) |
390 |
"Parse and produce code from FORM, which is `(submatch ...)'." |
"Parse and produce code from FORM, which is `(submatch ...)'." |
391 |
(concat "\\(" (mapconcat #'rx-to-string (cdr form) nil) "\\)")) |
(concat "\\(" |
392 |
|
(mapconcat (function (lambda (x) (rx-to-string x 'no-group))) |
393 |
|
(cdr form) nil) |
394 |
|
"\\)")) |
395 |
|
|
396 |
(defun rx-kleene (form) |
(defun rx-kleene (form) |
397 |
"Parse and produce code from FORM. |
"Parse and produce code from FORM. |
398 |
FORM is `(OP FORM1)', where OP is one of the `zero-or-one', |
FORM is `(OP FORM1)', where OP is one of the `zero-or-one', |
399 |
`zero-or-more' etc. operators. |
`zero-or-more' etc. operators. |
400 |
If OP is one of `*', `+', `?', produce a greedy regexp. |
If OP is one of `*', `+', `?', produce a greedy regexp. |
401 |
If OP is one of `*?', `+?', `??', produce a non-greedy regexp. |
If OP is one of `*?', `+?', `??', produce a non-greedy regexp. |
402 |
If OP is anything else, produce a greedy regexp if `rx-greedy-flag' |
If OP is anything else, produce a greedy regexp if `rx-greedy-flag' |
408 |
(t "?"))) |
(t "?"))) |
409 |
(op (cond ((memq (car form) '(* *? 0+ zero-or-more)) "*") |
(op (cond ((memq (car form) '(* *? 0+ zero-or-more)) "*") |
410 |
((memq (car form) '(+ +? 1+ one-or-more)) "+") |
((memq (car form) '(+ +? 1+ one-or-more)) "+") |
411 |
(t "?")))) |
(t "?"))) |
412 |
(format "\\(?:%s\\)%s%s" (rx-to-string (cadr form) 'no-group) |
(result (rx-to-string (cadr form) 'no-group))) |
413 |
op suffix))) |
(if (not (rx-atomic-p result)) |
414 |
|
(setq result (concat "\\(?:" result "\\)"))) |
415 |
|
(concat result op suffix))) |
416 |
|
|
417 |
|
(defun rx-atomic-p (r) |
418 |
|
"Return non-nil if regexp string R is atomic. |
419 |
|
An atomic regexp R is one such that a suffix operator |
420 |
|
appended to R will apply to all of R. For example, \"a\" |
421 |
|
\"[abc]\" and \"\\(ab\\|ab*c\\)\" are atomic and \"ab\", |
422 |
|
\"[ab]c\", and \"ab\\|ab*c\" are not atomic. |
423 |
|
|
424 |
|
This function may return false negatives, but it will not |
425 |
|
return false positives. It is nevertheless useful in |
426 |
|
situations where an efficiency shortcut can be taken iff a |
427 |
|
regexp is atomic. The function can be improved to detect |
428 |
|
more cases of atomic regexps. Presently, this function |
429 |
|
detects the following categories of atomic regexp; |
430 |
|
|
431 |
|
a group or shy group: \\(...\\) |
432 |
|
a character class: [...] |
433 |
|
a single character: a |
434 |
|
|
435 |
|
On the other hand, false negatives will be returned for |
436 |
|
regexps that are atomic but end in operators, such as |
437 |
|
\"a+\". I think these are rare. Probably such cases could |
438 |
|
be detected without much effort. A guarantee of no false |
439 |
|
negatives would require a theoretic specification of the set |
440 |
|
of all atomic regexps." |
441 |
|
(let ((l (length r))) |
442 |
|
(or (equal l 1) |
443 |
|
(and (>= l 6) |
444 |
|
(equal (substring r 0 2) "\\(") |
445 |
|
(equal (substring r -2) "\\)")) |
446 |
|
(and (>= l 2) |
447 |
|
(equal (substring r 0 1) "[") |
448 |
|
(equal (substring r -1) "]"))))) |
449 |
|
|
450 |
|
|
451 |
(defun rx-syntax (form) |
(defun rx-syntax (form) |
463 |
(cdr (assq form rx-categories))) |
(cdr (assq form rx-categories))) |
464 |
(error "Unknown category `%s'" form)) |
(error "Unknown category `%s'" form)) |
465 |
t) |
t) |
466 |
|
|
467 |
|
|
468 |
(defun rx-category (form) |
(defun rx-category (form) |
469 |
"Parse and produce code from FORM, which is `(category SYMBOL ...)'." |
"Parse and produce code from FORM, which is `(category SYMBOL ...)'." |
511 |
info) |
info) |
512 |
((null info) |
((null info) |
513 |
(error "Unknown Rx form `%s'" form)) |
(error "Unknown Rx form `%s'" form)) |
514 |
(t |
(t |
515 |
(funcall (nth 0 info) form))))) |
(funcall (nth 0 info) form))))) |
516 |
((consp form) |
((consp form) |
517 |
(let ((info (rx-info (car form)))) |
(let ((info (rx-info (car form)))) |
549 |
matches any character in SET. SET may be a character or string. |
matches any character in SET. SET may be a character or string. |
550 |
Ranges of characters can be specified as `A-Z' in strings. |
Ranges of characters can be specified as `A-Z' in strings. |
551 |
|
|
552 |
'(in SET)' |
'(in SET)' |
553 |
like `any'. |
like `any'. |
554 |
|
|
555 |
`(not (any SET))' |
`(not (any SET))' |
735 |
still match. A non-greedy regexp matches as little as possible. |
still match. A non-greedy regexp matches as little as possible. |
736 |
|
|
737 |
`(maximal-match SEXP)' |
`(maximal-match SEXP)' |
738 |
produce a greedy regexp for SEXP. This is the default. |
produce a greedy regexp for SEXP. This is the default. |
739 |
|
|
740 |
`(zero-or-more SEXP)' |
`(zero-or-more SEXP)' |
741 |
matches zero or more occurrences of what SEXP matches. |
matches zero or more occurrences of what SEXP matches. |
751 |
|
|
752 |
`(one-or-more SEXP)' |
`(one-or-more SEXP)' |
753 |
matches one or more occurrences of A. |
matches one or more occurrences of A. |
754 |
|
|
755 |
`(1+ SEXP)' |
`(1+ SEXP)' |
756 |
like `one-or-more'. |
like `one-or-more'. |
757 |
|
|
763 |
|
|
764 |
`(zero-or-one SEXP)' |
`(zero-or-one SEXP)' |
765 |
matches zero or one occurrences of A. |
matches zero or one occurrences of A. |
766 |
|
|
767 |
`(optional SEXP)' |
`(optional SEXP)' |
768 |
like `zero-or-one'. |
like `zero-or-one'. |
769 |
|
|
780 |
matches N to M occurrences of what SEXP matches. |
matches N to M occurrences of what SEXP matches. |
781 |
|
|
782 |
`(eval FORM)' |
`(eval FORM)' |
783 |
evaluate FORM and insert result. If result is a string, |
evaluate FORM and insert result. If result is a string, |
784 |
`regexp-quote' it. |
`regexp-quote' it. |
785 |
|
|
786 |
`(regexp REGEXP)' |
`(regexp REGEXP)' |