Warning: this is an htmlized version!
The original is here, and
the conversion rules are here.
;; This file:
;;   http://angg.twu.net/elisp/eev-peg.el.html
;;   http://angg.twu.net/elisp/eev-peg.el
;;           (find-angg "elisp/eev-peg.el")
;; Author: Eduardo Ochs <eduardoochs@gmail.com>
;;
;; "Query-replace pairs".
;;
;; (defun q () (interactive) (find-angg "elisp/eev-peg.el"))
;; (find-es "emacs" "rx")
;; (find-elnode "Rx Constructs" "(regexp EXPR)")
;; (find-angg ".emacs" "fooi")
;; (find-eev "eev-compose-hash.el")
;; (find-eev "eev-compose-hash.el" "ee-composes-do")
;; (load (buffer-file-name))


(require 'peg)

(defun find-epp-2a (obj &rest pos-spec-list)
  (find-2a nil `(find-epp ',obj ,@pos-spec-list)))

(defun find-eppm-2a (obj &rest pos-spec-list)
  (find-2a nil `(find-eppm ',obj ,@pos-spec-list)))

(defun find-pegtest (str peg)
  (find-2a nil `(progn (find-estring str) (peg-run peg))))

(defun find-pegtestm (str matcher)
  (find-2a nil `(progn (find-estring str) (eval matcher))))


;; This file needs peg.el:
;;
;;   (find-epackage-links 'peg "peg" t)
;;   (find-epackage       'peg)
;;   (code-c-d "peg" "~/.emacs.d/elpa/peg-1.0/")
;;   (find-pegfile "")
;;
;; See:
;;
;;   (find-pegfile "peg.el")
;;   (find-pegfile "peg.el" ";; Parsing Expression Grammars")
;;   (find-pegfile "peg.el" ";; Regexp equivalents:")
;;   (find-pegfile "peg.el" "(defmacro peg ")
;;   (find-pegfile "peg.el" "(defmacro peg " "Return a PEG-matcher")
;;   (find-pegfile "peg.el" "(defun peg-run ")
;;   (find-pegfile "peg.el" "(defun peg-run " "Parse with PEG-MATCHER")
;;
;; This is a PEX equivalent to the regexp "\n;; *":
;;
;;   (and "\n;;" (* " "))
;;
;; The "and" can sometimes be omitted. Try:
;;
;;                     (peg-run (peg "\n;;" (* " ")))
;;                              (peg "\n;;" (* " "))
;;                 (find-epp    (peg "\n;;" (* " ")))
;;   (find-2a nil '(find-epp    (peg "\n;;" (* " "))))
;;                 (find-epp-2a (peg "\n;;" (* " ")))
;;                 (find-epp-2a (peg "\n;;" (* " ")) "while")
;;
;;   (find-epp-2a           (peg (* (range ?a ?d))))
;;   (find-pegtest "abcdef" (peg (* (range ?a ?d))))
;;
;;
;; `ee-build-replacer'
;; ===================
;; The "replacer" associated to this list of pairs
;;
;;   (("a" "AA") ("b" "BB") ("c" "CC"))
;;
;; is a peg matcher that performs a search and replace that replaces
;; each "a" by a "AA", each "b" by a "BB", and each "c" by a "CC".
;; Replacers are easy to write using peg.el, and the replacer
;; associated to the list of pairs above is:
;;
 '    (with-peg-rules
        ((r (or (replace "a" "AA")
                (replace "b" "BB")
                (replace "c" "CC")))
         (rs (* (* (not r) (any)) r)))
	(peg-run (peg rs)))
;;
;; Try:
;;
;;   (setq mypairs '(("a" "AA") ("b" "BB") ("c" "CC")))
;;   (setq myreplacer (ee-build-replacer mypairs))
;;   (find-epp-2a  myreplacer)
;;   (find-eppm-2a myreplacer)
;;   (find-pegtestm "_a__b__c_def" myreplacer)
;;
;; Note that `myreplacer' is a sexp that starts with `with-peg-rules',
;; that is this macro:
;;
;;   (find-pegfile "peg.el" "(defmacro with-peg-rules ")
;;
;; and so we need to run it with `(eval myreplacer)', not with
;; `(peg-run myreplacer)'. Try:
;;
;;   (find-pegtest  "_a__b__c_def" myreplacer)
;;   (find-pegtestm "_a__b__c_def" myreplacer)
;;
;; The version with `find-pegtest' aborts with an "invalid function".
;;
;; ATTENTION, IMPORTANT: if you run the sexp below in this buffer
;;
;;   (eval myreplacer)
;;
;; it will replace all the "a"s, "b"s and "c"s from the end of the
;; sexp to the end of the buffer to "AA"s, "BB"s, and "CC"s - and you
;; will have to run an "undo" after running it... and this is why this
;; function `ee-replace-pairs' runs `(eval (ee-build-replacer pairs))'
;; after a narrow-to-region and inside a save-restriction.


;;



;; Test:
;; (find-epp (ee-replace-pairs-0 '(("a" "AA") ("b" "BB") ("c" "CC"))))
;;
(defun ee-build-replacer (pairs)
  "Return the replacer associated to the list of pairs PAIRS."
  (let* ((f (lambda (ab) (cons 'replace ab)))
	 (replaces (mapcar f pairs)))
    `(with-peg-rules
	 ((r  (or ,@replaces))
	  (rs (* (* (not r) (any)) r)))
       (peg-run (peg rs)))))

(defun ee-replace-pairs (pairs)
  "Replace all PAIRS in the region."
  (save-excursion
    (save-restriction
      (narrow-to-region (point) (mark))
      (goto-char (point-min))
      (eval (ee-build-replacer pairs)))))

(defun erp-test ()
  (interactive)
  (ee-replace-pairs '(("a" "AA") ("b" "BB") ("c" "CC"))))








;; Local Variables:
;; coding:  utf-8-unix
;; End: