branch: externals/xr
commit 32546a7c7eece83f486db88375b160fa050188af
Author: Mattias Engdegård <matti...@acm.org>
Commit: Mattias Engdegård <matti...@acm.org>

    Fix character alternative duplication removal
    
    Duplications such as "[aaaaa]" were not always removed correctly,
    nor were some cases of overlapping character ranges.
    
    Reported by Shigeru Fukaya.
---
 xr-test.el |  4 ++++
 xr.el      | 80 ++++++++++++++++++++++++++++++--------------------------------
 2 files changed, 43 insertions(+), 41 deletions(-)

diff --git a/xr-test.el b/xr-test.el
index d62d02d..90e5be2 100644
--- a/xr-test.el
+++ b/xr-test.el
@@ -197,6 +197,10 @@
   (should-error (xr "[[:=:]]"))
   (should-error (xr "[[:letter:]]"))
   (should-error (xr "[a-f"))
+  (should (equal (xr "[aaaaaa][bananabanana][aaaa-cccc][a-ca-ca-c]")
+                 '(seq "a" (any "abn") (any "a-c") (any "a-c"))))
+  (should (equal (xr "[a-fb-gc-h][a-fc-kh-p]")
+                 '(seq (any "a-h") (any "a-p"))))
   )
 
 (ert-deftest xr-empty ()
diff --git a/xr.el b/xr.el
index 03ab308..d314f9d 100644
--- a/xr.el
+++ b/xr.el
@@ -192,47 +192,45 @@
       (while (cdr s)
         (let ((this (car s))
               (next (cadr s)))
-          (when (>= (aref this 1) (aref next 0))
-            (let ((message
-                   (cond
-                    ;; Duplicate character: drop it and warn.
-                    ((and (eq (aref this 0) (aref this 1))
-                          (eq (aref next 0) (aref next 1)))
-                     (setcdr s (cddr s))
-                     (format-message
-                      "Duplicated `%c' inside character alternative"
-                      (aref this 0)))
-                    ;; Duplicate range: drop it and warn.
-                    ((and (eq (aref this 0) (aref next 0))
-                          (eq (aref this 1) (aref next 1)))
-                     (setcdr s (cddr s))
-                     (format-message
-                      "Duplicated `%c-%c' inside character alternative"
-                      (aref this 0) (aref this 1)))
-                    ;; Character in range: drop it and warn.
-                    ((eq (aref this 0) (aref this 1))
-                     (setcar s next)
-                     (setcdr s (cddr s))
-                     (format-message
-                      "Character `%c' included in range `%c-%c'"
-                      (aref this 0) (aref next 0) (aref next 1)))
-                    ;; Same but other way around.
-                    ((eq (aref next 0) (aref next 1))
-                     (setcdr s (cddr s))
-                     (format-message
-                      "Character `%c' included in range `%c-%c'"
-                      (aref next 0) (aref this 0) (aref this 1)))
-                    ;; Overlapping ranges: merge and warn.
-                    (t
-                     (let ((this-end (aref this 1)))
-                       (aset this 1 (max (aref this 1) (aref next 1)))
-                       (setcdr s (cddr s))
-                       (format-message "Ranges `%c-%c' and `%c-%c' overlap"
-                                       (aref this 0) this-end
-                                       (aref next 0) (aref next 1)))))))
-              (xr--report warnings (max (aref this 2) (aref next 2))
-                          (xr--escape-string message nil)))))
-        (setq s (cdr s)))
+          (if (>= (aref this 1) (aref next 0))
+              ;; Overlap.
+              (let ((message
+                     (cond
+                      ;; Duplicate character: drop it and warn.
+                      ((and (eq (aref this 0) (aref this 1))
+                            (eq (aref next 0) (aref next 1)))
+                       (format-message
+                        "Duplicated `%c' inside character alternative"
+                        (aref this 0)))
+                      ;; Duplicate range: drop it and warn.
+                      ((and (eq (aref this 0) (aref next 0))
+                            (eq (aref this 1) (aref next 1)))
+                       (format-message
+                        "Duplicated `%c-%c' inside character alternative"
+                        (aref this 0) (aref this 1)))
+                      ;; Character in range: drop it and warn.
+                      ((eq (aref this 0) (aref this 1))
+                       (setcar s next)
+                       (format-message
+                        "Character `%c' included in range `%c-%c'"
+                        (aref this 0) (aref next 0) (aref next 1)))
+                      ;; Same but other way around.
+                      ((eq (aref next 0) (aref next 1))
+                       (format-message
+                        "Character `%c' included in range `%c-%c'"
+                        (aref next 0) (aref this 0) (aref this 1)))
+                      ;; Overlapping ranges: merge and warn.
+                      (t
+                       (let ((this-end (aref this 1)))
+                         (aset this 1 (max (aref this 1) (aref next 1)))
+                         (format-message "Ranges `%c-%c' and `%c-%c' overlap"
+                                         (aref this 0) this-end
+                                         (aref next 0) (aref next 1)))))))
+                (xr--report warnings (max (aref this 2) (aref next 2))
+                            (xr--escape-string message nil))
+                (setcdr s (cddr s)))
+            ;; No overlap.
+            (setq s (cdr s)))))
             
       ;; Gather ranges and single characters separately.
       ;; We make no attempts at merging adjacent intervals/characters,

Reply via email to