From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.ciao.gmane.io!not-for-mail From: Mattias =?UTF-8?Q?Engdeg=C3=A5rd?= Newsgroups: gmane.emacs.bugs Subject: bug#37659: rx additions: anychar, unmatchable, unordered-or Date: Tue, 11 Feb 2020 20:17:50 +0100 Message-ID: References: <88571301-3F15-428F-82F9-60A23D817EF8@acm.org> <2F3A70C9-969B-4E86-998E-BF3CC990B769@acm.org> <838sl9ruxe.fsf@gnu.org> Mime-Version: 1.0 (Mac OS X Mail 12.4 \(3445.104.11\)) Content-Type: multipart/mixed; boundary="Apple-Mail=_1859A414-62A6-4E9B-BBF2-E05A74BBEEA4" Injection-Info: ciao.gmane.io; posting-host="ciao.gmane.io:159.69.161.202"; logging-data="70520"; mail-complaints-to="usenet@ciao.gmane.io" Cc: psainty@orcon.net.nz, Paul Eggert , 37659@debbugs.gnu.org To: Eli Zaretskii Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Tue Feb 11 20:19:20 2020 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1j1b44-000IF5-Gw for geb-bug-gnu-emacs@m.gmane-mx.org; Tue, 11 Feb 2020 20:19:20 +0100 Original-Received: from localhost ([::1]:56258 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1j1b43-0003wL-6h for geb-bug-gnu-emacs@m.gmane-mx.org; Tue, 11 Feb 2020 14:19:19 -0500 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]:49933) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1j1b3o-0003wA-Hv for bug-gnu-emacs@gnu.org; Tue, 11 Feb 2020 14:19:06 -0500 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1j1b3m-00073K-Jy for bug-gnu-emacs@gnu.org; Tue, 11 Feb 2020 14:19:03 -0500 Original-Received: from debbugs.gnu.org ([209.51.188.43]:51589) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1j1b3m-00073C-GN for bug-gnu-emacs@gnu.org; Tue, 11 Feb 2020 14:19:02 -0500 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1j1b3m-00029I-Bm for bug-gnu-emacs@gnu.org; Tue, 11 Feb 2020 14:19:02 -0500 X-Loop: help-debbugs@gnu.org Resent-From: Mattias =?UTF-8?Q?Engdeg=C3=A5rd?= Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Tue, 11 Feb 2020 19:19:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 37659 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: patch Original-Received: via spool by 37659-submit@debbugs.gnu.org id=B37659.15814486938192 (code B ref 37659); Tue, 11 Feb 2020 19:19:02 +0000 Original-Received: (at 37659) by debbugs.gnu.org; 11 Feb 2020 19:18:13 +0000 Original-Received: from localhost ([127.0.0.1]:57562 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1j1b2z-000284-7i for submit@debbugs.gnu.org; Tue, 11 Feb 2020 14:18:13 -0500 Original-Received: from mail1460c50.megamailservers.eu ([91.136.14.60]:42364 helo=mail267c50.megamailservers.eu) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1j1b2x-00027p-3Z for 37659@debbugs.gnu.org; Tue, 11 Feb 2020 14:18:12 -0500 X-Authenticated-User: mattiase@bredband.net DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=megamailservers.eu; s=maildub; t=1581448675; bh=fAIo6LGxWhNiwz9YIGFlq24iMmfYCogcywuvURa7qHc=; h=From:Subject:Date:In-Reply-To:Cc:To:References:From; b=fTid0jh5K3FVzlEm7/7N3B4sSPqUCjSqs8nS+d0qJrTGAPOgI/ieNPrIDhT6fRlUx MqBmq4+D1FcjEfBoMoRKfgLLL0W4hg209blOk6WCQkK5f4dLBv9MPR6/2ivCvmND9Z JTRnsqZa8XkDProihGKoz3o2z7dfq0piP3AVSM9A= Feedback-ID: mattiase@acm.or Original-Received: from stanniol.lan (c-6f4fe655.032-75-73746f71.bbcust.telenor.se [85.230.79.111]) (authenticated bits=0) by mail267c50.megamailservers.eu (8.14.9/8.13.1) with ESMTP id 01BJHpmG006792; Tue, 11 Feb 2020 19:17:53 +0000 In-Reply-To: <838sl9ruxe.fsf@gnu.org> X-Mailer: Apple Mail (2.3445.104.11) X-CTCH-RefID: str=0001.0A0B0207.5E42FDE3.0010, ss=1, re=0.000, recu=0.000, reip=0.000, cl=1, cld=1, fgs=0 X-CTCH-VOD: Unknown X-CTCH-Spam: Unknown X-CTCH-Score: 0.000 X-CTCH-Flags: 0 X-CTCH-ScoreCust: 0.000 X-CSC: 0 X-CHA: v=2.3 cv=OY7m8SbY c=1 sm=1 tr=0 a=fHaj9vQUQVKQ4sUldAaXuQ==:117 a=fHaj9vQUQVKQ4sUldAaXuQ==:17 a=jpOVt7BSZ2e4Z31A5e1TngXxSK0=:19 a=M51BFTxLslgA:10 a=mDV3o1hIAAAA:8 a=ZqXousmFQ0sRKU_ZFBwA:9 a=CjuIK1q_8ugA:10 a=ugqdcGqvHB9wOvkMhVYA:9 a=B2y7HmGcmWMA:10 a=_FVE-zBwftR9WsbkzFJk:22 X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.51.188.43 X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Original-Sender: "bug-gnu-emacs" Xref: news.gmane.io gmane.emacs.bugs:175953 Archived-At: --Apple-Mail=_1859A414-62A6-4E9B-BBF2-E05A74BBEEA4 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=us-ascii 11 feb. 2020 kl. 16.43 skrev Eli Zaretskii : > Can't say I'm happy with these last-minute experiments, but okay. Thanks, and I think it's actually a lesser experiment than status quo = ante. I'm allowing for more comments before pushing it; meanwhile, here is the = follow-up patch mentioned earlier. --Apple-Mail=_1859A414-62A6-4E9B-BBF2-E05A74BBEEA4 Content-Disposition: attachment; filename=0001-rx-Improve-or-compositionality.patch Content-Type: application/octet-stream; x-unix-mode=0644; name="0001-rx-Improve-or-compositionality.patch" Content-Transfer-Encoding: quoted-printable =46rom=20dc4aadfdacc2466420833281c5374279eee03aca=20Mon=20Sep=2017=20= 00:00:00=202001=0AFrom:=20=3D?UTF-8?q?Mattias=3D20Engdeg=3DC3=3DA5rd?=3D=20= =0ADate:=20Tue,=2011=20Feb=202020=2020:04:42=20+0100=0A= Subject:=20[PATCH]=20rx:=20Improve=20'or'=20compositionality=0A=0A= Perform=20'regexp-opt'=20on=20nested=20'or'=20forms,=20and=20after=20= expansion=20of=0Auser-defined=20and=20'eval'=20forms.=20=20Characters=20= are=20now=20turned=20into=0Astrings=20for=20wider=20'regexp-opt'=20= scope.=0A=0A*=20doc/lispref/searching.texi=20(Rx=20Constructs):=20= Document.=0A*=20lisp/emacs-lisp/rx.el=20(rx--normalise-or-arg)=0A= rx--all-string-or-args):=20New.=0A(rx--translate-or):=20Normalise=20= arguments=20first,=20and=20check=20for=20strings=0Ain=20subforms.=0A= (rx--expand-eval):=20Extracted=20from=20rx--translate-eval.=0A= (rx--translate-eval):=20Call=20rx--expand-eval.=0A---=0A=20= doc/lispref/searching.texi=20=20=20=20=20=20=20|=20=205=20++-=0A=20= lisp/emacs-lisp/rx.el=20=20=20=20=20=20=20=20=20=20=20=20|=2076=20= ++++++++++++++++++++------------=0A=20test/lisp/emacs-lisp/rx-tests.el=20= |=2013=20+++++-=0A=203=20files=20changed,=2063=20insertions(+),=2031=20= deletions(-)=0A=0Adiff=20--git=20a/doc/lispref/searching.texi=20= b/doc/lispref/searching.texi=0Aindex=205f4509a8b4..526ee77d40=20100644=0A= ---=20a/doc/lispref/searching.texi=0A+++=20b/doc/lispref/searching.texi=0A= @@=20-1081,8=20+1081,9=20@@=20Rx=20Constructs=0A=20@itemx=20@code{(|=20= @var{rx}@dots{})}=0A=20@cindex=20@code{|}=20in=20rx=0A=20Match=20exactly=20= one=20of=20the=20@var{rx}s.=0A-If=20all=20arguments=20are=20string=20= literals,=20the=20longest=20possible=20match=0A-will=20always=20be=20= used.=20=20Otherwise,=20either=20the=20longest=20match=20or=20the=0A+If=20= all=20arguments=20are=20strings,=20characters,=20or=20@code{or}=20forms=0A= +so=20constrained,=20the=20longest=20possible=20match=20will=20always=20= be=20used.=0A+Otherwise,=20either=20the=20longest=20match=20or=20the=0A=20= first=20(in=20left-to-right=20order)=20will=20be=20used.=0A=20Without=20= arguments,=20the=20expression=20will=20not=20match=20anything=20at=20= all.@*=0A=20Corresponding=20string=20regexp:=20= @samp{@var{A}\|@var{B}\|@dots{}}.=0Adiff=20--git=20= a/lisp/emacs-lisp/rx.el=20b/lisp/emacs-lisp/rx.el=0Aindex=20= b4cab5715d..7a7d09f10b=20100644=0A---=20a/lisp/emacs-lisp/rx.el=0A+++=20= b/lisp/emacs-lisp/rx.el=0A@@=20-254,22=20+254,39=20@@=20rx--foldl=0A=20=20= =20=20=20(setq=20l=20(cdr=20l)))=0A=20=20=20x)=0A=20=0A+(defun=20= rx--normalise-or-arg=20(form)=0A+=20=20"Normalise=20the=20`or'=20= argument=20FORM.=0A+Characters=20become=20strings,=20user-definitions=20= and=20`eval'=20forms=20are=20expanded,=0A+and=20`or'=20forms=20are=20= normalised=20recursively."=0A+=20=20(cond=20((characterp=20form)=0A+=20=20= =20=20=20=20=20=20=20(char-to-string=20form))=0A+=20=20=20=20=20=20=20=20= ((and=20(consp=20form)=20(memq=20(car=20form)=20'(or=20|)))=0A+=20=20=20=20= =20=20=20=20=20(cons=20(car=20form)=20(mapcar=20#'rx--normalise-or-arg=20= (cdr=20form))))=0A+=20=20=20=20=20=20=20=20((and=20(consp=20form)=20(eq=20= (car=20form)=20'eval))=0A+=20=20=20=20=20=20=20=20=20= (rx--normalise-or-arg=20(rx--expand-eval=20(cdr=20form))))=0A+=20=20=20=20= =20=20=20=20(t=0A+=20=20=20=20=20=20=20=20=20(let=20((expanded=20= (rx--expand-def=20form)))=0A+=20=20=20=20=20=20=20=20=20=20=20(if=20= expanded=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (rx--normalise-or-arg=20expanded)=0A+=20=20=20=20=20=20=20=20=20=20=20=20= =20form)))))=0A+=0A+(defun=20rx--all-string-or-args=20(body)=0A+=20=20= "If=20BODY=20only=20consists=20of=20strings=20or=20such=20`or'=20forms,=20= return=20all=20the=20strings.=0A+Otherwise=20throw=20`rx--nonstring'."=0A= +=20=20(mapcan=20(lambda=20(form)=0A+=20=20=20=20=20=20=20=20=20=20=20=20= (cond=20((stringp=20form)=20(list=20form))=0A+=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20((and=20(consp=20form)=20(memq=20(car=20form)=20= '(or=20|)))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (rx--all-string-or-args=20(cdr=20form)))=0A+=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20(t=20(throw=20'rx--nonstring=20nil))))=0A+=20=20=20= =20=20=20=20=20=20=20body))=0A+=0A=20(defun=20rx--translate-or=20(body)=0A= =20=20=20"Translate=20an=20or-pattern=20of=20zero=20or=20more=20rx=20= items.=0A=20Return=20(REGEXP=20.=20PRECEDENCE)."=0A=20=20=20;;=20FIXME:=20= Possible=20improvements:=0A=20=20=20;;=0A-=20=20;;=20-=20Turn=20single=20= characters=20to=20strings:=20(or=20?a=20?b)=20->=20(or=20"a"=20"b"),=0A-=20= =20;;=20=20=20so=20that=20they=20can=20be=20candidates=20for=20= regexp-opt.=0A-=20=20;;=0A-=20=20;;=20-=20Translate=20compile-time=20= strings=20(`eval'=20forms),=20again=20for=20regexp-opt.=0A-=20=20;;=0A=20= =20=20;;=20-=20Flatten=20sub-patterns=20first:=20(or=20(or=20A=20B)=20= (or=20C=20D))=20->=20(or=20A=20B=20C=20D)=0A-=20=20;;=20=20=20in=20order=20= to=20improve=20effectiveness=20of=20regexp-opt.=0A-=20=20;;=20=20=20This=20= would=20also=20help=20composability.=0A-=20=20;;=0A-=20=20;;=20-=20Use=20= associativity=20to=20run=20regexp-opt=20on=20contiguous=20subsets=20of=20= arguments=0A-=20=20;;=20=20=20if=20not=20all=20of=20them=20are=20= strings.=20=20Example:=0A+=20=20;;=20=20=20Then=20call=20regexp-opt=20on=20= runs=20of=20string=20arguments.=20Example:=0A=20=20=20;;=20=20=20(or=20= (+=20digit)=20"CHARLIE"=20"CHAN"=20(+=20blank))=0A=20=20=20;;=20=20=20->=20= (or=20(+=20digit)=20(or=20"CHARLIE"=20"CHAN")=20(+=20blank))=0A=20=20=20= ;;=0A@@=20-279,27=20+296,26=20@@=20rx--translate-or=0A=20=20=20;;=20=20=20= so=20that=20(or=20"@"=20"%"=20digit=20(any=20"A-Z"=20space)=20(syntax=20= word))=0A=20=20=20;;=20=20=20=20=20=20=20=20->=20(any=20"@"=20"%"=20= digit=20"A-Z"=20space=20word)=0A=20=20=20;;=20=20=20=20=20=20=20=20->=20= "[A-Z@%[:digit:][:space:][:word:]]"=0A-=20=20;;=0A-=20=20;;=20Problem:=20= If=20a=20subpattern=20is=20carefully=20written=20to=20be=0A-=20=20;;=20= optimizable=20by=20regexp-opt,=20how=20do=20we=20prevent=20the=20= transforms=0A-=20=20;;=20above=20from=20destroying=20that=20property?=0A= -=20=20;;=20Example:=20(or=20"a"=20(or=20"abc"=20"abd"=20"abe"))=0A=20=20= =20(cond=0A=20=20=20=20((null=20body)=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20;=20No=20items:=20a=20never-matching=20regexp.=0A= =20=20=20=20=20(rx--empty))=0A=20=20=20=20((null=20(cdr=20body))=20=20=20= =20=20=20=20=20=20=20=20=20=20=20;=20Single=20item.=0A=20=20=20=20=20= (rx--translate=20(car=20body)))=0A-=20=20=20((rx--every=20#'stringp=20= body)=20=20=20=20=20;=20All=20strings.=0A-=20=20=20=20(cons=20(list=20= (regexp-opt=20body=20nil))=0A-=20=20=20=20=20=20=20=20=20=20t))=0A-=20=20= =20((rx--every=20#'rx--charset-p=20body)=20=20;=20All=20charsets.=0A-=20=20= =20=20(rx--translate-union=20nil=20body))=0A=20=20=20=20(t=0A-=20=20=20=20= (cons=20(append=20(car=20(rx--translate=20(car=20body)))=0A-=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20(mapcan=20(lambda=20(item)=0A-=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20(cons=20"\\|"=20(car=20(rx--translate=20item))))=0A-=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(cdr=20= body)))=0A-=20=20=20=20=20=20=20=20=20=20nil))))=0A+=20=20=20=20(let*=20= ((args=20(mapcar=20#'rx--normalise-or-arg=20body))=0A+=20=20=20=20=20=20=20= =20=20=20=20(all-strings=20(catch=20'rx--nonstring=20= (rx--all-string-or-args=20args))))=0A+=20=20=20=20=20=20(cond=0A+=20=20=20= =20=20=20=20(all-strings=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20;=20Only=20strings.=0A+=20=20=20=20=20=20=20=20(cons=20= (list=20(regexp-opt=20all-strings=20nil))=0A+=20=20=20=20=20=20=20=20=20=20= =20=20=20=20t))=0A+=20=20=20=20=20=20=20((rx--every=20#'rx--charset-p=20= args)=20=20;=20All=20charsets.=0A+=20=20=20=20=20=20=20=20= (rx--translate-union=20nil=20args))=0A+=20=20=20=20=20=20=20(t=0A+=20=20=20= =20=20=20=20=20(cons=20(append=20(car=20(rx--translate=20(car=20args)))=0A= +=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (mapcan=20(lambda=20(item)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(cons=20"\\|"=20(car=20= (rx--translate=20item))))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(cdr=20args)))=0A+=20=20=20=20= =20=20=20=20=20=20=20=20=20=20nil)))))))=0A=20=0A=20(defun=20= rx--charset-p=20(form)=0A=20=20=20"Whether=20FORM=20looks=20like=20a=20= charset,=20only=20consisting=20of=20character=20intervals=0A@@=20-836,11=20= +852,15=20@@=20rx--translate-literal=0A=20=20=20=20=20=20=20=20=20=20=20=20= (cons=20(list=20(list=20'regexp-quote=20arg))=20'seq))=0A=20=20=20=20=20=20= =20=20=20=20=20(t=20(error=20"rx=20`literal'=20form=20with=20non-string=20= argument")))))=0A=20=0A-(defun=20rx--translate-eval=20(body)=0A-=20=20= "Translate=20the=20`eval'=20form.=20=20Return=20(REGEXP=20.=20= PRECEDENCE)."=0A+(defun=20rx--expand-eval=20(body)=0A+=20=20"Expand=20= `eval'=20arguments.=20=20Return=20a=20new=20rx=20form."=0A=20=20=20= (unless=20(and=20body=20(null=20(cdr=20body)))=0A=20=20=20=20=20(error=20= "rx=20`eval'=20form=20takes=20exactly=20one=20argument"))=0A-=20=20= (rx--translate=20(eval=20(car=20body))))=0A+=20=20(eval=20(car=20body)))=0A= +=0A+(defun=20rx--translate-eval=20(body)=0A+=20=20"Translate=20the=20= `eval'=20form.=20=20Return=20(REGEXP=20.=20PRECEDENCE)."=0A+=20=20= (rx--translate=20(rx--expand-eval=20body)))=0A=20=0A=20(defvar=20= rx--regexp-atomic-regexp=20nil)=0A=20=0Adiff=20--git=20= a/test/lisp/emacs-lisp/rx-tests.el=20b/test/lisp/emacs-lisp/rx-tests.el=0A= index=20a6c172adfe..4db6eb8c9c=20100644=0A---=20= a/test/lisp/emacs-lisp/rx-tests.el=0A+++=20= b/test/lisp/emacs-lisp/rx-tests.el=0A@@=20-42,13=20+42,24=20@@=20rx-seq=0A= =20(ert-deftest=20rx-or=20()=0A=20=20=20(should=20(equal=20(rx=20(or=20= "ab"=20(|=20"c"=20nonl)=20"de"))=0A=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20"ab\\|c\\|.\\|de"))=0A-=20=20(should=20(equal=20(rx=20(or=20= "ab"=20"abc"=20"a"))=0A+=20=20(should=20(equal=20(rx=20(or=20"ab"=20= "abc"=20?a))=0A=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= "\\(?:a\\(?:bc?\\)?\\)"))=0A+=20=20(should=20(equal=20(rx=20(or=20"ab"=20= (|=20(or=20"abcd"=20"abcde"))=20(or=20"a"=20"abc")))=0A+=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20= "\\(?:a\\(?:b\\(?:c\\(?:de?\\)?\\)?\\)?\\)"))=0A+=20=20(should=20(equal=20= (rx=20(or=20"a"=20(eval=20(string=20?a=20?b))))=0A+=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20"\\(?:ab?\\)"))=0A=20=20=20(should=20(equal=20= (rx=20(|=20nonl=20"a")=20(|=20"b"=20blank))=0A=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20"\\(?:.\\|a\\)\\(?:b\\|[[:blank:]]\\)"))=0A=20= =20=20(should=20(equal=20(rx=20(|))=0A=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20"\\`a\\`")))=0A=20=0A+(ert-deftest=20rx-def-in-or=20()=0A= +=20=20(rx-let=20((a=20b)=0A+=20=20=20=20=20=20=20=20=20=20=20(b=20(or=20= "abc"=20c))=0A+=20=20=20=20=20=20=20=20=20=20=20(c=20?a))=0A+=20=20=20=20= (should=20(equal=20(rx=20(or=20a=20(|=20"ab"=20"abcde")=20"abcd"))=0A+=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= "\\(?:a\\(?:b\\(?:c\\(?:de?\\)?\\)?\\)?\\)"))))=0A+=0A=20(ert-deftest=20= rx-char-any=20()=0A=20=20=20"Test=20character=20alternatives=20with=20= `]'=20and=20`-'=20(Bug#25123)."=0A=20=20=20(should=20(equal=0A--=20=0A= 2.21.1=20(Apple=20Git-122.3)=0A=0A= --Apple-Mail=_1859A414-62A6-4E9B-BBF2-E05A74BBEEA4--