emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[elpa] externals/xr 10205eb 1/5: Move to github


From: Stefan Monnier
Subject: [elpa] externals/xr 10205eb 1/5: Move to github
Date: Tue, 5 Feb 2019 10:52:03 -0500 (EST)

branch: externals/xr
commit 10205eb315c7c52aae10b023cbc70c828e513e59
Author: Mattias Engdegård <address@hidden>
Commit: Mattias Engdegård <address@hidden>

    Move to github
---
 xr.el | 657 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 657 insertions(+)

diff --git a/xr.el b/xr.el
new file mode 100644
index 0000000..bcda12b
--- /dev/null
+++ b/xr.el
@@ -0,0 +1,657 @@
+;;; xr.el --- Convert string regexp to rx notation   -*- lexical-binding: t -*-
+
+;; Author: Mattias Engdegård <mattiase at acm dot org>
+;; Version: 1.0
+;; Keywords: lisp, maint, regexps
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; This is an inverse companion to the rx package for translating
+;; regexps in string form to the rx notation.  Its chief uses are:
+;;
+;; - Migrating existing code to rx form, for better readability and
+;;   maintainability
+;; - Understanding complex regexp strings
+;;   
+;; Please refer to `rx' for more information about the notation.
+;;
+;; The exported functions are `xr', which simply returns the converted
+;; rx expression, and `xr-pp', which pretty-prints the rx expression.
+;; Suggested use is from an interactive elisp buffer.
+;;
+;; Example (regexp found in compile.el):
+;;
+;;   (xr-pp "\\`\\(?:[^^]\\|\\^\\(?: \\*\\|\\[\\)\\)")
+;; =>
+;;   (seq bos
+;;        (or
+;;         (not (any "^"))
+;;         (seq "^"
+;;              (or " *" "["))))
+;;
+;; The rx notation admits many synonyms; the xr functions mostly
+;; prefer brief variants, such as `seq' to `sequence' and `nonl' to
+;; `not-newline'.  The user is encouraged to edit the result for
+;; maximum readability, consistency and personal preference when
+;; replacing existing regexps in elisp code.
+
+;;; Code:
+
+(require 'rx)
+
+(defun xr--parse-char-alt (negated)
+  (let ((set nil))
+    (cond
+     ;; Initial ]-x range
+     ((looking-at (rx "]-" (not (any "]"))))
+      (push (match-string 0) set)
+      (goto-char (match-end 0)))
+     ;; Initial ]
+     ((looking-at "]")
+      (push "]" set)
+      (forward-char 1)))
+    (while (not (looking-at "]"))
+      (cond
+       ;; character class
+       ((looking-at (rx "[:" (group (one-or-more letter)) ":]"))
+        (let ((sym (intern (match-string 1))))
+          (when (not (memq sym
+                           '(ascii alnum alpha blank cntrl digit graph
+                             lower multibyte nonascii print punct space
+                             unibyte upper word xdigit)))
+            (error "no such character class: %s" sym))
+          (push sym set)
+          (goto-char (match-end 0))))
+       ;; character range
+       ((looking-at (rx (not (any "]")) "-" (not (any "]"))))
+        (let ((range (match-string 0)))
+          ;; We render [a-z] as (any "a-z") instead of (any (?a . ?z))
+          ;; for readability and brevity, and because the latter would
+          ;; become (97 . 122) when printed.
+          ;; TODO: Possibly convert "[0-9]" to digit, and
+          ;; "[0-9a-fA-F]" (and permutations) to hex-digit.
+          (push range set)
+          (goto-char (match-end 0))))
+       ((looking-at (rx eos))
+        (error "unterminated character alternative"))
+       ;; plain character (including ^ or -)
+       (t
+        (let* ((ch (following-char))
+               (ch-str (char-to-string ch)))
+          ;; Merge with the previous string if neither contains "-".
+          (if (and (stringp (car set))
+                   (not (eq ch ?-))
+                   (not (string-match "-" (car set))))
+              (setq set (cons (concat (car set) ch-str) (cdr set)))
+            (push ch-str set)))
+        (forward-char 1))))
+
+    (forward-char 1)                    ; eat the ]
+    (cond
+     ;; Non-negated single-char set, like [$]
+     ((and (not negated)
+           (= (length set) 1)
+           (stringp (car set))
+           (= (length (car set)) 1))
+      (car set))
+     ;; Single named class set, like [[:space:]]
+     ((and (= (length set) 1)
+           (symbolp (car set)))
+      (if negated
+          (list 'not (car set))
+        (car set)))
+     ;; Anything else.
+     (negated
+      (list 'not (cons 'any (reverse set))))
+     (t
+      (cons 'any (reverse set))))))
+
+;; Reverse a sequence, flatten any (seq ...) inside, and concatenate
+;; adjacent strings.
+(defun xr--rev-join-seq (sequence)
+  (let ((result nil))
+    (while sequence
+      (let ((elem (car sequence))
+            (rest (cdr sequence)))
+        (cond ((and (consp elem) (eq (car elem) 'seq))
+               (setq sequence (append (reverse (cdr elem)) rest)))
+              ((and (stringp elem) (stringp (car result)))
+               (setq result (cons (concat elem (car result)) (cdr result)))
+               (setq sequence rest))
+              (t
+               (setq result (cons elem result))
+               (setq sequence rest)))))
+    result))
+
+(defun xr--char-category (negated category-code)
+  (let ((sym (assq category-code
+                   '((?0 . consonant)
+                     (?1 . base-vowel)                        
+                     (?2 . upper-diacritical-mark)            
+                     (?3 . lower-diacritical-mark)            
+                     (?4 . tone-mark)                 
+                     (?5 . symbol)                            
+                     (?6 . digit)                             
+                     (?7 . vowel-modifying-diacritical-mark)  
+                     (?8 . vowel-sign)                        
+                     (?9 . semivowel-lower)                   
+                     (?< . not-at-end-of-line)                
+                     (?> . not-at-beginning-of-line)          
+                     (?A . alpha-numeric-two-byte)            
+                     (?C . chinese-two-byte)                  
+                     (?G . greek-two-byte)                    
+                     (?H . japanese-hiragana-two-byte)        
+                     (?I . indian-two-byte)                   
+                     (?K . japanese-katakana-two-byte)        
+                     (?N . korean-hangul-two-byte)            
+                     (?Y . cyrillic-two-byte)         
+                     (?^ . combining-diacritic)               
+                     (?a . ascii)                             
+                     (?b . arabic)                            
+                     (?c . chinese)                           
+                     (?e . ethiopic)                          
+                     (?g . greek)                             
+                     (?h . korean)                            
+                     (?i . indian)                            
+                     (?j . japanese)                          
+                     (?k . japanese-katakana)         
+                     (?l . latin)                             
+                     (?o . lao)                               
+                     (?q . tibetan)                           
+                     (?r . japanese-roman)                    
+                     (?t . thai)                              
+                     (?v . vietnamese)                        
+                     (?w . hebrew)                            
+                     (?y . cyrillic)                          
+                     (?| . can-break)))))
+    (when (not sym)
+      (error "unknown category code: %s" category-code))
+    (let ((item (list 'category (cdr sym))))
+      (if negated (list 'not item) item))))
+
+(defun xr--char-syntax (negated syntax-code)
+  (let ((sym (assq syntax-code
+                   '((?-  . whitespace)
+                     (?\s . whitespace)
+                     (?.  . punctuation)
+                     (?w  . word)
+                     (?_  . symbol)
+                     (?\( . open-parenthesis)
+                     (?\) . close-parenthesis)
+                     (?'  . expression-prefix)
+                     (?\" . string-quote)
+                     (?$  . paired-delimiter)
+                     (?\\ . escape)
+                     (?/  . character-quote)
+                     (?<  . comment-start)
+                     (?>  . comment-end)
+                     (?|  . string-delimiter)
+                     (?!  . comment-delimiter)))))
+    (when (not sym)
+      (error "unknown syntax code: %s" syntax-code))
+    (let ((item (list 'syntax (cdr sym))))
+      (if negated (list 'not item) item))))
+
+(defun xr--postfix (operator operand)
+  ;; We use verbose names for the common *, + and ? operators for readability,
+  ;; even though these names are affected by the rx-greedy-flag.
+  ;; For the (less common) non-greedy operators we might want to
+  ;; consider using minimal-match/maximal-match instead, but
+  ;; this would complicate the implementation.
+  (let* ((sym (cdr (assoc operator '(("*"  . zero-or-more)
+                                     ("+"  . one-or-more)
+                                     ("?"  . opt)
+                                     ("*?" . *?)
+                                     ("+?" . +?)
+                                     ("??" . ??)))))
+         ;; Simplify when the operand is (seq ...)
+         (body (if (and (listp operand) (eq (car operand) 'seq))
+                   (cdr operand)
+                 (list operand))))
+    (cons sym body)))
+
+;; Apply a repetition of {LOWER,UPPER} to OPERAND.
+;; UPPER may be nil, meaning infinity.
+(defun xr--repeat (lower upper operand)
+  ;; rx does not accept (= 0 ...) or (>= 0 ...), so we use 
+  ;; (repeat 0 0 ...) and (zero-or-more ...), respectively.
+  ;; Note that we cannot just delete the operand if LOWER=UPPER=0,
+  ;; since doing so may upset the group numbering.
+  (let* ((operator (cond ((null upper)
+                          (if (zerop lower)
+                              '(zero-or-more)
+                            (list '>= lower)))
+                         ((and (= lower upper) (> lower 0))
+                          (list '= lower))
+                         (t
+                          (list 'repeat lower upper))))
+         ;; Simplify when the operand is (seq ...).
+         (body (if (and (listp operand) (eq (car operand) 'seq))
+                   (cdr operand)
+                 (list operand))))
+    (append operator body)))
+  
+(defun xr--parse-seq ()
+  (let ((sequence nil))                 ; reversed
+    (while (not (looking-at (rx (or "\\|" "\\)" eos))))
+      (cond
+       ;; ^ - only special at beginning of sequence
+       ((and (looking-at (rx "^")) (null sequence))
+        (forward-char 1)
+        (push 'bol sequence))
+
+       ;; $ - only special at end of sequence
+       ((looking-at (rx "$" (or "\\|" "\\)" eos)))
+        (forward-char 1)
+        (push 'eol sequence))
+
+       ;; * ? + (and non-greedy variants)
+       ;; - not special at beginning of sequence or after ^
+       ((and (looking-at (rx (group (any "*?+")) (opt "?")))
+             sequence (not (eq (car sequence) 'bol)))
+        (let ((operator (match-string 0)))
+          (goto-char (match-end 0))
+          (setq sequence (cons (xr--postfix operator (car sequence))
+                               (cdr sequence)))))
+
+       ;; \{..\} - not special at beginning of sequence or after ^
+       ((and (looking-at (rx "\\{"))
+             sequence (not (eq (car sequence) 'bol)))
+        (forward-char 2)
+        (if (looking-at (rx (opt (group (one-or-more digit)))
+                            (opt (group ",")
+                                 (opt (group (one-or-more digit))))
+                            "\\}"))
+            (let ((lower (if (match-string 1)
+                             (string-to-number (match-string 1))
+                           0))
+                  (comma (match-string 2))
+                  (upper (and (match-string 3)
+                              (string-to-number (match-string 3)))))
+              (goto-char (match-end 0))
+              (setq sequence (cons (xr--repeat
+                                    lower
+                                    (if comma upper lower)
+                                    (car sequence))
+                                   (cdr sequence))))
+          (error "invalid \\{\\} syntax")))
+
+       ;; nonspecial character
+       ((looking-at (rx (not (any "\\.["))))
+        (forward-char 1)
+        (push (match-string 0) sequence))
+
+       ;; character alternative
+       ((looking-at (rx "[" (opt (group "^"))))
+        (goto-char (match-end 0))
+        (let ((negated (match-string 1)))
+          (push (xr--parse-char-alt negated) sequence)))
+
+       ;; group
+       ((looking-at (rx "\\("
+                        (opt (group "?" (group (zero-or-more digit)) ":"))))
+        (let ((question (match-string 1))
+              (number (match-string 2))
+              (end (match-end 0)))
+          (goto-char end)
+          (let* ((group (xr--parse-alt))
+                 ;; simplify - group has an implicit seq
+                 (operand (if (and (listp group) (eq (car group) 'seq))
+                              (cdr group)
+                            (list group))))
+            (when (not (looking-at (rx "\\)")))
+              (error "missing \\)"))
+            (forward-char 2)
+            (let ((item (cond ((not question)           ; plain subgroup
+                               (cons 'group operand))
+                              ((zerop (length number))  ; shy group
+                               group)
+                              (t
+                               (append (list 'group-n (string-to-number 
number))
+                                       operand)))))
+              (push item sequence)))))
+
+       ;; back-reference
+       ((looking-at (rx "\\" (group digit)))
+        (forward-char 2)
+        (push (list 'backref (string-to-number (match-string 1)))
+              sequence))
+
+       ;; various simple substitutions
+       ((looking-at (rx (or "." "\\w" "\\W" "\\`" "\\'" "\\="
+                            "\\b" "\\B" "\\<" "\\>" "\\_<" "\\_>")))
+        (goto-char (match-end 0))
+        (let ((sym (cdr (assoc
+                         (match-string 0)
+                         '(("." . nonl)
+                           ("\\w" . wordchar) ("\\W" . not-wordchar)
+                           ("\\`" . bos) ("\\'" . eos)
+                           ("\\=" . point)
+                           ("\\b" . word-boundary) ("\\B" . not-word-boundary)
+                           ("\\<" . bow) ("\\>" . eow)
+                           ("\\_<" . symbol-start) ("\\_>" . symbol-end))))))
+          (push sym sequence)))
+
+       ;; character syntax
+       ((looking-at (rx "\\" (group (any "sS")) (group anything)))
+        (let ((negated (string-equal (match-string 1) "S"))
+              (syntax-code (string-to-char (match-string 2))))
+          (goto-char (match-end 0))
+          (push (xr--char-syntax negated syntax-code) sequence)))
+
+       ;; character categories
+       ((looking-at (rx "\\" (group (any "cC")) (group anything)))
+        (let ((negated (string-equal (match-string 1) "C"))
+              (category-code (string-to-char (match-string 2))))
+          (goto-char (match-end 0))
+          (push (xr--char-category negated category-code) sequence)))
+
+       ;; Escaped character. Only \*+?.^$[ really need escaping, but we accept
+       ;; any not otherwise handled character after the backslash since
+       ;; such sequences are found in the wild.
+       ((looking-at (rx "\\" (group anything)))
+        (forward-char 2)
+        (push (match-string 1) sequence))
+
+       (t (error "backslash at end of regexp"))))
+
+    (let ((item-seq (xr--rev-join-seq sequence)))
+      (cond ((null item-seq)
+             "")
+            ((null (cdr item-seq))
+             (car item-seq))
+            (t 
+             (cons 'seq item-seq))))))
+
+(defun xr--parse-alt ()
+  (let ((alternatives nil))             ; reversed
+    (push (xr--parse-seq) alternatives)
+    (while (not (looking-at (rx (or "\\)" eos))))
+      (forward-char 2)                  ; skip \|
+      (push (xr--parse-seq) alternatives))
+    (if (cdr alternatives)
+        ;; Simplify (or nonl "\n") to anything
+        (if (or (equal alternatives '(nonl "\n"))
+                (equal alternatives '("\n" nonl)))
+            'anything
+          (cons 'or (reverse alternatives)))
+      (car alternatives))))
+
+;;;###autoload
+(defun xr (re-string)
+  "Convert a regexp string to rx notation; the inverse of `rx'.
+Passing the returned value to `rx' (or `rx-to-string') yields a regexp string
+equivalent to RE-STRING."
+  (with-temp-buffer
+    (insert re-string)
+    (goto-char (point-min))
+    (let ((rx (xr--parse-alt)))
+      (when (looking-at (rx "\\)"))
+        (error "unbalanced \\)"))
+      rx)))
+
+;; Print a rx expression to a string, unformatted.
+(defun xr--rx-to-string (rx)
+  (cond
+   ((eq rx '*?) "*?")                   ; Avoid unnecessary \ in symbol.
+   ((eq rx '+?) "+?")
+   ((consp rx)
+    ;; Render character ? as ?? when first in a list.
+    ;; Elsewhere, it's just an integer.
+    (let ((first (if (eq (car rx) ??)
+                     "??"
+                   (xr--rx-to-string (car rx))))
+          (rest (mapcar #'xr--rx-to-string (cdr rx))))
+      (concat "(" (mapconcat #'identity (cons first rest) " ") ")")))
+   ((stringp rx)
+    ;; Translate control and raw chars to escape sequences for readability.
+    ;; We prefer hex escapes (\xHH) since that is usually what the user wants,
+    ;; but use octal (\OOO) if a legitimate hex digit follows, as
+    ;; hex escapes are not limited to two digits.
+    (concat "\""
+            (replace-regexp-in-string
+             "[\x00-\x1f\"\\\x7f\x80-\xff][[:xdigit:]]?"
+             (lambda (s)
+               (let* ((c (logand (string-to-char s) #xff))
+                      (xdigit (substring s 1))
+                      (transl (assq c
+                                    '((?\" . "\\\"")
+                                      (?\\ . "\\\\")
+                                      (?\a . "\\a")
+                                      (?\b . "\\b")
+                                      (?\t . "\\t")
+                                      (?\n . "\\n")
+                                      (?\v . "\\v")
+                                      (?\f . "\\f")
+                                      (?\r . "\\r")
+                                      (?\e . "\\e")))))
+                 (concat
+                  (if transl
+                      (cdr transl)
+                    (format (if (zerop (length xdigit)) "\\x%02x" "\\%03o")
+                            c))
+                  xdigit)))
+             rx 'fixedcase 'literal)
+            "\""))
+   (t (prin1-to-string rx))))
+
+;; Pretty-print a regexp (in rx notation) to a string.
+;; It does a slightly better job than standard `pp' for rx purposes.
+(defun xr--pp-rx-to-str (rx)
+  (with-temp-buffer
+    (insert (xr--rx-to-string rx) "\n")
+    (pp-buffer)
+
+    ;; Remove the line break after "(not" for readability and compactness.
+    (goto-char (point-min))
+    (while (re-search-forward
+            (rx bol
+                (zero-or-more (any space)) "(not"
+                (group "\n" (zero-or-more (any space)))
+                (one-or-more nonl) "))"
+                eol)
+            nil t)
+      (replace-match " " t t nil 1))
+    
+    (buffer-string)))
+
+;;;###autoload
+(defun xr-pp (re-string)
+  "Convert to `rx' notation and pretty-print.
+This basically does `(pp (rx RE-STRING))', but in a slightly more readable
+way.  It is intended for use from an interactive elisp session.
+Returns nil."
+  (insert (xr--pp-rx-to-str (xr re-string))))
+
+
+(defun xr--expect-result (fun input expected)
+  "Verify (FUN INPUT) against EXPECTED."
+  (let ((got (funcall fun input)))
+    (unless (equal got expected)
+      (error "Failure in (%s %S):\ngot      %S\nexpected %S"
+             fun input got expected))))
+
+(defun xr--expect (regexp-str expected-rx)
+  "Verify (xr REGEXP-STR) against EXPECTED-RX."
+  (xr--expect-result 'xr regexp-str expected-rx))
+
+(defun xr--expect-pp (rx expected-str)
+  "Verify (xr--pp-rx-to-str RX) against EXPECTED-STR."
+  (xr--expect-result 'xr--pp-rx-to-str rx expected-str))
+
+(eval-when-compile
+  (xr--expect "a\\$b\\\\c\\[\\]\\q"
+              "a$b\\c[]q")
+  (xr--expect "\\(?:ab\\|c*d\\)?"
+              '(opt (or "ab" (seq (zero-or-more "c") "d"))))
+  (xr--expect ".+"
+              '(one-or-more nonl))
+  (xr--expect "\\(?:x?y\\)\\{3\\}"
+              '(= 3 (opt "x") "y"))
+  (xr--expect "\\(?:x?y\\)\\{3,8\\}"
+              '(repeat 3 8 (opt "x") "y"))
+  (xr--expect "\\(?:x?y\\)\\{3,\\}"
+              '(>= 3 (opt "x") "y"))
+  (xr--expect "\\(?:x?y\\)\\{,8\\}"
+              '(repeat 0 8 (opt "x") "y"))
+  (xr--expect "\\(?:xy\\)\\{4,4\\}"
+              '(= 4 "xy"))
+  (xr--expect "a\\{,\\}"
+              '(zero-or-more "a"))
+  (xr--expect "a\\{0\\}"
+              '(repeat 0 0 "a"))
+  (xr--expect "a\\{0,\\}"
+              '(zero-or-more "a"))
+  (xr--expect "a\\{0,0\\}"
+              '(repeat 0 0 "a"))
+  (xr--expect "a\\{\\}"
+              '(repeat 0 0 "a"))
+  (xr--expect "a\\{,1\\}"
+              '(repeat 0 1 "a"))
+  (xr--expect "a\\{1,\\}"
+              '(>= 1 "a"))
+  (xr--expect "\\(ab\\)\\(?3:cd\\)\\1\\3"
+              '(seq (group "ab") (group-n 3 "cd") (backref 1) (backref 3)))
+  (xr--expect "^.\\w\\W\\`\\'\\=\\b\\B\\<\\>\\_<\\_>$"
+              '(seq bol nonl wordchar not-wordchar bos eos point
+                    word-boundary not-word-boundary bow eow
+                    symbol-start symbol-end eol))
+  (xr--expect "\\s-\\s \\sw\\s_\\s.\\s(\\s)\\s\""
+              '(seq (syntax whitespace) (syntax whitespace) (syntax word)
+                    (syntax symbol) (syntax punctuation)
+                    (syntax open-parenthesis) (syntax close-parenthesis)
+                    (syntax string-quote)))
+  (xr--expect "\\s\\\\s/\\s$\\s'\\s<\\s>\\s!\\s|"
+              '(seq (syntax escape) (syntax character-quote)
+                    (syntax paired-delimiter) (syntax expression-prefix)
+                    (syntax comment-start) (syntax comment-end)
+                    (syntax comment-delimiter) (syntax string-delimiter)))
+  (xr--expect "\\S-\\S<"
+              '(seq (not (syntax whitespace))
+                    (not (syntax comment-start))))
+  (xr--expect "\\c0\\c1\\c2\\c3\\c4\\c5\\c6\\c7\\c8\\c9\\c<\\c>"
+              '(seq (category consonant) (category base-vowel)
+                    (category upper-diacritical-mark)
+                    (category lower-diacritical-mark)
+                    (category tone-mark) (category symbol) (category digit)
+                    (category vowel-modifying-diacritical-mark)
+                    (category vowel-sign) (category semivowel-lower)
+                    (category not-at-end-of-line)
+                    (category not-at-beginning-of-line)))
+  (xr--expect "\\cA\\cC\\cG\\cH\\cI\\cK\\cN\\cY\\c^"
+          '(seq (category alpha-numeric-two-byte) (category chinese-two-byte)
+                (category greek-two-byte) (category japanese-hiragana-two-byte)
+                (category indian-two-byte)
+                (category japanese-katakana-two-byte)
+                (category korean-hangul-two-byte) (category cyrillic-two-byte)
+                (category combining-diacritic)))
+  (xr--expect "\\ca\\cb\\cc\\ce\\cg\\ch\\ci\\cj\\ck\\cl\\co\\cq\\cr"
+          '(seq (category ascii) (category arabic) (category chinese)
+                (category ethiopic) (category greek) (category korean)
+                (category indian)  (category japanese)
+                (category japanese-katakana) (category latin) (category lao)
+                (category tibetan) (category japanese-roman)))
+  (xr--expect "\\ct\\cv\\cw\\cy\\c|"
+              '(seq (category thai) (category vietnamese) (category hebrew)
+                    (category cyrillic) (category can-break)))
+  (xr--expect "\\C2\\C^"
+              '(seq (not (category upper-diacritical-mark))
+                    (not (category combining-diacritic))))
+  (xr--expect "\\(?:a.\\)*?"
+              '(*? "a" nonl))
+  (xr--expect "\\(?:a.\\)+?"
+              '(+? "a" nonl))
+  (xr--expect "\\(?:a.\\)??"
+              '(?? "a" nonl))
+  (xr--expect "\\(?:.\\(a+\\(?:b+?c*\\)?\\)??\\)*"
+              '(zero-or-more
+                nonl
+                (?? (group (one-or-more "a")
+                           (opt (+? "b")
+                                (zero-or-more "c"))))))
+  (xr--expect "[[:alnum:][:blank:]][[:alpha:]][[:cntrl:][:digit:]]"
+              '(seq (any alnum blank) alpha (any cntrl digit)))
+  (xr--expect "[^[:lower:][:punct:]][^[:space:]]"
+              '(seq (not (any lower punct)) (not space)))
+  (xr--expect "^[a-z]*"
+              '(seq bol (zero-or-more (any "a-z"))))
+  (xr--expect "some[.]thing"
+              "some.thing")
+  (xr--expect "[^]-c]"
+              '(not (any "]-c")))
+  (xr--expect "[-^]"
+              '(any "-" "^"))
+  (xr--expect "[a-z-+/*%0-4[:xdigit:]]"
+              '(any "a-z" "-" "+/*%" "0-4" xdigit))
+  (xr--expect "[^]A-Za-z-]*"
+              '(zero-or-more (not (any "]" "A-Z" "a-z" "-"))))
+  (xr--expect ""
+              "")
+  (xr--expect "a\\|"
+              '(or "a" ""))
+  (xr--expect "\\|a"
+              '(or "" "a"))
+  (xr--expect "a\\|\\|b"
+              '(or "a" "" "b"))
+  (xr--expect "\\(?:.\\|\n\\)?\\(\n\\|.\\)*"
+              '(seq (opt anything) (zero-or-more (group anything))))
+  (xr--expect "\\*\\*\\* EOOH \\*\\*\\*\n"
+              "*** EOOH ***\n")
+  (xr--expect "\\<\\(catch\\|finally\\)\\>[^_]"
+              '(seq bow (group (or "catch" "finally")) eow
+                    (not (any "_"))))
+  (xr--expect "[ \t\n]*:\\([^:]+\\|$\\)"
+              '(seq (zero-or-more (any " \t\n")) ":"
+                    (group (or (one-or-more (not (any ":")))
+                               eol))))
+  (xr--expect "^a^b\\(?:^c^\\|^d^\\|e^\\)^"
+              '(seq bol "a^b" (or (seq bol "c^") (seq bol "d^") "e^") "^"))
+  (xr--expect "$a$b\\(?:$c$\\|$d$\\|$e$\\)$"
+              '(seq "$a$b" (or (seq "$c" eol) (seq "$d" eol) (seq "$e" eol))
+                    eol))
+  (xr--expect "*a\\|*b\\(*c\\)"
+              '(or "*a" (seq "*b" (group "*c"))))
+  (xr--expect "+a\\|+b\\(+c\\)"
+              '(or "+a" (seq "+b" (group "+c"))))
+  (xr--expect "?a\\|?b\\(?c\\)"
+              '(or "?a" (seq "?b" (group "?c"))))
+  (xr--expect "^**"
+              '(seq bol (zero-or-more "*")))
+  (xr--expect "^+"
+              '(seq bol "+"))
+  (xr--expect "^?"
+              '(seq bol "?"))
+  (xr--expect "*?a\\|^??b"
+              '(or (seq (opt "*") "a") (seq bol (opt "?") "b")))
+  (xr--expect "^\\{xy"
+              '(seq bol "{xy"))
+  (xr--expect "\\{2,3\\}"
+              "{2,3}")
+  (xr--expect "a\\(?:b?\\(?:c.\\)d*\\)e"
+              '(seq "a" (opt "b") "c" nonl (zero-or-more "d") "e"))
+  (xr--expect "a\\(?:b\\(?:c.d\\)e\\)f"
+              '(seq "abc" nonl "def"))
+  (xr--expect-pp "A\e\r\n\t\0 \x7f\x80\ B\xff\x02"
+                 "\"A\\e\\r\\n\\t\\x00 \\x7f\\200B\\xff\\x02\"\n")
+  (xr--expect-pp '(?? nonl)
+                 "(?? nonl)\n")
+  (xr--expect-pp '(repeat 1 63 "a")
+                 "(repeat 1 63 \"a\")\n")
+  )
+
+(provide 'xr)
+
+;;; xr.el ends here



reply via email to

[Prev in Thread] Current Thread [Next in Thread]