]> git.eshelyaron.com Git - emacs.git/commitdiff
Fix rx wrong-code bug: ranges starting with ^
authorMattias Engdegård <mattiase@acm.org>
Sun, 30 Jul 2023 13:30:38 +0000 (15:30 +0200)
committerMattias Engdegård <mattiase@acm.org>
Sun, 30 Jul 2023 16:12:19 +0000 (18:12 +0200)
(rx (in (?^ . ?a))) was incorrectly translated to "[^-a]".
Change it so that we get "[_-a^]" instead.

* lisp/emacs-lisp/rx.el (rx--generate-alt): Split ranges starting with
`^` occurring first in a non-negated character alternative.
* test/lisp/emacs-lisp/rx-tests.el (rx-any): Add and adapt tests.

(cherry picked from commit 5f5d668ac7917d61e9366fe0c3efd7b542671c3d)

lisp/emacs-lisp/rx.el
test/lisp/emacs-lisp/rx-tests.el

index 46f61c26bc4f8b7028f53eab85f48543bca4a539..30195cbae32463760660bf8604c3038e82eed61c 100644 (file)
@@ -445,13 +445,19 @@ classes."
           (setcar dash-l ?.))                  ; Reduce --x to .-x
         (setq items (nconc items '((?- . ?-))))))
 
-    ;; Deal with leading ^ and range ^-x.
-    (when (and (consp (car items))
-               (eq (caar items) ?^)
-               (cdr items))
-      ;; Move ^ and ^-x to second place.
-      (setq items (cons (cadr items)
-                        (cons (car items) (cddr items)))))
+    ;; Deal with leading ^ and range ^-x in non-negated set.
+    (when (and (eq (car-safe (car items)) ?^)
+               (not negated))
+      (if (eq (cdar items) ?^)
+          ;; single leading ^
+          (when (cdr items)
+            ;; Move the ^ to second place.
+            (setq items (cons (cadr items)
+                              (cons (car items) (cddr items)))))
+        ;; Split ^-x to _-x^
+        (setq items (cons (cons ?_ (cdar items))
+                          (cons '(?^ . ?^)
+                                (cdr items))))))
 
     (cond
      ;; Empty set: if negated, any char, otherwise match-nothing.
index 028250b73528b962b98d882b26c76fb01edcf8a9..9c8628a8f26d1ba7ec5f6da6e7c225cf0422587e 100644 (file)
   (should (equal (rx (any "]" "^") (any "]" "-") (any "-" "^")
                      (not (any "]" "^")) (not (any "]" "-"))
                      (not (any "-" "^")))
-                 "[]^][]-][-^][^]^][^]-][^-^]"))
+                 "[]^][]-][-^][^]^][^]-][^^-]"))
   (should (equal (rx (any "]" "^" "-") (not (any "]" "^" "-")))
                  "[]^-][^]^-]"))
+  (should (equal (rx (any "^-f") (any "^-f" "-")
+                     (any "^-f" "z") (any "^-f" "z" "-"))
+                 "[_-f^][_-f^-][_-f^z][_-f^z-]"))
+  (should (equal (rx (not (any "^-f")) (not (any "^-f" "-"))
+                     (not (any "^-f" "z")) (not (any "^-f" "z" "-")))
+                 "[^^-f][^^-f-][^^-fz][^^-fz-]"))
+  (should (equal (rx (any "^-f" word) (any "^-f" "-" word))
+                 "[_-f^[:word:]][_-f^[:word:]-]"))
+  (should (equal (rx (not (any "^-f" word)) (not (any "^-f" "-" word)))
+                 "[^^-f[:word:]][^^-f[:word:]-]"))
   (should (equal (rx (any "-" ascii) (any "^" ascii) (any "]" ascii))
                  "[[:ascii:]-][[:ascii:]^][][:ascii:]]"))
   (should (equal (rx (not (any "-" ascii)) (not (any "^" ascii))
                      (not (any "]" ascii)))
-                 "[^[:ascii:]-][^[:ascii:]^][^][:ascii:]]"))
+                 "[^[:ascii:]-][^^[:ascii:]][^][:ascii:]]"))
   (should (equal (rx (any "-]" ascii) (any "^]" ascii) (any "-^" ascii))
                  "[][:ascii:]-][]^[:ascii:]][[:ascii:]^-]"))
   (should (equal (rx (not (any "-]" ascii)) (not (any "^]" ascii))
                      (not (any "-^" ascii)))
-                 "[^][:ascii:]-][^]^[:ascii:]][^[:ascii:]^-]"))
+                 "[^][:ascii:]-][^]^[:ascii:]][^^[:ascii:]-]"))
   (should (equal (rx (any "-]^" ascii) (not (any "-]^" ascii)))
                  "[]^[:ascii:]-][^]^[:ascii:]-]"))
   (should (equal (rx (any "^" lower upper) (not (any "^" lower upper)))
-                 "[[:lower:]^[:upper:]][^[:lower:]^[:upper:]]"))
+                 "[[:lower:]^[:upper:]][^^[:lower:][:upper:]]"))
   (should (equal (rx (any "-" lower upper) (not (any "-" lower upper)))
                  "[[:lower:][:upper:]-][^[:lower:][:upper:]-]"))
   (should (equal (rx (any "]" lower upper) (not (any "]" lower upper)))
                  "[]-a-][^]-a-]"))
   (should (equal (rx (any "--]") (not (any "--]"))
                      (any "-" "^-a") (not (any "-" "^-a")))
-                 "[].-\\-][^].-\\-][-^-a][^-^-a]"))
+                 "[].-\\-][^].-\\-][_-a^-][^^-a-]"))
   (should (equal (rx (not (any "!a" "0-8" digit nonascii)))
                  "[^!0-8a[:digit:][:nonascii:]]"))
   (should (equal (rx (any) (not (any)))