Function: rx--translate-or

rx--translate-or is a byte-compiled function defined in rx.el.gz.

Signature

(rx--translate-or BODY)

Documentation

Translate an or-pattern of zero or more rx items.

Return (REGEXP . PRECEDENCE).

Source Code

;; Defined in /usr/src/emacs/lisp/emacs-lisp/rx.el.gz
;; TODO: Write a more general rx-level factoriser to replace
;; `regexp-opt' for our purposes.  It would handle non-literals:
;;
;;    (or "ab" (: "a" space) "bc" (: "b" (+ digit)))
;; -> (or (: "a" (in "b" space)) (: "b" (or "c" (+ digit))))
;;
;; As a minor side benefit we would get less useless bracketing.
;; The main problem is how to deal with matching order, which `regexp-opt'
;; alters in its own way.

(defun rx--translate-or (body)
  "Translate an or-pattern of zero or more rx items.
Return (REGEXP . PRECEDENCE)."
  (cond
   ((null body)                    ; No items: a never-matching regexp.
    (rx--empty))
   ((null (cdr body))              ; Single item.
    (rx--translate (car body)))
   (t
    (let ((args (mapcar #'rx--normalize-char-pattern body)))
      (if (rx--all-string-branches-p args)
          ;; All branches are strings: use `regexp-opt'.
          (cons (list (regexp-opt (rx--collect-or-strings args) nil))
                t)
        (let ((form (rx--optimize-or-args args)))
          (if (eq (car-safe form) 'or)
              (let ((branches (cdr form)))
                (cons (append (car (rx--translate (car branches)))
                              (mapcan (lambda (item)
                                        (cons "\\|" (car (rx--translate item))))
                                      (cdr branches)))
                      nil))
            (rx--translate form))))))))