From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!.POSTED.blaine.gmane.org!not-for-mail From: =?utf-8?Q?Mattias_Engdeg=C3=A5rd?= Newsgroups: gmane.emacs.devel Subject: Re: New rx implementation with extension constructs Date: Fri, 6 Sep 2019 16:09:07 +0200 Message-ID: <4FEFB231-9880-4C05-8E5F-63CB64368DC6@acm.org> References: Mime-Version: 1.0 (Mac OS X Mail 12.4 \(3445.104.11\)) Content-Type: multipart/mixed; boundary="Apple-Mail=_13F108E5-C9EF-4F5C-9D1D-158EFACFAEE4" Injection-Info: blaine.gmane.org; posting-host="blaine.gmane.org:195.159.176.226"; logging-data="221996"; mail-complaints-to="usenet@blaine.gmane.org" To: emacs-devel Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Fri Sep 06 16:09:34 2019 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([209.51.188.17]) by blaine.gmane.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.89) (envelope-from ) id 1i6Evd-000vbv-IW for ged-emacs-devel@m.gmane.org; Fri, 06 Sep 2019 16:09:34 +0200 Original-Received: from localhost ([::1]:56722 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1i6Evc-0007f0-7t for ged-emacs-devel@m.gmane.org; Fri, 06 Sep 2019 10:09:32 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]:48516) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1i6EvN-0007dM-2B for emacs-devel@gnu.org; Fri, 06 Sep 2019 10:09:22 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1i6EvL-0006kf-7F for emacs-devel@gnu.org; Fri, 06 Sep 2019 10:09:16 -0400 Original-Received: from mail82c50.megamailservers.eu ([91.136.10.92]:59502 helo=mail18c50.megamailservers.eu) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1i6EvJ-0006eY-La for emacs-devel@gnu.org; Fri, 06 Sep 2019 10:09:15 -0400 X-Authenticated-User: mattiase@bredband.net DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=megamailservers.eu; s=maildub; t=1567778950; bh=WMuhC9oXF8A7cOi9NHWOiiKTF8eOE1WjvGNeymPI1PY=; h=From:Subject:Date:References:To:In-Reply-To:From; b=ikJF8RmkkzOS/Ds12oC0h3sFKcJ6lC3p7j1fuh9x8wNtA/1A00waORLMJjrjnPw5y oNvpRdujWUwSOHFaSUne7SzN/VixcaLECz/ojl/AI6jVc4iMkLRG6BP/hGu4f2bmr5 4s3dLHUHlRintpd2ihhQICtyjzMZSCg/LO/mdN8I= Feedback-ID: mattiase@acm.or Original-Received: from [192.168.0.4] ([188.150.171.71]) (authenticated bits=0) by mail18c50.megamailservers.eu (8.14.9/8.13.1) with ESMTP id x86E98Uf005970 for ; Fri, 6 Sep 2019 14:09:09 +0000 In-Reply-To: X-Mailer: Apple Mail (2.3445.104.11) X-CTCH-RefID: str=0001.0A0B0210.5D726886.0020, 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=dPfYZ9Rb c=1 sm=1 tr=0 a=SF+I6pRkHZhrawxbOkkvaA==:117 a=SF+I6pRkHZhrawxbOkkvaA==:17 a=jpOVt7BSZ2e4Z31A5e1TngXxSK0=:19 a=M51BFTxLslgA:10 a=lnuC4T4bT6MT6ylM1ukA:9 a=CjuIK1q_8ugA:10 a=LDcqEWYTlQjDgXGOZ8IA:9 a=B2y7HmGcmWMA:10 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x (no timestamps) [generic] X-Received-From: 91.136.10.92 X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Original-Sender: "Emacs-devel" Xref: news.gmane.org gmane.emacs.devel:239901 Archived-At: --Apple-Mail=_13F108E5-C9EF-4F5C-9D1D-158EFACFAEE4 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=us-ascii Here is a revised patch after comments on and off the list (many = thanks!). There is now a section in the manual that describes the extension = facility. Although consistent and usable in its current form, there are a few = points where I have yet to make up my mind. Perhaps you may shed some = insight on the matters: The rx-define, rx-let and rx-let-eval macros all essentially use the = syntax (NAME RX-FORM) or (NAME (ARGS...) RX-FORM) for definining plain and parametrised rx forms, respectively. It is very common for RX-FORM to be a sequence of rx elements. As a = result, the majority of definitions will need an explicit (seq ...) = around the definition, as in (rx-define float-num (seq (+ digit) ?. (* digit))) An alternative syntax would be the (Scheme-inspired) (NAME RX-FORMS...) ((NAME ARGS...) RX-FORMS...) where the `seq' wouldn't be necessary, but the argument list syntax no = longer follows Lisp tradition. Would it be palatable? Forms with rest arguments, currently written (NAME (ARG1 ARG2 &rest REST-ARG) RX-FORM) might become (Scheme again) ((NAME ARG1 ARG2 . REST-ARG) RX-FORMS...) A second, orthogonal point is how rest arguments are expanded in the = definition form. Right now, they expand as (seq ...) forms, which mostly = works but not always: (rx-let ((flavour (&rest choices) (or "vanilla" choices))) (rx (flavour "strawberry" "chocolate"))) expands to (rx (or "vanilla" (seq "strawberry" "chocolate"))) which = wasn't the intention. It may be better to make rest arguments = auto-splicing when substituted, which would work in all cases that I can = think of. --Apple-Mail=_13F108E5-C9EF-4F5C-9D1D-158EFACFAEE4 Content-Disposition: attachment; filename=0001-New-rx-implementation.patch Content-Type: application/octet-stream; x-unix-mode=0644; name="0001-New-rx-implementation.patch" Content-Transfer-Encoding: quoted-printable =46rom=202bdeab42045df344b550093a4d1efdd2babf2b3e=20Mon=20Sep=2017=20= 00:00:00=202001=0AFrom:=20=3D?UTF-8?q?Mattias=3D20Engdeg=3DC3=3DA5rd?=3D=20= =0ADate:=20Mon,=202=20Sep=202019=2016:07:23=20+0200=0A= Subject:=20[PATCH]=20New=20rx=20implementation=0A=0A*=20= lisp/emacs-lisp/rx.el:=0A*=20test/lisp/emacs-lisp/rx-tests.el:=0A*=20= doc/lispref/searching.texi:=0A*=20etc/NEWS:=0ARewrite=20rx=20for=20= correctness,=20clarity,=20and=20performance.=20=20The=20new=0A= implementation=20retains=20full=20compatibility=20and=20has=20more=20= comprehensive=0Atests,=20as=20well=20as=20a=20built-in=20set=20of=20= extension=20macros:=20`rx-define',=0A`rx-let'=20and=20`rx-let-eval'.=0A= ---=0A=20doc/lispref/searching.texi=20=20=20=20=20=20=20|=20=20157=20+++=0A= =20etc/NEWS=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=204=20+=0A=20lisp/emacs-lisp/rx.el=20=20=20=20=20=20= =20=20=20=20=20=20|=202039=20++++++++++++++++--------------=0A=20= test/lisp/emacs-lisp/rx-tests.el=20|=20=20421=20++++--=0A=204=20files=20= changed,=201562=20insertions(+),=201059=20deletions(-)=0A=0Adiff=20--git=20= a/doc/lispref/searching.texi=20b/doc/lispref/searching.texi=0Aindex=20= 2088f16e47..777a34f958=20100644=0A---=20a/doc/lispref/searching.texi=0A= +++=20b/doc/lispref/searching.texi=0A@@=20-1037,6=20+1037,7=20@@=20Rx=20= Notation=0A=20@menu=0A=20*=20Rx=20Constructs::=20=20=20=20=20=20=20= Constructs=20valid=20in=20rx=20forms.=0A=20*=20Rx=20Functions::=20=20=20=20= =20=20=20=20Functions=20and=20macros=20that=20use=20rx=20forms.=0A+*=20= Extending=20Rx::=20=20=20=20=20=20=20=20How=20to=20define=20your=20own=20= rx=20forms.=0A=20@end=20menu=0A=20=0A=20@node=20Rx=20Constructs=0A@@=20= -1526,6=20+1527,162=20@@=20Rx=20Functions=0A=20=0A=20The=20@code{pcase}=20= macro=20can=20use=20@code{rx}=20expressions=20as=20patterns=0A=20= directly;=20@pxref{rx=20in=20pcase}.=0A+=0A+For=20mechanisms=20to=20add=20= user-defined=20extensions=20to=20the=20@code{rx}=0A+notation,=20= @pxref{Extending=20Rx}.=0A+=0A+@node=20Extending=20Rx=0A+@subsubsection=20= Defining=20new=20@code{rx}=20forms=0A+=0A+The=20@code{rx}=20notation=20= can=20be=20extended=20by=20defining=20new=20symbols=20and=0A= +parametrised=20forms=20in=20terms=20of=20other=20@code{rx}=20= expressions.=20=20This=20is=0A+handy=20for=20sharing=20parts=20between=20= several=20regexps,=20and=20for=20making=0A+complex=20ones=20easier=20to=20= build=20and=20understand=20by=20putting=20them=20together=0A+from=20= smaller=20pieces.=0A+=0A+For=20example,=20you=20could=20define=20= @code{name}=20to=20mean=0A+@code{(one-or-more=20letter)},=20and=20= @code{(quoted=20@var{x})}=20to=20mean=0A+@code{(seq=20?'=20@var{x}=20= ?')}=20for=20any=20@var{x}.=20=20These=20forms=20could=20then=20be=0A= +used=20in=20@code{rx}=20expressions=20like=20any=20other:=20@code{(rx=20= (quoted=20name))}=0A+would=20match=20a=20nonempty=20sequence=20of=20= letters=20inside=20single=20quotes.=0A+=0A+The=20Lisp=20macros=20below=20= provide=20different=20ways=20of=20binding=20names=20to=0A+definitions.=20= =20Common=20to=20all=20of=20them=20are=20the=20following=20rules:=0A+=0A= +@itemize=0A+@item=0A+Built-in=20@code{rx}=20forms,=20like=20= @code{digit}=20and=20@code{group},=20always=0A+take=20precedence;=20they=20= cannot=20be=20redefined.=0A+=0A+@item=0A+The=20definitions=20live=20in=20= a=20name=20space=20of=20their=20own,=20separate=20from=20that=0A+of=20= Lisp=20variables.=20=20There=20is=20thus=20no=20need=20to=20attach=20a=20= suffix=20like=0A+@code{-regexp}=20to=20names;=20they=20cannot=20collide=20= with=20anything=20else.=0A+=0A+@item=0A+Definitions=20cannot=20refer=20= to=20themselves=20recursively,=20directly=20or=0A+indirectly.=20=20If=20= you=20find=20yourself=20needing=20this,=20you=20want=20a=20parser,=20not=0A= +a=20regular=20expression.=0A+=0A+@item=0A+Definitions=20are=20only=20= ever=20expanded=20in=20calls=20to=20@code{rx}=20or=0A= +@code{rx-to-string},=20not=20merely=20by=20their=20presence=20in=20= definition=0A+macros.=20=20This=20means=20that=20the=20order=20of=20= definitions=20doesn't=20matter,=20even=0A+when=20they=20refer=20to=20= each=20other,=20and=20that=20syntax=20errors=20only=20show=20up=0A+when=20= they=20are=20used,=20not=20when=20they=20are=20defined.=0A+=0A+@item=0A= +User-defined=20forms=20are=20allowed=20wherever=20arbitrary=20@code{rx}=0A= +expressions=20are=20expected;=20for=20example,=20in=20the=20body=20of=20= a=0A+@code{zero-or-one}=20form,=20but=20not=20inside=20@code{any}=20or=20= @code{category}=0A+forms.=0A+@end=20itemize=0A+=0A+@defmac=20rx-define=20= name=20[arglist]=20rx-form=0A+Define=20@var{name}=20globally=20in=20all=20= subsequent=20@code{rx}=20expressions.=0A+If=20@var{arglist}=20is=20= absent,=20then=20@var{name}=20is=20defined=20as=20a=20plain=0A+symbol=20= to=20be=20replaced=20with=20@var{rx-form}.=20=20Example:=0A+=0A+@example=0A= +@group=0A+(rx-define=20haskell-comment=20(seq=20"--"=20(zero-or-more=20= nonl)))=0A+(rx=20haskell-comment)=0A+=20=20=20=20=20@result{}=20"--.*"=0A= +@end=20group=0A+@end=20example=0A+=0A+If=20@var{arglist}=20is=20= present,=20it=20must=20be=20a=20list=20of=20zero=20or=20more=0A+argument=20= names,=20and=20@var{name}=20is=20then=20defined=20as=20a=20parametrised=20= form.=0A+When=20used=20in=20an=20@code{rx}=20expression=20as=20= @code{(@var{name}=20@var{arg}@dots{})},=0A+each=20@var{arg}=20will=20= replace=20the=20corresponding=20argument=20name=20inside=0A= +@var{rx-form}.=0A+=0A+@var{arglist}=20may=20end=20in=20@code{&rest}=20= and=20one=20final=20argument=20name,=0A+denoting=20a=20rest=20parameter.=20= =20The=20rest=20parameter=20will=20expand=0A+to=20all=20extra=20actual=20= argument=20values=20not=20matched=20by=20any=20other=20parameter=0A+in=20= @var{arglist},=20as=20if=20wrapped=20in=20@code{(seq=20...)}.=20=20= Example:=0A+=0A+@example=0A+@group=0A+(rx-define=20moan=20(x=20y=20&rest=20= r)=20(seq=20x=20(one-or-more=20y)=20r=20"!"))=0A+(rx=20(moan=20"MOO"=20= "A"=20"MEE"=20"OW"))=0A+=20=20=20=20=20@result{}=20"MOOA+MEEOW!"=0A+@end=20= group=0A+@end=20example=0A+=0A+Since=20the=20definition=20is=20global,=20= it=20is=20recommended=20to=20give=20@var{name}=20a=0A+package=20prefix=20= to=20avoid=20name=20clashes=20with=20definitions=20elsewhere,=20as=20is=0A= +usual=20when=20naming=20non-local=20variables=20and=20functions.=0A= +@end=20defmac=0A+=0A+@defmac=20rx-let=20(bindings@dots{})=20body@dots{}=0A= +Make=20the=20@code{rx}=20definitions=20in=20@var{bindings}=20available=20= locally=20for=0A+@code{rx}=20macro=20invocations=20in=20@var{body},=20= which=20is=20then=20evaluated.=0A+=0A+Each=20element=20of=20= @var{bindings}=20is=20on=20the=20form=0A+@w{@code{(@var{name}=20= [@var{arglist}]=20@var{rx-form})}},=20where=20the=20parts=0A+have=20the=20= same=20meaning=20as=20in=20@code{rx-define}=20above.=20=20Example:=0A+=0A= +@example=0A+@group=0A+(rx-let=20((comma-separated=20(item)=20(seq=20= item=20(0+=20","=20item)))=0A+=20=20=20=20=20=20=20=20=20(number=20(1+=20= digit))=0A+=20=20=20=20=20=20=20=20=20(numbers=20(comma-separated=20= number)))=0A+=20=20(re-search-forward=20(rx=20"("=20numbers=20")")))=0A= +@end=20group=0A+@end=20example=0A+=0A+The=20definitions=20are=20only=20= available=20during=20the=20macro-expansion=20of=0A+@var{body},=20and=20= are=20thus=20not=20present=20during=20execution=20of=20compiled=0A+code.=0A= +=0A+@code{rx-let}=20can=20be=20used=20not=20only=20inside=20a=20= function,=20but=20also=20at=20top=0A+level=20to=20include=20global=20= variable=20and=20function=20definitions=20that=20need=0A+to=20share=20a=20= common=20set=20of=20@code{rx}=20forms.=20=20Since=20the=20names=20are=20= local=0A+inside=20@var{body},=20there=20is=20no=20need=20for=20any=20= package=20prefixes.=0A+Example:=0A+=0A+@example=0A+@group=0A+(rx-let=20= ((phone-number=20(seq=20(opt=20?+)=20(1+=20(any=20digit=20?-)))))=0A+=20=20= (defun=20find-next-phone-number=20()=0A+=20=20=20=20(re-search-forward=20= (rx=20phone-number)))=0A+=20=20(defun=20phone-number-p=20(string)=0A+=20=20= =20=20(string-match-p=20(rx=20bos=20phone-number=20eos)=20string)))=0A= +@end=20group=0A+@end=20example=0A+=0A+The=20scope=20of=20the=20= @code{rx-let}=20bindings=20is=20lexical,=20which=20means=20that=0A+they=20= are=20not=20visible=20outside=20@var{body}=20itself,=20even=20in=20= functions=0A+called=20from=20@var{body}.=0A+@end=20defmac=0A+=0A+@defmac=20= rx-let-eval=20bindings=20body@dots{}=0A+Evaluate=20@var{bindings}=20to=20= a=20list=20of=20bindings=20as=20in=20@code{rx-let},=0A+and=20evaluate=20= @var{body}=20with=20those=20bindings=20in=20effect=20for=20calls=0A+to=20= @code{rx-to-string}.=0A+=0A+This=20macro=20is=20similar=20to=20= @code{rx-let},=20except=20that=20the=20@var{bindings}=0A+argument=20is=20= evaluated=20(and=20thus=20needs=20to=20be=20quoted=20if=20it=20is=20a=20= list=0A+literal),=20and=20the=20definitions=20are=20substituted=20at=20= run=20time,=20which=20is=0A+required=20for=20@code{rx-to-string}=20to=20= work.=20=20Example:=0A+=0A+@example=0A+@group=0A+(rx-let-eval=0A+=20=20=20= =20'((ponder=20(x)=20(seq=20"Where=20have=20all=20the=20"=20x=20"=20= gone?")))=0A+=20=20(looking-at=20(rx-to-string=0A+=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20'(ponder=20(or=20"flowers"=20"young=20girls"=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"left=20socks")))))=0A+@end=20group=0A+@end=20example=0A+=0A+Another=20= difference=20from=20@code{rx-let}=20is=20that=20the=20@var{bindings}=20= are=0A+dynamically=20scoped,=20and=20thus=20also=20available=20in=20= functions=20called=20from=0A+@var{body}.=20However,=20they=20are=20not=20= visible=20inside=20functions=20defined=20in=0A+@var{body}.=0A+@end=20= defmac=0A+=0A=20@end=20ifnottex=0A=20=0A=20@node=20Regexp=20Functions=0A= diff=20--git=20a/etc/NEWS=20b/etc/NEWS=0Aindex=20d5130e9f3c..e1353f4250=20= 100644=0A---=20a/etc/NEWS=0A+++=20b/etc/NEWS=0A@@=20-1666,6=20+1666,10=20= @@=20This=20also=20works=20for=20their=20aliases:=20'|'=20for=20'or';=20= ':',=20'and'=20and=0A=20In=20this=20case,=20'rx'=20will=20generate=20= code=20which=20produces=20a=20regexp=20string=0A=20at=20run=20time,=20= instead=20of=20a=20constant=20string.=0A=20=0A+---=0A+***=20New=20rx=20= extension=20mechanism:=20'rx-define',=20'rx-let',=20'rx-let-eval'.=0A= +These=20macros=20add=20new=20forms=20to=20the=20rx=20notation.=0A+=0A=20= **=20Frames=0A=20=0A=20+++=0Adiff=20--git=20a/lisp/emacs-lisp/rx.el=20= b/lisp/emacs-lisp/rx.el=0Aindex=20249529e54e..5fa7c55a1c=20100644=0A---=20= a/lisp/emacs-lisp/rx.el=0A+++=20b/lisp/emacs-lisp/rx.el=0A@@=20-1,11=20= +1,7=20@@=0A-;;;=20rx.el=20---=20sexp=20notation=20for=20regular=20= expressions=20=20-*-=20lexical-binding:=20t=20-*-=0A+;;;=20rx.el=20---=20= S-exp=20notation=20for=20regexps=20=20=20=20=20=20=20=20=20=20=20--*-=20= lexical-binding:=20t=20-*-=0A=20=0A=20;;=20Copyright=20(C)=202001-2019=20= Free=20Software=20Foundation,=20Inc.=0A=20=0A-;;=20Author:=20Gerd=20= Moellmann=20=0A-;;=20Maintainer:=20emacs-devel@gnu.org=0A= -;;=20Keywords:=20strings,=20regexps,=20extensions=0A-=0A=20;;=20This=20= file=20is=20part=20of=20GNU=20Emacs.=0A=20=0A=20;;=20GNU=20Emacs=20is=20= free=20software:=20you=20can=20redistribute=20it=20and/or=20modify=0A@@=20= -23,937=20+19,932=20@@=0A=20=0A=20;;;=20Commentary:=0A=20=0A-;;=20This=20= is=20another=20implementation=20of=20sexp-form=20regular=20expressions.=0A= -;;=20It=20was=20unfortunately=20written=20without=20being=20aware=20of=20= the=20Sregex=0A-;;=20package=20coming=20with=20Emacs,=20but=20as=20= things=20stand,=20Rx=20completely=0A-;;=20covers=20all=20regexp=20= features,=20which=20Sregex=20doesn't,=20doesn't=20suffer=0A-;;=20from=20= the=20bugs=20mentioned=20in=20the=20commentary=20section=20of=20Sregex,=20= and=0A-;;=20uses=20a=20nicer=20syntax=20(IMHO,=20of=20course=20:-).=0A-=0A= -;;=20This=20significantly=20extended=20version=20of=20the=20original,=20= is=20almost=0A-;;=20compatible=20with=20Sregex.=20=20The=20only=20= incompatibility=20I=20(fx)=20know=20of=20is=0A-;;=20that=20the=20= `repeat'=20form=20can't=20have=20multiple=20regexp=20args.=0A-=0A-;;=20= Now=20alternative=20forms=20are=20provided=20for=20a=20degree=20of=20= compatibility=0A-;;=20with=20Olin=20Shivers'=20attempted=20definitive=20= SRE=20notation.=20=20SRE=20forms=0A-;;=20not=20catered=20for=20include:=20= dsm,=20uncase,=20w/case,=20w/nocase,=20,@,=0A-;;=20,,=20(word=20= ...),=20word+,=20posix-string,=20and=20character=20class=20forms.=0A-;;=20= Some=20forms=20are=20inconsistent=20with=20SRE,=20either=20for=20= historical=20reasons=0A-;;=20or=20because=20of=20the=20implementation=20= --=20simple=20translation=20into=20Emacs=0A-;;=20regexp=20strings.=20=20= These=20include:=20any,=20word.=20=20Also,=20case-sensitivity=0A-;;=20= and=20greediness=20are=20controlled=20by=20variables=20external=20to=20= the=20regexp,=0A-;;=20and=20you=20need=20to=20feed=20the=20forms=20to=20= the=20`posix-'=20functions=20to=20get=0A-;;=20SRE's=20POSIX=20semantics.=20= =20There=20are=20probably=20more=20difficulties.=0A-=0A-;;=20Rx=20= translates=20a=20sexp=20notation=20for=20regular=20expressions=20into=20= the=0A-;;=20usual=20string=20notation.=20=20The=20translation=20can=20be=20= done=20at=20compile-time=0A-;;=20by=20using=20the=20`rx'=20macro.=20=20= The=20`regexp'=20and=20`literal'=20forms=20accept=0A-;;=20non-constant=20= expressions,=20in=20which=20case=20`rx'=20will=20translate=20to=20a=0A= -;;=20`concat'=20expression.=20=20Translation=20can=20be=20done=20fully=20= at=20run=20time=20by=0A-;;=20calling=20function=20`rx-to-string'.=20=20= See=20the=20documentation=20of=20`rx'=20for=0A-;;=20a=20complete=20= description=20of=20the=20sexp=20notation.=0A-;;=0A-;;=20Some=20examples=20= of=20string=20regexps=20and=20their=20sexp=20counterparts:=0A-;;=0A-;;=20= "^[a-z]*"=0A-;;=20(rx=20line-start=20(0+=20(in=20"a-z")))=0A-;;=0A-;;=20= "\n[^=20\t]"=0A-;;=20(rx=20?\n=20(not=20(in=20"=20\t")))=0A-;;=0A-;;=20= "\\*\\*\\*=20EOOH=20\\*\\*\\*\n"=0A-;;=20(rx=20"***=20EOOH=20***\n")=0A= -;;=0A-;;=20"\\<\\(catch\\|finally\\)\\>[^_]"=0A-;;=20(rx=20word-start=20= (submatch=20(or=20"catch"=20"finally"))=20word-end=0A-;;=20=20=20=20=20= (not=20(in=20?_)))=0A-;;=0A-;;=20"[=20\t\n]*:\\($\\|[^:]+\\)"=0A-;;=20= (rx=20(*=20(in=20"=20\t\n"))=20":"=0A-;;=20=20=20=20=20(submatch=20(or=20= line-end=20(+=20(not=20(in=20?:))))))=0A+;;=20This=20facility=20allows=20= writing=20regexps=20in=20a=20sexp-based=20language=0A+;;=20instead=20of=20= strings.=20=20Regexps=20in=20the=20`rx'=20notation=20are=20easier=20to=0A= +;;=20read,=20write=20and=20maintain;=20they=20can=20be=20indented=20and=20= commented=20in=20a=0A+;;=20natural=20way,=20and=20are=20easily=20= composed=20by=20program=20code.=0A+;;=20The=20translation=20to=20string=20= regexp=20is=20done=20by=20a=20macro=20and=20does=20not=0A+;;=20incur=20= any=20extra=20processing=20during=20run=20time.=20=20Example:=0A=20;;=0A= -;;=20"^content-transfer-encoding:\\(?:\n?[\t=20= ]\\)*quoted-printable\\(?:\n?[\t=20]\\)*"=0A-;;=20(rx=20line-start=0A-;;=20= =20=20=20=20"content-transfer-encoding:"=0A-;;=20=20=20=20=20(*=20(?=20= ?\n)=20(in=20"=20\t"))=0A-;;=20=20=20=20=20"quoted-printable"=0A-;;=20=20= =20=20=20(*=20(?=20?\n)=20(in=20"=20\t")))=0A+;;=20=20(rx=20bos=20(or=20= (not=20(any=20"^"))=0A+;;=20=20=20=20=20=20=20=20=20=20=20=20=20=20(seq=20= "^"=20(or=20"=20*"=20"["))))=0A=20;;=0A-;;=20(concat=20"^\\(?:"=20= something-else=20"\\)")=0A-;;=20(rx=20line-start=20(regexp=20= something-else))=0A-;;=0A-;;=20(regexp-opt=20'(STRING1=20STRING2=20...))=0A= -;;=20(rx=20(or=20STRING1=20STRING2=20...)),=20or=20in=20other=20words,=20= `or'=20automatically=0A-;;=20calls=20`regexp-opt'=20as=20needed.=0A-;;=0A= -;;=20"^;;\\s-*\n\\|^\n"=0A-;;=20(rx=20(or=20(seq=20line-start=20";;"=20= (0+=20space)=20?\n)=0A-;;=20=20=20=20=20=20=20=20=20(seq=20line-start=20= ?\n)))=0A-;;=0A-;;=20"\\$[I]d:=20[^=20]+=20\\([^=20]+\\)=20"=0A-;;=20(rx=20= "$Id:=20"=0A-;;=20=20=20=20=20(1+=20(not=20(in=20"=20")))=0A-;;=20=20=20=20= =20"=20"=0A-;;=20=20=20=20=20(submatch=20(1+=20(not=20(in=20"=20"))))=0A= -;;=20=20=20=20=20"=20")=0A-;;=0A-;;=20"\\\\\\\\\\[\\w+"=0A-;;=20(rx=20= "\\\\["=20(1+=20word))=0A-;;=0A-;;=20etc.=0A-=0A-;;;=20History:=0A+;;=20= =3D>=20"\\`\\(?:[^^]\\|\\^\\(?:=20\\*\\|\\[\\)\\)"=0A=20;;=0A+;;=20The=20= notation=20is=20much=20influenced=20by=20and=20retains=20some=20= compatibility=20with=0A+;;=20Olin=20Shivers's=20SRE,=20with=20= concessions=20to=20Emacs=20regexp=20peculiarities,=0A+;;=20and=20the=20= older=20Emacs=20package=20Sregex.=0A=20=0A=20;;;=20Code:=0A=20=0A= -(require=20'cl-lib)=0A-(require=20'cl-extra)=0A-=0A-;;=20FIXME:=20= support=20macros.=0A-=0A-(defvar=20rx-constituents=20=20=20=20=20=20=20=20= =20=20=20=20=20=20;Not=20`const'=20because=20some=20modes=20extend=20it.=0A= -=20=20'((and=09=09.=20(rx-and=200=20nil))=0A-=20=20=20=20(seq=09=09.=20= and)=09=09;=20SRE=0A-=20=20=20=20(:=09=09=09.=20and)=09=09;=20SRE=0A-=20=20= =20=20(sequence=09=09.=20and)=09=09;=20sregex=0A-=20=20=20=20(or=09=09=09= .=20(rx-or=200=20nil))=0A-=20=20=20=20(|=09=09=09.=20or)=09=09;=20SRE=0A= -=20=20=20=20(not-newline=09.=20".")=0A-=20=20=20=20(nonl=09=09.=20= not-newline)=09;=20SRE=0A-=20=20=20=20(anything=09=09.=20(rx-anything=20= 0=20nil))=0A-=20=20=20=20(any=09=09.=20(rx-any=201=20nil=20= rx-check-any))=20;=20inconsistent=20with=20SRE=0A-=20=20=20=20(any=09=09= .=20".")=20=20=20=20=20=20=20=20=20=20;=20sregex=0A-=20=20=20=20(in=09=09= =09.=20any)=0A-=20=20=20=20(char=09=09.=20any)=09=09;=20sregex=0A-=20=20=20= =20(not-char=09=09.=20(rx-not-char=201=20nil=20rx-check-any))=20;=20= sregex=0A-=20=20=20=20(not=09=09.=20(rx-not=201=201=20rx-check-not))=0A-=20= =20=20=20(repeat=09=09.=20(rx-repeat=202=20nil))=0A-=20=20=20=20(=3D=09=09= =09.=20(rx-=3D=202=20nil))=09=20=20=20;=20SRE=0A-=20=20=20=20(>=3D=09=09=09= .=20(rx->=3D=202=20nil))=20=20=20;=20SRE=0A-=20=20=20=20(**=09=09=09.=20= (rx-**=202=20nil))=20=20=20;=20SRE=0A-=20=20=20=20(submatch=09=09.=20= (rx-submatch=201=20nil))=20;=20SRE=0A-=20=20=20=20(group=09=09.=20= submatch)=20=20=20=20=20;=20sregex=0A-=20=20=20=20(submatch-n=09=09.=20= (rx-submatch-n=202=20nil))=0A-=20=20=20=20(group-n=09=09.=20submatch-n)=0A= -=20=20=20=20(zero-or-more=09.=20(rx-kleene=201=20nil))=0A-=20=20=20=20= (one-or-more=09.=20(rx-kleene=201=20nil))=0A-=20=20=20=20(zero-or-one=09= .=20(rx-kleene=201=20nil))=0A-=20=20=20=20(\?=09=09=09.=20zero-or-one)=09= ;=20SRE=0A-=20=20=20=20(\??=09=09.=20zero-or-one)=0A-=20=20=20=20(*=09=09= =09.=20zero-or-more)=09;=20SRE=0A-=20=20=20=20(*?=09=09=09.=20= zero-or-more)=0A-=20=20=20=20(0+=09=09=09.=20zero-or-more)=0A-=20=20=20=20= (+=09=09=09.=20one-or-more)=09;=20SRE=0A-=20=20=20=20(+?=09=09=09.=20= one-or-more)=0A-=20=20=20=20(1+=09=09=09.=20one-or-more)=0A-=20=20=20=20= (optional=09=09.=20zero-or-one)=0A-=20=20=20=20(opt=09=09.=20= zero-or-one)=09;=20sregex=0A-=20=20=20=20(minimal-match=09.=20(rx-greedy=20= 1=201))=0A-=20=20=20=20(maximal-match=09.=20(rx-greedy=201=201))=0A-=20=20= =20=20(backref=09=09.=20(rx-backref=201=201=20rx-check-backref))=0A-=20=20= =20=20(line-start=09=09.=20"^")=0A-=20=20=20=20(bol=09=09.=20line-start)=09= ;=20SRE=0A-=20=20=20=20(line-end=09=09.=20"$")=0A-=20=20=20=20(eol=09=09= .=20line-end)=09;=20SRE=0A-=20=20=20=20(string-start=09.=20"\\`")=0A-=20=20= =20=20(bos=09=09.=20string-start)=09;=20SRE=0A-=20=20=20=20(bot=09=09.=20= string-start)=09;=20sregex=0A-=20=20=20=20(string-end=09=09.=20"\\'")=0A= -=20=20=20=20(eos=09=09.=20string-end)=09;=20SRE=0A-=20=20=20=20(eot=09=09= .=20string-end)=09;=20sregex=0A-=20=20=20=20(buffer-start=09.=20"\\`")=0A= -=20=20=20=20(buffer-end=09=09.=20"\\'")=0A-=20=20=20=20(point=09=09.=20= "\\=3D")=0A-=20=20=20=20(word-start=09=09.=20"\\<")=0A-=20=20=20=20(bow=09= =09.=20word-start)=09;=20SRE=0A-=20=20=20=20(word-end=09=09.=20"\\>")=0A= -=20=20=20=20(eow=09=09.=20word-end)=09;=20SRE=0A-=20=20=20=20= (word-boundary=09.=20"\\b")=0A-=20=20=20=20(not-word-boundary=09.=20= "\\B")=09;=20sregex=0A-=20=20=20=20(symbol-start=20=20=20=20=20=20=20.=20= "\\_<")=0A-=20=20=20=20(symbol-end=20=20=20=20=20=20=20=20=20.=20"\\_>")=0A= -=20=20=20=20(syntax=09=09.=20(rx-syntax=201=201))=0A-=20=20=20=20= (not-syntax=09=09.=20(rx-not-syntax=201=201))=20;=20sregex=0A-=20=20=20=20= (category=09=09.=20(rx-category=201=201=20rx-check-category))=0A-=20=20=20= =20(eval=09=09.=20(rx-eval=201=201))=0A-=20=20=20=20(literal=09=09.=20= (rx-literal=201=201=20stringp))=0A-=20=20=20=20(regexp=09=09.=20= (rx-regexp=201=201=20stringp))=0A-=20=20=20=20(regex=09=09.=20regexp)=20=20= =20=20=20=20=20;=20sregex=0A-=20=20=20=20(digit=09=09.=20"[[:digit:]]")=0A= -=20=20=20=20(numeric=09=09.=20digit)=09;=20SRE=0A-=20=20=20=20(num=09=09= .=20digit)=09;=20SRE=0A-=20=20=20=20(control=09=09.=20"[[:cntrl:]]")=20;=20= SRE=0A-=20=20=20=20(cntrl=09=09.=20control)=09=20;=20SRE=0A-=20=20=20=20= (hex-digit=09=09.=20"[[:xdigit:]]")=20;=20SRE=0A-=20=20=20=20(hex=09=09.=20= hex-digit)=09=20=20;=20SRE=0A-=20=20=20=20(xdigit=09=09.=20hex-digit)=09=20= =20;=20SRE=0A-=20=20=20=20(blank=09=09.=20"[[:blank:]]")=20=20;=20SRE=0A= -=20=20=20=20(graphic=09=09.=20"[[:graph:]]")=20=20;=20SRE=0A-=20=20=20=20= (graph=09=09.=20graphic)=09=20=20;=20SRE=0A-=20=20=20=20(printing=09=09.=20= "[[:print:]]")=20=20;=20SRE=0A-=20=20=20=20(print=09=09.=20printing)=09=20= =20;=20SRE=0A-=20=20=20=20(alphanumeric=09.=20"[[:alnum:]]")=20=20;=20= SRE=0A-=20=20=20=20(alnum=09=09.=20alphanumeric)=09=20=20;=20SRE=0A-=20=20= =20=20(letter=09=09.=20"[[:alpha:]]")=0A-=20=20=20=20(alphabetic=09=09.=20= letter)=09;=20SRE=0A-=20=20=20=20(alpha=09=09.=20letter)=09;=20SRE=0A-=20= =20=20=20(ascii=09=09.=20"[[:ascii:]]")=20;=20SRE=0A-=20=20=20=20= (nonascii=09=09.=20"[[:nonascii:]]")=0A-=20=20=20=20(lower=09=09.=20= "[[:lower:]]")=20;=20SRE=0A-=20=20=20=20(lower-case=09=09.=20lower)=09=20= ;=20SRE=0A-=20=20=20=20(punctuation=09.=20"[[:punct:]]")=20;=20SRE=0A-=20= =20=20=20(punct=09=09.=20punctuation)=09=20;=20SRE=0A-=20=20=20=20(space=09= =09.=20"[[:space:]]")=20;=20SRE=0A-=20=20=20=20(whitespace=09=09.=20= space)=09=20;=20SRE=0A-=20=20=20=20(white=09=09.=20space)=09=20;=20SRE=0A= -=20=20=20=20(upper=09=09.=20"[[:upper:]]")=20;=20SRE=0A-=20=20=20=20= (upper-case=09=09.=20upper)=09=20;=20SRE=0A-=20=20=20=20(word=09=09.=20= "[[:word:]]")=09=20;=20inconsistent=20with=20SRE=0A-=20=20=20=20= (wordchar=09=09.=20word)=09=09=20;=20sregex=0A-=20=20=20=20(not-wordchar=09= .=20"\\W"))=0A-=20=20"Alist=20of=20sexp=20form=20regexp=20constituents.=0A= -Each=20element=20of=20the=20alist=20has=20the=20form=20(SYMBOL=20.=20= DEFN).=0A-SYMBOL=20is=20a=20valid=20constituent=20of=20sexp=20regular=20= expressions.=0A-If=20DEFN=20is=20a=20string,=20SYMBOL=20is=20translated=20= into=20DEFN.=0A-If=20DEFN=20is=20a=20symbol,=20use=20the=20definition=20= of=20DEFN,=20recursively.=0A-Otherwise,=20DEFN=20must=20be=20a=20list=20= (FUNCTION=20MIN-ARGS=20MAX-ARGS=20PREDICATE).=0A-FUNCTION=20is=20used=20= to=20produce=20code=20for=20SYMBOL.=20=20MIN-ARGS=20and=20MAX-ARGS=0A= -are=20the=20minimum=20and=20maximum=20number=20of=20arguments=20the=20= function-form=0A-sexp=20constituent=20SYMBOL=20may=20have=20in=20sexp=20= regular=20expressions.=0A-MAX-ARGS=20nil=20means=20no=20limit.=20=20= PREDICATE,=20if=20specified,=20means=20that=0A-all=20arguments=20must=20= satisfy=20PREDICATE.")=0A-=0A-=0A-(defconst=20rx-syntax=0A-=20=20= '((whitespace=09=09.=20?-)=0A-=20=20=20=20(punctuation=09.=20?.)=0A-=20=20= =20=20(word=09=09.=20?w)=0A-=20=20=20=20(symbol=09=09.=20?_)=0A-=20=20=20= =20(open-parenthesis=09.=20?\()=0A-=20=20=20=20(close-parenthesis=09.=20= ?\))=0A-=20=20=20=20(expression-prefix=09.=20?\')=0A-=20=20=20=20= (string-quote=09.=20?\")=0A-=20=20=20=20(paired-delimiter=09.=20?$)=0A-=20= =20=20=20(escape=09=09.=20?\\)=0A-=20=20=20=20(character-quote=09.=20?/)=0A= -=20=20=20=20(comment-start=09.=20?<)=0A-=20=20=20=20(comment-end=09.=20= ?>)=0A-=20=20=20=20(string-delimiter=09.=20?|)=0A-=20=20=20=20= (comment-delimiter=09.=20?!))=0A-=20=20"Alist=20mapping=20Rx=20syntax=20= symbols=20to=20syntax=20characters.=0A-Each=20entry=20has=20the=20form=20= (SYMBOL=20.=20CHAR),=20where=20SYMBOL=20is=20a=20valid=0A-symbol=20in=20= `(syntax=20SYMBOL)',=20and=20CHAR=20is=20the=20syntax=20character=0A= -corresponding=20to=20SYMBOL,=20as=20it=20would=20be=20used=20with=20\\s=20= or=20\\S=20in=0A-regular=20expressions.")=0A-=0A-=0A-(defconst=20= rx-categories=0A-=20=20'((space-for-indent=20=20=20=20=20=20=20=20=20=20=20= .=20?\s)=0A-=20=20=20=20(base=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20.=20?.)=0A-=20=20=20=20(consonant=09=09=09.=20= ?0)=0A-=20=20=20=20(base-vowel=09=09=09.=20?1)=0A-=20=20=20=20= (upper-diacritical-mark=09.=20?2)=0A-=20=20=20=20(lower-diacritical-mark=09= .=20?3)=0A-=20=20=20=20(tone-mark=09=09=09.=20?4)=0A-=20=20=20=20(symbol=09= =09=09.=20?5)=0A-=20=20=20=20(digit=09=09=09.=20?6)=0A-=20=20=20=20= (vowel-modifying-diacritical-mark=20.=20?7)=0A-=20=20=20=20(vowel-sign=09= =09=09.=20?8)=0A-=20=20=20=20(semivowel-lower=09=09.=20?9)=0A-=20=20=20=20= (not-at-end-of-line=09=09.=20?<)=0A-=20=20=20=20= (not-at-beginning-of-line=09.=20?>)=0A-=20=20=20=20= (alpha-numeric-two-byte=09.=20?A)=0A-=20=20=20=20(chinese-two-byte=09=09= .=20?C)=0A-=20=20=20=20(chinse-two-byte=09=09.=20?C)=20;;=20A=20typo=20= in=20Emacs=2021.1-24.3.=0A-=20=20=20=20(greek-two-byte=09=09.=20?G)=0A-=20= =20=20=20(japanese-hiragana-two-byte=20.=20?H)=0A-=20=20=20=20= (indian-two-byte=09=09.=20?I)=0A-=20=20=20=20(japanese-katakana-two-byte=20= .=20?K)=0A-=20=20=20=20(strong-left-to-right=20=20=20=20=20=20=20.=20?L)=0A= -=20=20=20=20(korean-hangul-two-byte=09.=20?N)=0A-=20=20=20=20= (strong-right-to-left=20=20=20=20=20=20=20.=20?R)=0A-=20=20=20=20= (cyrillic-two-byte=09=09.=20?Y)=0A-=20=20=20=20(combining-diacritic=09.=20= ?^)=0A-=20=20=20=20(ascii=09=09=09.=20?a)=0A-=20=20=20=20(arabic=09=09=09= .=20?b)=0A-=20=20=20=20(chinese=09=09=09.=20?c)=0A-=20=20=20=20(ethiopic=09= =09=09.=20?e)=0A-=20=20=20=20(greek=09=09=09.=20?g)=0A-=20=20=20=20= (korean=09=09=09.=20?h)=0A-=20=20=20=20(indian=09=09=09.=20?i)=0A-=20=20=20= =20(japanese=09=09=09.=20?j)=0A-=20=20=20=20(japanese-katakana=09=09.=20= ?k)=0A-=20=20=20=20(latin=09=09=09.=20?l)=0A-=20=20=20=20(lao=09=09=09.=20= ?o)=0A-=20=20=20=20(tibetan=09=09=09.=20?q)=0A-=20=20=20=20= (japanese-roman=09=09.=20?r)=0A-=20=20=20=20(thai=09=09=09.=20?t)=0A-=20=20= =20=20(vietnamese=09=09=09.=20?v)=0A-=20=20=20=20(hebrew=09=09=09.=20?w)=0A= -=20=20=20=20(cyrillic=09=09=09.=20?y)=0A-=20=20=20=20(can-break=09=09=09= .=20?|))=0A-=20=20"Alist=20mapping=20symbols=20to=20category=20= characters.=0A-Each=20entry=20has=20the=20form=20(SYMBOL=20.=20CHAR),=20= where=20SYMBOL=20is=20a=20valid=0A-symbol=20in=20`(category=20SYMBOL)',=20= and=20CHAR=20is=20the=20category=20character=0A-corresponding=20to=20= SYMBOL,=20as=20it=20would=20be=20used=20with=20`\\c'=20or=20`\\C'=20in=0A= -regular=20expression=20strings.")=0A-=0A-=0A-(defvar=20rx-greedy-flag=20= t=0A-=20=20"Non-nil=20means=20produce=20greedy=20regular=20expressions=20= for=20`zero-or-one',=0A-`zero-or-more',=20and=20`one-or-more'.=20=20= Dynamically=20bound.")=0A-=0A-(defvar=20rx--compile-to-lisp=20nil=0A-=20=20= "Nil=20means=20return=20a=20regexp=20as=20a=20string.=0A-Non-nil=20means=20= we=20may=20return=20a=20lisp=20form=20which=20produces=20a=0A-string=20= (used=20for=20`rx'=20macro).")=0A-=0A-(defun=20rx-info=20(op=20head)=0A-=20= =20"Return=20parsing/code=20generation=20info=20for=20OP.=0A-If=20OP=20= is=20the=20space=20character=20ASCII=2032,=20return=20info=20for=20the=20= symbol=20`?'.=0A-If=20OP=20is=20the=20character=20`?',=20return=20info=20= for=20the=20symbol=20`??'.=0A-See=20also=20`rx-constituents'.=0A-If=20= HEAD=20is=20non-nil,=20then=20OP=20is=20the=20head=20of=20a=20sexp,=20= otherwise=20it's=0A-a=20standalone=20symbol."=0A-=20=20(cond=20((eq=20op=20= ?=20)=20(setq=20op=20'\?))=0A-=09((eq=20op=20??)=20(setq=20op=20'\??)))=0A= -=20=20(let=20(old-op)=0A-=20=20=20=20(while=20(and=20(not=20(null=20= op))=20(symbolp=20op))=0A-=20=20=20=20=20=20(setq=20old-op=20op)=0A-=20=20= =20=20=20=20(setq=20op=20(cdr=20(assq=20op=20rx-constituents)))=0A-=20=20= =20=20=20=20(when=20(if=20head=20(stringp=20op)=20(consp=20op))=0A-=20=20= =20=20=20=20=20=20;;=20We=20found=20something=20but=20of=20the=20wrong=20= kind.=20=20Let's=20look=20for=20an=0A-=20=20=20=20=20=20=20=20;;=20= alternate=20definition=20for=20the=20other=20case.=0A-=20=20=20=20=20=20=20= =20(let=20((new-op=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(cdr=20= (assq=20old-op=20(cdr=20(memq=20(assq=20old-op=20rx-constituents)=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=20=20=20=20=20=20=20=20=20=20=20=20rx-constituents))))))=0A= -=20=20=20=20=20=20=20=20=20=20(if=20(and=20new-op=20(not=20(if=20head=20= (stringp=20new-op)=20(consp=20new-op))))=0A-=20=20=20=20=20=20=20=20=20=20= =20=20=20=20(setq=20op=20new-op))))))=0A-=20=20op)=0A-=0A-=0A-(defun=20= rx-check=20(form)=0A-=20=20"Check=20FORM=20according=20to=20its=20car's=20= parsing=20info."=0A-=20=20(unless=20(listp=20form)=0A-=20=20=20=20(error=20= "rx=20`%s'=20needs=20argument(s)"=20form))=0A-=20=20(let*=20((rx=20= (rx-info=20(car=20form)=20'head))=0A-=09=20(nargs=20(1-=20(length=20= form)))=0A-=09=20(min-args=20(nth=201=20rx))=0A-=09=20(max-args=20(nth=20= 2=20rx))=0A-=09=20(type-pred=20(nth=203=20rx)))=0A-=20=20=20=20(when=20= (and=20(not=20(null=20min-args))=0A-=09=20=20=20=20=20=20=20(<=20nargs=20= min-args))=0A-=20=20=20=20=20=20(error=20"rx=20form=20`%s'=20requires=20= at=20least=20%d=20args"=0A-=09=20=20=20=20=20(car=20form)=20min-args))=0A= -=20=20=20=20(when=20(and=20(not=20(null=20max-args))=0A-=09=20=20=20=20=20= =20=20(>=20nargs=20max-args))=0A-=20=20=20=20=20=20(error=20"rx=20form=20= `%s'=20accepts=20at=20most=20%d=20args"=0A-=09=20=20=20=20=20(car=20= form)=20max-args))=0A-=20=20=20=20(when=20type-pred=0A-=20=20=20=20=20=20= (dolist=20(sub-form=20(cdr=20form))=0A-=09(unless=20(funcall=20type-pred=20= sub-form)=0A-=09=20=20(error=20"rx=20form=20`%s'=20requires=20args=20= satisfying=20`%s'"=0A-=09=09=20(car=20form)=20type-pred))))))=0A-=0A-=0A= -(defun=20rx-group-if=20(regexp=20group)=0A-=20=20"Put=20shy=20groups=20= around=20REGEXP=20if=20seemingly=20necessary=20when=20GROUP=0A-is=20= non-nil."=0A+;;=20The=20`rx--translate...'=20functions=20below=20return=20= (REGEXP=20.=20PRECEDENCE),=0A+;;=20where=20REGEXP=20is=20a=20list=20of=20= string=20expressions=20that=20will=20be=0A+;;=20concatenated=20into=20a=20= regexp,=20and=20PRECEDENCE=20is=20one=20of=0A+;;=0A+;;=20=20t=20=20=20=20= --=20can=20be=20used=20as=20argument=20to=20postfix=20operators=20(eg.=20= "a")=0A+;;=20=20seq=20=20--=20can=20be=20concatenated=20in=20sequence=20= with=20other=20seq=20or=20higher=20(eg.=20"ab")=0A+;;=20=20lseq=20--=20= can=20be=20concatenated=20to=20the=20left=20of=20rseq=20or=20higher=20= (eg.=20"^a")=0A+;;=20=20rseq=20--=20can=20be=20concatenated=20to=20the=20= right=20of=20lseq=20or=20higher=20(eg.=20"a$")=0A+;;=20=20nil=20=20--=20= can=20only=20be=20used=20in=20alternatives=20(eg.=20"a\\|b")=0A+;;=0A+;;=20= They=20form=20a=20lattice:=0A+;;=0A+;;=20=20=20=20=20=20=20=20=20=20=20t=20= =20=20=20=20=20=20=20=20=20highest=20precedence=0A+;;=20=20=20=20=20=20=20= =20=20=20=20|=0A+;;=20=20=20=20=20=20=20=20=20=20seq=0A+;;=20=20=20=20=20= =20=20=20=20/=20=20=20\=0A+;;=20=20=20=20=20=20lseq=20=20=20rseq=0A+;;=20= =20=20=20=20=20=20=20=20\=20=20=20/=0A+;;=20=20=20=20=20=20=20=20=20=20= nil=20=20=20=20=20=20=20=20=20lowest=20precedence=0A+=0A+=0A+(defconst=20= rx--char-classes=0A+=20=20'((digit=20=20=20=20=20=20=20=20=20.=20digit)=0A= +=20=20=20=20(numeric=20=20=20=20=20=20=20.=20digit)=0A+=20=20=20=20(num=20= =20=20=20=20=20=20=20=20=20=20.=20digit)=0A+=20=20=20=20(control=20=20=20= =20=20=20=20.=20cntrl)=0A+=20=20=20=20(cntrl=20=20=20=20=20=20=20=20=20.=20= cntrl)=0A+=20=20=20=20(hex-digit=20=20=20=20=20.=20xdigit)=0A+=20=20=20=20= (hex=20=20=20=20=20=20=20=20=20=20=20.=20xdigit)=0A+=20=20=20=20(xdigit=20= =20=20=20=20=20=20=20.=20xdigit)=0A+=20=20=20=20(blank=20=20=20=20=20=20=20= =20=20.=20blank)=0A+=20=20=20=20(graphic=20=20=20=20=20=20=20.=20graph)=0A= +=20=20=20=20(graph=20=20=20=20=20=20=20=20=20.=20graph)=0A+=20=20=20=20= (printing=20=20=20=20=20=20.=20print)=0A+=20=20=20=20(print=20=20=20=20=20= =20=20=20=20.=20print)=0A+=20=20=20=20(alphanumeric=20=20.=20alnum)=0A+=20= =20=20=20(alnum=20=20=20=20=20=20=20=20=20.=20alnum)=0A+=20=20=20=20= (letter=20=20=20=20=20=20=20=20.=20alpha)=0A+=20=20=20=20(alphabetic=20=20= =20=20.=20alpha)=0A+=20=20=20=20(alpha=20=20=20=20=20=20=20=20=20.=20= alpha)=0A+=20=20=20=20(ascii=20=20=20=20=20=20=20=20=20.=20ascii)=0A+=20=20= =20=20(nonascii=20=20=20=20=20=20.=20nonascii)=0A+=20=20=20=20(lower=20=20= =20=20=20=20=20=20=20.=20lower)=0A+=20=20=20=20(lower-case=20=20=20=20.=20= lower)=0A+=20=20=20=20(punctuation=20=20=20.=20punct)=0A+=20=20=20=20= (punct=20=20=20=20=20=20=20=20=20.=20punct)=0A+=20=20=20=20(space=20=20=20= =20=20=20=20=20=20.=20space)=0A+=20=20=20=20(whitespace=20=20=20=20.=20= space)=0A+=20=20=20=20(white=20=20=20=20=20=20=20=20=20.=20space)=0A+=20=20= =20=20(upper=20=20=20=20=20=20=20=20=20.=20upper)=0A+=20=20=20=20= (upper-case=20=20=20=20.=20upper)=0A+=20=20=20=20(word=20=20=20=20=20=20=20= =20=20=20.=20word)=0A+=20=20=20=20(wordchar=20=20=20=20=20=20.=20word)=0A= +=20=20=20=20(unibyte=20=20=20=20=20=20=20.=20unibyte)=0A+=20=20=20=20= (multibyte=20=20=20=20=20.=20multibyte))=0A+=20=20"Alist=20mapping=20rx=20= symbols=20to=20character=20classes.=0A+Most=20of=20the=20names=20are=20= from=20SRE.")=0A+=0A+(defvar=20rx-constituents=20nil=0A+=20=20"Alist=20= of=20old-style=20rx=20extensions,=20for=20compatibility.=0A+Each=20= element=20is=20(SYMBOL=20.=20DEF).=0A+=0A+If=20DEF=20is=20a=20symbol,=20= then=20SYMBOL=20is=20an=20alias=20of=20DEF.=0A+=0A+If=20DEF=20is=20a=20= string,=20then=20SYMBOL=20is=20a=20plain=20rx=20symbol=20defined=20as=20= the=0A+=20=20=20regexp=20string=20DEF.=0A+=0A+If=20DEF=20is=20a=20list=20= on=20the=20form=20(FUN=20MIN-ARGS=20MAX-ARGS=20PRED),=20then=0A+=20=20=20= SYMBOL=20is=20an=20rx=20form=20with=20at=20least=20MIN-ARGS=20and=20at=20= most=0A+=20=20=20MAX-ARGS=20arguments.=0A+=20=20=20If=20MAX-ARGS=20is=20= nil,=20then=20there=20is=20no=20upper=20limit.=0A+=20=20=20FUN=20is=20a=20= function=20taking=20the=20entire=20rx=20form=20as=20argument=0A+=20=20=20= and=20returning=20the=20translated=20regexp=20string.=0A+=20=20=20If=20= PRED=20is=20non-nil,=20it=20is=20a=20predicate=20that=20all=20actual=20= arguments=20must=0A+=20=20=20satisfy.")=0A+=0A+(defvar=20= rx--global-definitions=20nil=0A+=20=20"Alist=20of=20global=20rx=20= definitions.=0A+Each=20entry=20is:=0A+=20(NAME=20DEF)=20=20=20=20=20=20= --=20NAME=20is=20an=20rx=20symbol=20defined=20as=20the=20rx=20form=20= DEF.=0A+=20(NAME=20ARGS=20DEF)=20--=20NAME=20is=20an=20rx=20form=20with=20= arglist=20ARGS,=20defined=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20as=20the=20rx=20form=20DEF=20(which=20can=20contain=20= members=20of=20ARGS).")=0A+=0A+(defvar=20rx--local-definitions=20nil=0A+=20= =20"Alist=20of=20dynamic=20local=20rx=20definitions.=0A+Takes=20= precedence=20over=20`rx--global-definitions',=20and=20has=20the=20same=20= type.")=0A+=0A+(defsubst=20rx--lookup-def=20(name)=0A+=20=20(or=20(assq=20= name=20rx--local-definitions)=0A+=20=20=20=20=20=20(assq=20name=20= rx--global-definitions)))=0A+=0A+;;=20TODO:=20Additions=20to=20consider:=0A= +;;=20-=20A=20better=20name=20for=20`anything',=20like=20`any-char'=20or=20= `anychar'.=0A+;;=20-=20A=20name=20for=20(or),=20maybe=20`unmatchable'.=0A= +;;=20-=20A=20construct=20like=20`or'=20but=20without=20the=20match=20= order=20guarantee,=0A+;;=20=20=20maybe=20`unordered-or'.=20=20Useful=20= for=20composition=20or=20generation=20of=0A+;;=20=20=20alternatives;=20= permits=20more=20effective=20use=20of=20regexp-opt.=0A+=0A+(defun=20= rx--translate-symbol=20(sym)=0A+=20=20"Translate=20an=20rx=20symbol.=20=20= Return=20(REGEXP=20.=20PRECEDENCE)."=0A+=20=20(pcase=20sym=0A+=20=20=20=20= ;;=20Use=20`list'=20instead=20of=20a=20quoted=20list=20to=20wrap=20the=20= strings=20here,=0A+=20=20=20=20;;=20since=20the=20return=20value=20may=20= be=20mutated.=0A+=20=20=20=20((or=20'nonl=20'not-newline=20'any)=20(cons=20= (list=20".")=20t))=0A+=20=20=20=20('anything=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20(rx--translate-form=20'(or=20nonl=20= "\n")))=0A+=20=20=20=20((or=20'bol=20'line-start)=20=20=20=20=20=20=20=20= (cons=20(list=20"^")=20'lseq))=0A+=20=20=20=20((or=20'eol=20'line-end)=20= =20=20=20=20=20=20=20=20=20(cons=20(list=20"$")=20'rseq))=0A+=20=20=20=20= ((or=20'bos=20'string-start=20'bot=20'buffer-start)=20(cons=20(list=20= "\\`")=20t))=0A+=20=20=20=20((or=20'eos=20'string-end=20=20=20'eot=20= 'buffer-end)=20=20=20(cons=20(list=20"\\'")=20t))=0A+=20=20=20=20('point=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= (list=20"\\=3D")=20t))=0A+=20=20=20=20((or=20'bow=20'word-start)=20=20=20= =20=20=20=20=20(cons=20(list=20"\\<")=20t))=0A+=20=20=20=20((or=20'eow=20= 'word-end)=20=20=20=20=20=20=20=20=20=20(cons=20(list=20"\\>")=20t))=0A+=20= =20=20=20('word-boundary=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (cons=20(list=20"\\b")=20t))=0A+=20=20=20=20('not-word-boundary=20=20=20=20= =20=20=20=20=20=20=20(cons=20(list=20"\\B")=20t))=0A+=20=20=20=20= ('symbol-start=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(cons=20= (list=20"\\_<")=20t))=0A+=20=20=20=20('symbol-end=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20(cons=20(list=20"\\_>")=20t))=0A+=20=20=20=20= ('not-wordchar=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(cons=20= (list=20"\\W")=20t))=0A+=20=20=20=20(_=0A+=20=20=20=20=20(cond=0A+=20=20=20= =20=20=20((let=20((class=20(cdr=20(assq=20sym=20rx--char-classes))))=0A+=20= =20=20=20=20=20=20=20=20(and=20class=20(cons=20(list=20(concat=20"[[:"=20= (symbol-name=20class)=20":]]"))=20t))))=0A+=0A+=20=20=20=20=20=20((let=20= ((definition=20(rx--lookup-def=20sym)))=0A+=20=20=20=20=20=20=20=20=20= (and=20definition=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20(if=20= (cddr=20definition)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20(error=20"Not=20an=20`rx'=20symbol=20definition:=20%s"=20sym)=0A+=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20(rx--translate=20(nth=201=20= definition))))))=0A+=0A+=20=20=20=20=20=20;;=20For=20compatibility=20= with=20old=20rx.=0A+=20=20=20=20=20=20((let=20((entry=20(assq=20sym=20= rx-constituents)))=0A+=20=20=20=20=20=20=20=20=20(and=20(progn=0A+=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20(while=20(and=20entry=20(not=20= (stringp=20(cdr=20entry))))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20(setq=20entry=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(if=20(symbolp=20(cdr=20entry))=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= ;;=20Alias=20for=20another=20entry.=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(assq=20(cdr=20entry)=20= rx-constituents)=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;;=20Wrong=20type,=20try=20further=20down=20the=20= list.=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(assq=20(car=20entry)=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(cdr=20(memq=20= entry=20rx-constituents))))))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20entry)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20(cons=20(list=20= (cdr=20entry))=20nil))))=0A+=20=20=20=20=20=20(t=20(error=20"Unknown=20= rx=20symbol=20`%s'"=20sym))))))=0A+=0A+(defun=20rx--enclose=20(left-str=20= rexp=20right-str)=0A+=20=20"Bracket=20REXP=20by=20LEFT-STR=20and=20= RIGHT-STR."=0A+=20=20(append=20(list=20left-str)=20rexp=20(list=20= right-str)))=0A+=0A+(defun=20rx--bracket=20(rexp)=0A+=20=20(rx--enclose=20= "\\(?:"=20rexp=20"\\)"))=0A+=0A+(defun=20rx--sequence=20(left=20right)=0A= +=20=20"Return=20the=20sequence=20(concatenation)=20of=20two=20= translated=20items,=0A+each=20on=20the=20form=20(REGEXP=20.=20= PRECEDENCE),=20returning=20(REGEXP=20.=20PRECEDENCE)."=0A+=20=20;;=20= Concatenation=20rules:=0A+=20=20;;=20=20seq=20=20++=20seq=20=20->=20seq=0A= +=20=20;;=20=20lseq=20++=20seq=20=20->=20lseq=0A+=20=20;;=20=20seq=20=20= ++=20rseq=20->=20rseq=0A+=20=20;;=20=20lseq=20++=20rseq=20->=20nil=0A+=20= =20(cond=20((not=20(car=20left))=20right)=0A+=20=20=20=20=20=20=20=20= ((not=20(car=20right))=20left)=0A+=20=20=20=20=20=20=20=20(t=0A+=20=20=20= =20=20=20=20=20=20(let=20((l=20(if=20(memq=20(cdr=20left)=20'(nil=20= rseq))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20(cons=20(rx--bracket=20(car=20left))=20t)=0A+=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20left))=0A+=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20(r=20(if=20(memq=20(cdr=20right)=20'(nil=20lseq))=0A+=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(cons=20= (rx--bracket=20(car=20right))=20t)=0A+=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20right)))=0A+=20=20=20=20=20=20=20=20=20=20=20= (cons=20(append=20(car=20l)=20(car=20r))=0A+=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20(if=20(eq=20(cdr=20l)=20'lseq)=0A+=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(if=20(eq=20(cdr=20r)=20= 'rseq)=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=20nil=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= ;=20lseq=20++=20rseq=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20'lseq)=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20;=20lseq=20++=20seq=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20(if=20(eq=20(cdr=20r)=20'rseq)=0A+=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20'rseq=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20;=20seq=20++=20rseq=0A+=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20'seq)))))))=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20;=20seq=20++=20seq=0A+=0A+(defun=20= rx--translate-seq=20(body)=0A+=20=20"Translate=20a=20sequence=20of=20one=20= or=20more=20rx=20items.=20=20Return=20(REGEXP=20.=20PRECEDENCE)."=0A+=20=20= (if=20body=0A+=20=20=20=20=20=20(let*=20((items=20(mapcar=20= #'rx--translate=20body))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20= (result=20(car=20items)))=0A+=20=20=20=20=20=20=20=20(dolist=20(item=20= (cdr=20items))=0A+=20=20=20=20=20=20=20=20=20=20(setq=20result=20= (rx--sequence=20result=20item)))=0A+=20=20=20=20=20=20=20=20result)=0A+=20= =20=20=20(cons=20nil=20'seq)))=0A+=0A+(defun=20rx--empty=20()=0A+=20=20= "Regexp=20that=20never=20matches=20anything."=0A+=20=20(cons=20(list=20= regexp-unmatchable)=20'seq))=0A+=0A+;;=20`cl-every'=20replacement=20to=20= avoid=20bootstrapping=20problems.=0A+(defun=20rx--every=20(pred=20list)=0A= +=20=20"Whether=20PRED=20is=20true=20for=20every=20element=20of=20LIST."=0A= +=20=20(while=20(and=20list=20(funcall=20pred=20(car=20list)))=0A+=20=20=20= =20(setq=20list=20(cdr=20list)))=0A+=20=20(null=20list))=0A+=0A+(defun=20= rx--translate-or=20(body)=0A+=20=20"Translate=20an=20or-pattern=20of=20= one=20of=20more=20rx=20items.=0A+Return=20(REGEXP=20.=20PRECEDENCE)."=0A= +=20=20;;=20FIXME:=20Possible=20improvements:=0A+=20=20;;=0A+=20=20;;=20= -=20Turn=20single=20characters=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=20= candidates=20for=20regexp-opt.=0A+=20=20;;=0A+=20=20;;=20-=20Translate=20= compile-time=20strings=20(`eval'=20forms),=20again=20for=20regexp-opt.=0A= +=20=20;;=0A+=20=20;;=20-=20Flatten=20sub-patterns=20first:=20(or=20(or=20= A=20B)=20(or=20C=20D))=20->=20(or=20A=20B=20C=20D)=0A+=20=20;;=20=20=20= in=20order=20to=20improve=20effectiveness=20of=20regexp-opt.=0A+=20=20;;=20= =20=20This=20would=20also=20help=20composability.=0A+=20=20;;=0A+=20=20= ;;=20-=20Use=20associativity=20to=20run=20regexp-opt=20on=20contiguous=20= subsets=20of=20arguments=0A+=20=20;;=20=20=20if=20not=20all=20of=20them=20= are=20strings.=20=20Example:=0A+=20=20;;=20=20=20(or=20(+=20digit)=20= "CHARLIE"=20"CHAN"=20(+=20blank))=0A+=20=20;;=20=20=20->=20(or=20(+=20= digit)=20(or=20"CHARLIE"=20"CHAN")=20(+=20blank))=0A+=20=20;;=0A+=20=20= ;;=20-=20Fuse=20patterns=20into=20a=20single=20character=20alternative=20= if=20they=20fit.=0A+=20=20;;=20=20=20regexp-opt=20will=20do=20that=20if=20= all=20are=20strings,=20but=20we=20want=20to=20do=20that=20for:=0A+=20=20= ;;=20=20=20=20=20*=20symbols=20that=20expand=20to=20classes:=20space,=20= alpha,=20...=0A+=20=20;;=20=20=20=20=20*=20character=20alternatives:=20= (any=20...)=0A+=20=20;;=20=20=20=20=20*=20(syntax=20S),=20for=20some=20S=20= (whitespace,=20word)=0A+=20=20;;=20=20=20so=20that=20(or=20"@"=20"%"=20= digit=20(any=20"A-Z"=20space)=20(syntax=20word))=0A+=20=20;;=20=20=20=20=20= =20=20=20->=20(any=20"@"=20"%"=20digit=20"A-Z"=20space=20word)=0A+=20=20= ;;=20=20=20=20=20=20=20=20->=20"[A-Z@%[:digit:][:space:][:word:]]"=0A+=20= =20;;=0A+=20=20;;=20Problem:=20If=20a=20subpattern=20is=20carefully=20= written=20to=20to=20be=0A+=20=20;;=20optimisable=20by=20regexp-opt,=20= how=20do=20we=20prevent=20the=20transforms=0A+=20=20;;=20above=20from=20= destroying=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;;=20for=20some=20= repetition=0A-=20=20=20((eq=20group=20'*)=20(if=20(rx-atomic-p=20regexp)=20= (setq=20group=20nil)))=0A-=20=20=20;;=20for=20concatenation=0A-=20=20=20= ((eq=20group=20':)=0A-=20=20=20=20(if=20(rx-atomic-p=0A-=20=20=20=20=20=20= =20=20=20(if=20(and=20(stringp=20regexp)=0A-=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20(string-match=0A-=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20= "\\(?:[?*+]\\??\\|\\\\{[0-9]*,?[0-9]*\\\\}\\)\\'"=20regexp))=0A-=09=20=20= =20=20=20(substring=20regexp=200=20(match-beginning=200))=0A-=09=20=20=20= regexp))=0A-=09(setq=20group=20nil)))=0A-=20=20=20;;=20for=20OR=0A-=20=20= =20((eq=20group=20'|)=20(setq=20group=20nil))=0A-=20=20=20;;=20do=20= anyway=0A-=20=20=20((eq=20group=20t))=0A-=20=20=20((rx-atomic-p=20regexp=20= t)=20(setq=20group=20nil)))=0A-=20=20(cond=20((and=20group=20(stringp=20= regexp))=0A-=20=20=20=20=20=20=20=20=20(concat=20"\\(?:"=20regexp=20= "\\)"))=0A-=20=20=20=20=20=20=20=20(group=20`("\\(?:"=20,@regexp=20= "\\)"))=0A-=20=20=20=20=20=20=20=20(t=20regexp)))=0A-=0A-=0A-(defvar=20= rx-parent)=0A-;;=20dynamically=20bound=20in=20some=20functions.=0A-=0A-=0A= -(defun=20rx-and=20(form)=0A-=20=20"Parse=20and=20produce=20code=20from=20= FORM.=0A-FORM=20is=20of=20the=20form=20`(and=20FORM1=20...)'."=0A-=20=20= (rx-check=20form)=0A-=20=20(rx-group-if=0A-=20=20=20(rx--subforms=20(cdr=20= form)=20':)=0A-=20=20=20(and=20(memq=20rx-parent=20'(*=20t))=20= rx-parent)))=0A-=0A-=0A-(defun=20rx-or=20(form)=0A-=20=20"Parse=20and=20= produce=20code=20from=20FORM,=20which=20is=20`(or=20FORM1=20...)'."=0A-=20= =20(rx-check=20form)=0A-=20=20(rx-group-if=0A-=20=20=20(cond=0A-=20=20=20= =20((null=20(cdr=20form))=20regexp-unmatchable)=0A-=20=20=20=20= ((cl-every=20#'stringp=20(cdr=20form))=0A-=20=20=20=20=20(regexp-opt=20= (cdr=20form)=20nil=20t))=0A-=20=20=20=20(t=20(rx--subforms=20(cdr=20= form)=20'|=20"\\|")))=0A-=20=20=20(and=20(memq=20rx-parent=20'(:=20*=20= t))=20rx-parent)))=0A-=0A-=0A-(defun=20rx-anything=20(form)=0A-=20=20= "Match=20any=20character."=0A-=20=20(if=20(consp=20form)=0A-=20=20=20=20=20= =20(error=20"rx=20`anything'=20syntax=20error:=20%s"=20form))=0A-=20=20= (rx-or=20(list=20'or=20'not-newline=20?\n)))=0A-=0A-=0A-(defun=20= rx-any-delete-from-range=20(char=20ranges)=0A-=20=20"Delete=20by=20side=20= effect=20character=20CHAR=20from=20RANGES.=0A-Only=20both=20edges=20of=20= each=20range=20is=20checked."=0A-=20=20(let=20(m)=0A-=20=20=20=20(cond=0A= -=20=20=20=20=20((memq=20char=20ranges)=20(setq=20ranges=20(delq=20char=20= ranges)))=0A-=20=20=20=20=20((setq=20m=20(assq=20char=20ranges))=0A-=20=20= =20=20=20=20(if=20(eq=20(1+=20char)=20(cdr=20m))=0A-=09=20=20(setcar=20= (memq=20m=20ranges)=20(1+=20char))=0A-=09(setcar=20m=20(1+=20char))))=0A= -=20=20=20=20=20((setq=20m=20(rassq=20char=20ranges))=0A-=20=20=20=20=20=20= (if=20(eq=20(1-=20char)=20(car=20m))=0A-=09=20=20(setcar=20(memq=20m=20= ranges)=20(1-=20char))=0A-=09(setcdr=20m=20(1-=20char)))))=0A-=20=20=20=20= ranges))=0A-=0A-=0A-(defun=20rx-any-condense-range=20(args)=0A-=20=20= "Condense=20by=20side=20effect=20ARGS=20as=20range=20for=20Rx=20`any'."=0A= -=20=20(let=20(str=0A-=09l)=0A-=20=20=20=20;;=20set=20STR=20list=20of=20= all=20strings=0A-=20=20=20=20;;=20set=20L=20list=20of=20all=20ranges=0A-=20= =20=20=20(mapc=20(lambda=20(e)=20(cond=20((stringp=20e)=20(push=20e=20= str))=0A-=09=09=09=20=20=20=20((numberp=20e)=20(push=20(cons=20e=20e)=20= l))=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;;=20Ranges=20between=20ASCII=20and=20raw=20bytes=20= are=20split,=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;;=20to=20prevent=20accidental=20inclusion=20= of=20Unicode=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;;=20characters=20later=20on.=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= ((and=20(<=3D=20(car=20e)=20#x7f)=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=20=20(>=3D=20= (cdr=20e)=20#x3fff80))=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(push=20(cons=20(car=20e)=20#x7f)=20= l)=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(push=20(cons=20#x3fff80=20(cdr=20e))=20l))=0A-=09=09=09= =20=20=20=20(t=20(push=20e=20l))))=0A-=09=20=20args)=0A-=20=20=20=20;;=20= condense=20overlapped=20ranges=20in=20L=0A-=20=20=20=20(let=20((tail=20= (setq=20l=20(sort=20l=20#'car-less-than-car)))=0A-=09=20=20d)=0A-=20=20=20= =20=20=20(while=20(setq=20d=20(cdr=20tail))=0A-=09(if=20(>=3D=20(cdar=20= tail)=20(1-=20(caar=20d)))=0A-=09=20=20=20=20(progn=0A-=09=20=20=20=20=20= =20(setcdr=20(car=20tail)=20(max=20(cdar=20tail)=20(cdar=20d)))=0A-=09=20= =20=20=20=20=20(setcdr=20tail=20(cdr=20d)))=0A-=09=20=20(setq=20tail=20= d))))=0A-=20=20=20=20;;=20Separate=20small=20ranges=20to=20single=20= number,=20and=20delete=20dups.=0A-=20=20=20=20(nconc=0A-=20=20=20=20=20= (apply=20#'nconc=0A-=09=20=20=20=20(mapcar=20(lambda=20(e)=0A-=09=09=20=20= =20=20=20=20(cond=0A-=09=09=20=20=20=20=20=20=20((=3D=20(car=20e)=20(cdr=20= e))=20(list=20(car=20e)))=0A-=09=09=20=20=20=20=20=20=20((=3D=20(1+=20= (car=20e))=20(cdr=20e))=20(list=20(car=20e)=20(cdr=20e)))=0A-=09=09=20=20= =20=20=20=20=20((list=20e))))=0A-=09=09=20=20=20=20l))=0A-=20=20=20=20=20= (delete-dups=20str))))=0A-=0A-=0A-(defun=20rx-check-any-string=20(str)=0A= -=20=20"Turn=20the=20`any'=20argument=20string=20STR=20into=20a=20list=20= of=20characters.=0A-The=20original=20order=20is=20not=20preserved.=20=20= Ranges,=20\"A-Z\",=20become=20pairs,=20(?A=20.=20?Z)."=0A+=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= (rx--empty))=0A+=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(rx--translate=20(car=20= body)))=0A+=20=20=20((rx--every=20#'stringp=20body)=20=20=20=20=20;=20= All=20strings.=0A+=20=20=20=20(cons=20(list=20(regexp-opt=20body=20nil=20= t))=0A+=20=20=20=20=20=20=20=20=20=20t))=0A+=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+=0A+(defun=20= rx--string-to-intervals=20(str)=0A+=20=20"Decode=20STR=20as=20intervals:=20= A-Z=20becomes=20(?A=20.=20?Z),=20and=20the=20single=0A+character=20X=20= becomes=20(?X=20.=20?X).=20=20Return=20the=20intervals=20in=20a=20list."=0A= +=20=20;;=20We=20could=20just=20do=20string-to-multibyte=20on=20the=20= string=20and=20work=20with=0A+=20=20;;=20that=20instead=20of=20this=20= `decode-char'=20workaround.=0A=20=20=20(let=20((decode-char=0A-=20=20=20=20= =20=20=20=20=20;;=20Make=20sure=20raw=20bytes=20are=20decoded=20as=20= such,=20to=20avoid=20confusion=20with=0A-=20=20=20=20=20=20=20=20=20;;=20= U+0080..U+00FF.=0A=20=20=20=20=20=20=20=20=20=20(if=20= (multibyte-string-p=20str)=0A=20=20=20=20=20=20=20=20=20=20=20=20=20=20= #'identity=0A-=20=20=20=20=20=20=20=20=20=20=20(lambda=20(c)=20(if=20(<=3D= =20#x80=20c=20#xff)=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(+=20c=20#x3fff00)=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=20c))))=0A+=20=20=20=20= =20=20=20=20=20=20=20#'unibyte-char-to-multibyte))=0A=20=20=20=20=20=20=20= =20=20(len=20(length=20str))=0A=20=20=20=20=20=20=20=20=20(i=200)=0A-=20=20= =20=20=20=20=20=20(ret=20nil))=0A-=20=20=20=20(if=20(=3D=200=20len)=0A-=20= =20=20=20=20=20=20=20(error=20"String=20arg=20for=20Rx=20`any'=20must=20= not=20be=20empty"))=0A+=20=20=20=20=20=20=20=20(intervals=20nil))=0A=20=20= =20=20=20(while=20(<=20i=20len)=0A=20=20=20=20=20=20=20(cond=20((and=20= (<=20i=20(-=20len=202))=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20(=3D=20(aref=20str=20(+=20i=201))=20?-))=0A+=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20(=3D=20(aref=20str=20(1+=20i))=20?-))=0A=20= =20=20=20=20=20=20=20=20=20=20=20=20=20;;=20Range.=0A=20=20=20=20=20=20=20= =20=20=20=20=20=20=20(let=20((start=20(funcall=20decode-char=20(aref=20= str=20i)))=0A=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (end=20=20=20(funcall=20decode-char=20(aref=20str=20(+=20i=202)))))=0A-=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20(cond=20((<=20start=20end)=20= (push=20(cons=20start=20end)=20ret))=0A-=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20((=3D=20start=20end)=20(push=20start=20= ret))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(cond=20((and=20= (<=3D=20start=20#x7f)=20(>=3D=20end=20#x3fff80))=0A+=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20;;=20Ranges=20between=20= ASCII=20and=20raw=20bytes=20are=20split=20to=0A+=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20;;=20avoid=20having=20them=20= absorb=20Unicode=20characters=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20;;=20caught=20in-between.=0A+=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(push=20(cons=20start=20= #x7f)=20intervals)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20(push=20(cons=20#x3fff80=20end)=20intervals))=0A+=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20((<=3D=20start=20= end)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (push=20(cons=20start=20end)=20intervals))=0A=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20(t=0A-=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20(error=20"Rx=20character=20range=20= `%c-%c'=20is=20reversed"=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=20start=20end)))=0A+=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(error=20"Invalid=20= rx=20`any'=20range:=20%s"=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(substring=20str=20i=203))))=0A= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(setq=20i=20(+=20i=20= 3))))=0A=20=20=20=20=20=20=20=20=20=20=20=20=20(t=0A=20=20=20=20=20=20=20= =20=20=20=20=20=20=20;;=20Single=20character.=0A-=20=20=20=20=20=20=20=20= =20=20=20=20=20(push=20(funcall=20decode-char=20(aref=20str=20i))=20ret)=0A= +=20=20=20=20=20=20=20=20=20=20=20=20=20(let=20((char=20(funcall=20= decode-char=20(aref=20str=20i))))=0A+=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20(push=20(cons=20char=20char)=20intervals))=0A=20=20=20=20=20=20=20= =20=20=20=20=20=20=20(setq=20i=20(+=20i=201)))))=0A-=20=20=20=20ret))=0A= -=0A-=0A-(defun=20rx-check-any=20(arg)=0A-=20=20=20"Check=20arg=20ARG=20= for=20Rx=20`any'."=0A-=20=20=20(cond=0A-=20=20=20=20((integerp=20arg)=20= (list=20arg))=0A-=20=20=20=20((symbolp=20arg)=0A-=20=20=20=20=20(let=20= ((translation=20(condition-case=20nil=0A-=09=09=09=20=20=20=20(rx-form=20= arg)=0A-=09=09=09=20=20(error=20nil))))=0A-=20=20=20=20=20=20=20(if=20= (or=20(null=20translation)=0A-=09=20=20=20=20=20=20=20(null=20= (string-match=20"\\`\\[\\[:[-a-z]+:\\]\\]\\'"=20translation)))=0A-=09=20=20= =20(error=20"Invalid=20char=20class=20`%s'=20in=20Rx=20`any'"=20arg))=0A= -=20=20=20=20=20=20=20(list=20(substring=20translation=201=20-1))))=20;=20= strip=20outer=20brackets=0A-=20=20=20=20((and=20(characterp=20(car-safe=20= arg))=20(characterp=20(cdr-safe=20arg)))=0A-=20=20=20=20=20(unless=20(<=3D= =20(car=20arg)=20(cdr=20arg))=0A-=20=20=20=20=20=20=20(error=20"Rx=20= character=20range=20`%c-%c'=20is=20reversed"=0A-=20=20=20=20=20=20=20=20=20= =20=20=20=20=20(car=20arg)=20(cdr=20arg)))=0A-=20=20=20=20=20(list=20= arg))=0A-=20=20=20=20((stringp=20arg)=20(rx-check-any-string=20arg))=0A-=20= =20=20=20((error=0A-=20=20=20=20=20=20"rx=20`any'=20requires=20string,=20= character,=20char=20pair=20or=20char=20class=20args"))))=0A-=0A-=0A= -(defun=20rx-any=20(form)=0A-=20=20"Parse=20and=20produce=20code=20from=20= FORM,=20which=20is=20`(any=20ARG=20...)'.=0A-ARG=20is=20optional."=0A-=20= =20(rx-check=20form)=0A-=20=20(let*=20((args=20(rx-any-condense-range=0A= -=09=09(apply=0A-=09=09=20#'nconc=0A-=09=09=20(mapcar=20#'rx-check-any=20= (cdr=20form)))))=0A-=09=20m=0A-=09=20s)=0A-=20=20=20=20(cond=0A-=20=20=20= =20=20;;=20single=20close=20bracket=0A-=20=20=20=20=20;;=09=20=3D>=20= "[]...-]"=20or=20"[]...--.]"=0A-=20=20=20=20=20((memq=20?\]=20args)=0A-=20= =20=20=20=20=20;;=20set=20]=20at=20the=20beginning=0A-=20=20=20=20=20=20= (setq=20args=20(cons=20?\]=20(delq=20?\]=20args)))=0A-=20=20=20=20=20=20= ;;=20set=20-=20at=20the=20end=0A-=20=20=20=20=20=20(if=20(or=20(memq=20= ?-=20args)=20(assq=20?-=20args))=0A-=09=20=20(setq=20args=20(nconc=20= (rx-any-delete-from-range=20?-=20args)=0A-=09=09=09=20=20=20=20(list=20= ?-)))))=0A-=20=20=20=20=20;;=20close=20bracket=20starts=20a=20range=0A-=20= =20=20=20=20;;=20=20=3D>=20"[]-....-]"=20or=20"[]-.--....]"=0A-=20=20=20=20= =20((setq=20m=20(assq=20?\]=20args))=0A-=20=20=20=20=20=20;;=20bring=20= it=20to=20the=20beginning=0A-=20=20=20=20=20=20(setq=20args=20(cons=20m=20= (delq=20m=20args)))=0A-=20=20=20=20=20=20(cond=20((memq=20?-=20args)=0A-=09= =20=20=20=20=20;;=20to=20the=20end=0A-=09=20=20=20=20=20(setq=20args=20= (nconc=20(delq=20?-=20args)=20(list=20?-))))=0A-=09=20=20=20=20((setq=20= m=20(assq=20?-=20args))=0A-=09=20=20=20=20=20;;=20next=20to=20the=20= bracket's=20range,=20make=20the=20second=20range=0A-=09=20=20=20=20=20= (setcdr=20args=20(cons=20m=20(delq=20m=20(cdr=20args)))))))=0A-=20=20=20=20= =20;;=20bracket=20in=20the=20end=20range=0A-=20=20=20=20=20;;=09=20=3D>=20= "[]...-]"=0A-=20=20=20=20=20((setq=20m=20(rassq=20?\]=20args))=0A-=20=20=20= =20=20=20;;=20set=20]=20at=20the=20beginning=0A-=20=20=20=20=20=20(setq=20= args=20(cons=20?\]=20(rx-any-delete-from-range=20?\]=20args)))=0A-=20=20=20= =20=20=20;;=20set=20-=20at=20the=20end=0A-=20=20=20=20=20=20(if=20(or=20= (memq=20?-=20args)=20(assq=20?-=20args))=0A-=09=20=20(setq=20args=20= (nconc=20(rx-any-delete-from-range=20?-=20args)=0A-=09=09=09=20=20=20=20= (list=20?-)))))=0A-=20=20=20=20=20;;=20{no=20close=20bracket=20appears}=0A= -=20=20=20=20=20;;=0A-=20=20=20=20=20;;=20bring=20single=20bar=20to=20= the=20beginning=0A-=20=20=20=20=20((memq=20?-=20args)=0A-=20=20=20=20=20=20= (setq=20args=20(cons=20?-=20(delq=20?-=20args))))=0A-=20=20=20=20=20;;=20= bar=20start=20a=20range,=20bring=20it=20to=20the=20beginning=0A-=20=20=20= =20=20((setq=20m=20(assq=20?-=20args))=0A-=20=20=20=20=20=20(setq=20args=20= (cons=20m=20(delq=20m=20args))))=0A-=20=20=20=20=20;;=0A-=20=20=20=20=20= ;;=20hat=20at=20the=20beginning?=0A-=20=20=20=20=20((or=20(eq=20(car=20= args)=20?^)=20(eq=20(car-safe=20(car=20args))=20?^))=0A-=20=20=20=20=20=20= (setq=20args=20(if=20(cdr=20args)=0A-=09=09=20=20=20=20=20`(,(cadr=20= args)=20,(car=20args)=20,@(cddr=20args))=0A-=09=09=20=20=20(nconc=20= (rx-any-delete-from-range=20?^=20args)=0A-=09=09=09=20=20(list=20= ?^))))))=0A-=20=20=20=20;;=20some=201-char?=0A-=20=20=20=20(if=20(and=20= (null=20(cdr=20args))=20(numberp=20(car=20args))=0A-=09=20=20=20=20=20= (or=20(=3D=201=20(length=0A-=09=09=20=20=20=20=20=20=20(setq=20s=20= (regexp-quote=20(string=20(car=20args))))))=0A-=09=09=20(and=20(equal=20= (car=20args)=20?^)=20;;=20unnecessary=20predicate?=0A-=09=09=20=20=20=20=20= =20(null=20(eq=20rx-parent=20'!)))))=0A-=09s=0A-=20=20=20=20=20=20= (concat=20"["=0A-=09=20=20=20=20=20=20(mapconcat=0A-=09=20=20=20=20=20=20= =20(lambda=20(e)=20(cond=0A-=09=09=09=20=20=20=20((numberp=20e)=20= (string=20e))=0A-=09=09=09=20=20=20=20((consp=20e)=0A-=09=09=09=20=20=20=20= =20(if=20(and=20(=3D=20(1+=20(car=20e))=20(cdr=20e))=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=20=20=20=20=20=20;;=20rx-any-condense-range=20should=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=20=20=20=20=20=20;;=20prevent=20this=20case=20from=20happening.=0A= -=09=09=09=09=20=20=20=20=20=20(null=20(memq=20(car=20e)=20'(?\]=20?-)))=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=20=20=20=20=20=20(null=20(memq=20(cdr=20e)=20= '(?\]=20?-))))=0A-=09=09=09=09=20(string=20(car=20e)=20(cdr=20e))=0A-=09=09= =09=20=20=20=20=20=20=20(string=20(car=20e)=20?-=20(cdr=20e))))=0A-=09=09= =09=20=20=20=20(e)))=0A-=09=20=20=20=20=20=20=20args=0A-=09=20=20=20=20=20= =20=20nil)=0A-=09=20=20=20=20=20=20"]"))))=0A-=0A-=0A-(defun=20= rx-check-not=20(arg)=0A-=20=20"Check=20arg=20ARG=20for=20Rx=20`not'."=0A= -=20=20(unless=20(or=20(and=20(symbolp=20arg)=0A-=09=09=20=20=20= (string-match=20"\\`\\[\\[:[-a-z]+:\\]\\]\\'"=0A-=09=09=09=09=20= (condition-case=20nil=0A-=09=09=09=09=20=20=20=20=20(rx-form=20arg)=0A-=09= =09=09=09=20=20=20(error=20""))))=0A-=09=20=20=20=20=20=20(eq=20arg=20= 'word-boundary)=0A-=09=20=20=20=20=20=20(and=20(consp=20arg)=0A-=09=09=20= =20=20(memq=20(car=20arg)=20'(not=20any=20in=20syntax=20category))))=0A-=20= =20=20=20(error=20"rx=20`not'=20syntax=20error:=20%s"=20arg))=0A-=20=20= t)=0A-=0A-=0A-(defun=20rx-not=20(form)=0A-=20=20"Parse=20and=20produce=20= code=20from=20FORM.=20=20FORM=20is=20`(not=20...)'."=0A-=20=20(rx-check=20= form)=0A-=20=20(let=20((result=20(rx-form=20(cadr=20form)=20'!))=0A-=09= case-fold-search)=0A-=20=20=20=20(cond=20((string-match=20"\\`\\[\\^"=20= result)=0A-=09=20=20=20(cond=0A-=09=20=20=20=20((equal=20result=20"[^]")=20= "[^^]")=0A-=09=20=20=20=20((and=20(=3D=20(length=20result)=204)=20(null=20= (eq=20rx-parent=20'!)))=0A-=09=20=20=20=20=20(regexp-quote=20(substring=20= result=202=203)))=0A-=09=20=20=20=20((concat=20"["=20(substring=20result=20= 2)))))=0A-=09=20=20((eq=20?\[=20(aref=20result=200))=0A-=09=20=20=20= (concat=20"[^"=20(substring=20result=201)))=0A-=09=20=20((string-match=20= "\\`\\\\[scbw]"=20result)=0A-=09=20=20=20(concat=20(upcase=20(substring=20= result=200=202))=0A-=09=09=20=20=20(substring=20result=202)))=0A-=09=20=20= ((string-match=20"\\`\\\\[SCBW]"=20result)=0A-=09=20=20=20(concat=20= (downcase=20(substring=20result=200=202))=0A-=09=09=20=20=20(substring=20= result=202)))=0A-=09=20=20(t=0A-=09=20=20=20(concat=20"[^"=20result=20= "]")))))=0A-=0A-=0A-(defun=20rx-not-char=20(form)=0A-=20=20"Parse=20and=20= produce=20code=20from=20FORM.=20=20FORM=20is=20`(not-char=20...)'."=0A-=20= =20(rx-check=20form)=0A-=20=20(rx-not=20`(not=20(in=20,@(cdr=20form)))))=0A= -=0A-=0A-(defun=20rx-not-syntax=20(form)=0A-=20=20"Parse=20and=20produce=20= code=20from=20FORM.=20=20FORM=20is=20`(not-syntax=20SYNTAX)'."=0A-=20=20= (rx-check=20form)=0A-=20=20(rx-not=20`(not=20(syntax=20,@(cdr=20= form)))))=0A-=0A-=0A-(defun=20rx-trans-forms=20(form=20&optional=20skip)=0A= -=20=20"If=20FORM's=20length=20is=20greater=20than=20two,=20transform=20= it=20to=20length=20two.=0A-A=20form=20(HEAD=20REST=20...)=20becomes=20= (HEAD=20(and=20REST=20...)).=0A-If=20SKIP=20is=20non-nil,=20allow=20that=20= number=20of=20items=20after=20the=20head,=20i.e.=0A-`(=3D=20N=20REST=20= ...)'=20becomes=20`(=3D=20N=20(and=20REST=20...))'=20if=20SKIP=20is=20= 1."=0A-=20=20(unless=20skip=20(setq=20skip=200))=0A-=20=20(let=20((tail=20= (nthcdr=20(1+=20skip)=20form)))=0A-=20=20=20=20(if=20(=3D=20(length=20= tail)=201)=0A-=09form=0A-=20=20=20=20=20=20(let=20((form=20= (copy-sequence=20form)))=0A-=09(setcdr=20(nthcdr=20skip=20form)=20(list=20= (cons=20'and=20tail)))=0A-=09form))))=0A-=0A-=0A-(defun=20rx-=3D=20= (form)=0A-=20=20"Parse=20and=20produce=20code=20from=20FORM=20`(=3D=20N=20= ...)'."=0A-=20=20(rx-check=20form)=0A-=20=20(setq=20form=20= (rx-trans-forms=20form=201))=0A-=20=20(unless=20(and=20(integerp=20(nth=20= 1=20form))=0A-=09=20=20=20=20=20=20=20(>=20(nth=201=20form)=200))=0A-=20=20= =20=20(error=20"rx=20`=3D'=20requires=20positive=20integer=20first=20= arg"))=0A-=20=20(let=20((subform=20(rx-form=20(nth=202=20form)=20'*)))=0A= -=20=20=20=20(if=20(stringp=20subform)=0A-=20=20=20=20=20=20=20=20= (format=20"%s\\{%d\\}"=20subform=20(nth=201=20form))=0A-=20=20=20=20=20=20= `(,@subform=20,(format=20"\\{%d\\}"=20(nth=201=20form))))))=0A-=0A-=0A= -(defun=20rx->=3D=20(form)=0A-=20=20"Parse=20and=20produce=20code=20from=20= FORM=20`(>=3D=20N=20...)'."=0A-=20=20(rx-check=20form)=0A-=20=20(setq=20= form=20(rx-trans-forms=20form=201))=0A-=20=20(unless=20(and=20(integerp=20= (nth=201=20form))=0A-=09=20=20=20=20=20=20=20(>=20(nth=201=20form)=200))=0A= -=20=20=20=20(error=20"rx=20`>=3D'=20requires=20positive=20integer=20= first=20arg"))=0A-=20=20(let=20((subform=20(rx-form=20(nth=202=20form)=20= '*)))=0A-=20=20=20=20(if=20(stringp=20subform)=0A-=20=20=20=20=20=20=20=20= (format=20"%s\\{%d,\\}"=20subform=20(nth=201=20form))=0A-=20=20=20=20=20=20= `(,@subform=20,(format=20"\\{%d,\\}"=20(nth=201=20form))))))=0A-=0A-=0A= -(defun=20rx-**=20(form)=0A-=20=20"Parse=20and=20produce=20code=20from=20= FORM=20`(**=20N=20M=20...)'."=0A-=20=20(rx-check=20form)=0A-=20=20= (rx-form=20(cons=20'repeat=20(cdr=20(rx-trans-forms=20form=202)))=20'*))=0A= -=0A-=0A-(defun=20rx-repeat=20(form)=0A-=20=20"Parse=20and=20produce=20= code=20from=20FORM.=0A-FORM=20is=20either=20`(repeat=20N=20FORM1)'=20or=20= `(repeat=20N=20M=20FORMS...)'."=0A-=20=20(rx-check=20form)=0A-=20=20(if=20= (>=20(length=20form)=204)=0A-=20=20=20=20=20=20(setq=20form=20= (rx-trans-forms=20form=202)))=0A-=20=20(if=20(null=20(nth=202=20form))=0A= -=20=20=20=20=20=20(setq=20form=20(cons=20(nth=200=20form)=20(cons=20= (nth=201=20form)=20(nthcdr=203=20form)))))=0A-=20=20(cond=20((=3D=20= (length=20form)=203)=0A-=09=20(unless=20(and=20(integerp=20(nth=201=20= form))=0A-=09=09=20=20=20=20=20=20(>=20(nth=201=20form)=200))=0A-=09=20=20= =20(error=20"rx=20`repeat'=20requires=20positive=20integer=20first=20= arg"))=0A-=20=20=20=20=20=20=20=20=20(let=20((subform=20(rx-form=20(nth=20= 2=20form)=20'*)))=0A-=20=20=20=20=20=20=20=20=20=20=20(if=20(stringp=20= subform)=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(format=20= "%s\\{%d\\}"=20subform=20(nth=201=20form))=0A-=20=20=20=20=20=20=20=20=20= =20=20=20=20`(,@subform=20,(format=20"\\{%d\\}"=20(nth=201=20form))))))=0A= -=09((or=20(not=20(integerp=20(nth=202=20form)))=0A-=09=20=20=20=20=20(<=20= (nth=202=20form)=200)=0A-=09=20=20=20=20=20(not=20(integerp=20(nth=201=20= form)))=0A-=09=20=20=20=20=20(<=20(nth=201=20form)=200)=0A-=09=20=20=20=20= =20(<=20(nth=202=20form)=20(nth=201=20form)))=0A-=09=20(error=20"rx=20= `repeat'=20range=20error"))=0A-=09(t=0A-=20=20=20=20=20=20=20=20=20(let=20= ((subform=20(rx-form=20(nth=203=20form)=20'*)))=0A-=20=20=20=20=20=20=20=20= =20=20=20(if=20(stringp=20subform)=0A-=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20(format=20"%s\\{%d,%d\\}"=20subform=20(nth=201=20form)=20(nth=20= 2=20form))=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20`(,@subform=20= ,(format=20"\\{%d,%d\\}"=20(nth=201=20form)=20(nth=202=20form))))))))=0A= -=0A-=0A-(defun=20rx-submatch=20(form)=0A-=20=20"Parse=20and=20produce=20= code=20from=20FORM,=20which=20is=20`(submatch=20...)'."=0A-=20=20(let=20= ((subforms=20(rx--subforms=20(cdr=20form)=20':)))=0A-=20=20=20=20(if=20= (stringp=20subforms)=0A-=20=20=20=20=20=20=20=20(concat=20"\\("=20= subforms=20"\\)")=0A-=20=20=20=20=20=20`("\\("=20,@subforms=20"\\)"))))=0A= -=0A-(defun=20rx-submatch-n=20(form)=0A-=20=20"Parse=20and=20produce=20= code=20from=20FORM,=20which=20is=20`(submatch-n=20N=20...)'."=0A-=20=20= (let=20((n=20(nth=201=20form))=0A-=20=20=20=20=20=20=20=20(subforms=20= (rx--subforms=20(cddr=20form)=20':)))=0A-=20=20=20=20(unless=20(and=20= (integerp=20n)=20(>=20n=200))=0A-=20=20=20=20=20=20(error=20"rx=20= `submatch-n'=20argument=20must=20be=20positive"))=0A-=20=20=20=20(if=20= (stringp=20subforms)=0A-=20=20=20=20=20=20=20=20(concat=20"\\(?"=20= (number-to-string=20n)=20":"=20subforms=20"\\)")=0A-=20=20=20=20=20=20= `("\\(?"=20,(number-to-string=20n)=20":"=20,@subforms=20"\\)"))))=0A-=0A= -(defun=20rx-backref=20(form)=0A-=20=20"Parse=20and=20produce=20code=20= from=20FORM,=20which=20is=20`(backref=20N)'."=0A-=20=20(rx-check=20form)=0A= -=20=20(format=20"\\%d"=20(nth=201=20form)))=0A-=0A-(defun=20= rx-check-backref=20(arg)=0A-=20=20"Check=20arg=20ARG=20for=20Rx=20= `backref'."=0A-=20=20(or=20(and=20(integerp=20arg)=20(>=3D=20arg=201)=20= (<=3D=20arg=209))=0A-=20=20=20=20=20=20(error=20"rx=20`backref'=20= requires=20numeric=201<=3Darg<=3D9:=20%s"=20arg)))=0A-=0A-(defun=20= rx-kleene=20(form)=0A-=20=20"Parse=20and=20produce=20code=20from=20FORM.=0A= -FORM=20is=20`(OP=20FORM1)',=20where=20OP=20is=20one=20of=20the=20= `zero-or-one',=0A-`zero-or-more'=20etc.=20=20operators.=0A-If=20OP=20is=20= one=20of=20`*',=20`+',=20`?',=20produce=20a=20greedy=20regexp.=0A-If=20= OP=20is=20one=20of=20`*?',=20`+?',=20`??',=20produce=20a=20non-greedy=20= regexp.=0A-If=20OP=20is=20anything=20else,=20produce=20a=20greedy=20= regexp=20if=20`rx-greedy-flag'=0A-is=20non-nil."=0A-=20=20(rx-check=20= form)=0A-=20=20(setq=20form=20(rx-trans-forms=20form))=0A-=20=20(let=20= ((suffix=20(cond=20((memq=20(car=20form)=20'(*=20+=20\?=20?\s))=20"")=0A= -=09=09=20=20=20=20=20=20((memq=20(car=20form)=20'(*?=20+?=20\??=20??))=20= "?")=0A-=09=09=20=20=20=20=20=20(rx-greedy-flag=20"")=0A-=09=09=20=20=20=20= =20=20(t=20"?")))=0A-=09(op=20(cond=20((memq=20(car=20form)=20'(*=20*?=20= 0+=20zero-or-more))=20"*")=0A-=09=09=20=20((memq=20(car=20form)=20'(+=20= +?=201+=20one-or-more))=20=20"+")=0A-=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20(t=20"?")))=0A-=20=20=20=20=20=20=20=20(subform=20= (rx-form=20(cadr=20form)=20'*)))=0A-=20=20=20=20(rx-group-if=0A-=20=20=20= =20=20(if=20(stringp=20subform)=0A-=20=20=20=20=20=20=20=20=20(concat=20= subform=20op=20suffix)=0A-=20=20=20=20=20=20=20`(,@subform=20,(concat=20= op=20suffix)))=0A-=20=20=20=20=20(and=20(memq=20rx-parent=20'(t=20*))=20= rx-parent))))=0A-=0A-=0A-(defun=20rx-atomic-p=20(r=20&optional=20lax)=0A= -=20=20"Return=20non-nil=20if=20regexp=20string=20R=20is=20atomic.=0A-An=20= atomic=20regexp=20R=20is=20one=20such=20that=20a=20suffix=20operator=0A= -appended=20to=20R=20will=20apply=20to=20all=20of=20R.=20=20For=20= example,=20\"a\"=0A-\"[abc]\"=20and=20\"\\(ab\\|ab*c\\)\"=20are=20atomic=20= and=20\"ab\",=0A-\"[ab]c\",=20and=20\"ab\\|ab*c\"=20are=20not=20atomic.=0A= -=0A-This=20function=20may=20return=20false=20negatives,=20but=20it=20= will=20not=0A-return=20false=20positives.=20=20It=20is=20nevertheless=20= useful=20in=0A-situations=20where=20an=20efficiency=20shortcut=20can=20= be=20taken=20only=20if=20a=0A-regexp=20is=20atomic.=20=20The=20function=20= can=20be=20improved=20to=20detect=0A-more=20cases=20of=20atomic=20= regexps.=20=20Presently,=20this=20function=0A-detects=20the=20following=20= categories=20of=20atomic=20regexp;=0A-=0A-=20=20a=20group=20or=20shy=20= group:=20=20\\(...\\)=0A-=20=20a=20character=20class:=20=20=20=20=20= [...]=0A-=20=20a=20single=20character:=20=20=20=20a=0A-=0A-On=20the=20= other=20hand,=20false=20negatives=20will=20be=20returned=20for=0A= -regexps=20that=20are=20atomic=20but=20end=20in=20operators,=20such=20as=0A= -\"a+\".=20=20I=20think=20these=20are=20rare.=20=20Probably=20such=20= cases=20could=0A-be=20detected=20without=20much=20effort.=20=20A=20= guarantee=20of=20no=20false=0A-negatives=20would=20require=20a=20= theoretic=20specification=20of=20the=20set=0A-of=20all=20atomic=20= regexps."=0A-=20=20(if=20(and=20rx--compile-to-lisp=0A-=20=20=20=20=20=20= =20=20=20=20=20(not=20(stringp=20r)))=0A-=20=20=20=20=20=20nil=20;;=20= Runtime=20value,=20we=20must=20assume=20non-atomic.=0A-=20=20=20=20(let=20= ((l=20(length=20r)))=0A+=20=20=20=20intervals))=0A+=0A+(defun=20= rx--condense-intervals=20(intervals)=0A+=20=20"Merge=20adjacent=20and=20= overlapping=20intervals=20by=20mutation,=20preserving=20the=20order.=0A= +INTERVALS=20is=20a=20list=20of=20(START=20.=20END)=20with=20START=20=E2=89= =A4=20END,=20sorted=20by=20START."=0A+=20=20(let=20((tail=20intervals)=0A= +=20=20=20=20=20=20=20=20d)=0A+=20=20=20=20(while=20(setq=20d=20(cdr=20= tail))=0A+=20=20=20=20=20=20(if=20(>=3D=20(cdar=20tail)=20(1-=20(caar=20= d)))=0A+=20=20=20=20=20=20=20=20=20=20(progn=0A+=20=20=20=20=20=20=20=20=20= =20=20=20(setcdr=20(car=20tail)=20(max=20(cdar=20tail)=20(cdar=20d)))=0A= +=20=20=20=20=20=20=20=20=20=20=20=20(setcdr=20tail=20(cdr=20d)))=0A+=20=20= =20=20=20=20=20=20(setq=20tail=20d)))=0A+=20=20=20=20intervals))=0A+=0A= +;;=20FIXME:=20Consider=20expanding=20definitions=20inside=20(any=20...)=20= and=20(not=20...),=0A+;;=20and=20perhaps=20allow=20(any=20...)=20inside=20= (any=20...).=0A+;;=20It=20would=20be=20benefit=20composability=20(build=20= a=20character=20alternative=20by=20pieces)=0A+;;=20and=20be=20handy=20= for=20obtaining=20the=20complement=20of=20a=20defined=20set=20of=0A+;;=20= characters.=20=20(See,=20for=20example,=20python.el:421,=20= `not-simple-operator'.)=0A+;;=20(Expansion=20in=20other=20non-rx=20= positions=20is=20probably=20not=20a=20good=20idea:=0A+;;=20syntax,=20= category,=20backref,=20and=20the=20integer=20parameters=20of=20group-n,=0A= +;;=20=3D,=20>=3D,=20**,=20repeat)=0A+;;=20Similar=20effect=20could=20be=20= attained=20by=20ensuring=20that=0A+;;=20(or=20(any=20X)=20(any=20Y))=20= ->=20(any=20X=20Y),=20and=20find=20a=20way=20to=20compose=20negative=0A= +;;=20sets.=20=20`and'=20is=20taken,=20but=20we=20could=20add=0A+;;=20= (intersection=20(not=20(any=20X))=20(not=20(any=20Y)))=20->=20(not=20= (any=20X=20Y)).=0A+=0A+(defun=20rx--translate-any=20(negated=20body)=0A+=20= =20"Translate=20an=20(any=20...)=20construct.=20=20Return=20(REGEXP=20.=20= PRECEDENCE).=0A+If=20NEGATED,=20negate=20the=20sense."=0A+=20=20(let=20= ((classes=20nil)=0A+=20=20=20=20=20=20=20=20(strings=20nil)=0A+=20=20=20=20= =20=20=20=20(conses=20nil))=0A+=20=20=20=20;;=20Collect=20strings,=20= conses=20and=20characters,=20and=20classes=20in=20separate=20bins.=0A+=20= =20=20=20(dolist=20(arg=20body)=0A+=20=20=20=20=20=20(cond=20((stringp=20= arg)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20(push=20arg=20strings))=0A= +=20=20=20=20=20=20=20=20=20=20=20=20((and=20(consp=20arg)=0A+=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20(characterp=20(car=20arg))=0A+=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(characterp=20(cdr=20= arg))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(<=3D=20= (car=20arg)=20(cdr=20arg)))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20;;=20= Copy=20the=20cons,=20in=20case=20we=20need=20to=20modify=20it.=0A+=20=20=20= =20=20=20=20=20=20=20=20=20=20(push=20(cons=20(car=20arg)=20(cdr=20arg))=20= conses))=0A+=20=20=20=20=20=20=20=20=20=20=20=20((characterp=20arg)=0A+=20= =20=20=20=20=20=20=20=20=20=20=20=20(push=20(cons=20arg=20arg)=20= conses))=0A+=20=20=20=20=20=20=20=20=20=20=20=20((and=20(symbolp=20arg)=0A= +=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(let=20((class=20= (cdr=20(assq=20arg=20rx--char-classes))))=0A+=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20(and=20class=20(push=20class=20= classes)))))=0A+=20=20=20=20=20=20=20=20=20=20=20=20(t=20(error=20= "Invalid=20rx=20`any'=20argument:=20%s"=20arg))))=0A+=20=20=20=20(let=20= ((items=0A+=20=20=20=20=20=20=20=20=20=20=20;;=20Translate=20strings=20= and=20conses=20into=20nonoverlapping=20intervals,=0A+=20=20=20=20=20=20=20= =20=20=20=20;;=20and=20add=20classes=20as=20symbols=20at=20the=20end.=0A= +=20=20=20=20=20=20=20=20=20=20=20(append=0A+=20=20=20=20=20=20=20=20=20=20= =20=20(rx--condense-intervals=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20= (sort=20(append=20conses=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(mapcan=20#'rx--string-to-intervals=20= strings))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= #'car-less-than-car))=0A+=20=20=20=20=20=20=20=20=20=20=20=20(reverse=20= classes))))=0A+=0A+=20=20=20=20=20=20;;=20Move=20lone=20]=20and=20range=20= ]-x=20to=20the=20start.=0A+=20=20=20=20=20=20(let=20((rbrac-l=20(assq=20= ?\]=20items)))=0A+=20=20=20=20=20=20=20=20(when=20rbrac-l=0A+=20=20=20=20= =20=20=20=20=20=20(setq=20items=20(cons=20rbrac-l=20(delq=20rbrac-l=20= items)))))=0A+=0A+=20=20=20=20=20=20;;=20Split=20x-]=20and=20move=20the=20= lone=20]=20to=20the=20start.=0A+=20=20=20=20=20=20(let=20((rbrac-r=20= (rassq=20?\]=20items)))=0A+=20=20=20=20=20=20=20=20(when=20(and=20= rbrac-r=20(not=20(eq=20(car=20rbrac-r)=20?\])))=0A+=20=20=20=20=20=20=20=20= =20=20(setcdr=20rbrac-r=20?\\)=0A+=20=20=20=20=20=20=20=20=20=20(setq=20= items=20(cons=20'(?\]=20.=20?\])=20items))))=0A+=0A+=20=20=20=20=20=20;;=20= Split=20,--=20(which=20would=20end=20up=20as=20,-=20otherwise).=0A+=20=20= =20=20=20=20(let=20((dash-r=20(rassq=20?-=20items)))=0A+=20=20=20=20=20=20= =20=20(when=20(eq=20(car=20dash-r)=20?,)=0A+=20=20=20=20=20=20=20=20=20=20= (setcdr=20dash-r=20?,)=0A+=20=20=20=20=20=20=20=20=20=20(setq=20items=20= (nconc=20items=20'((?-=20.=20?-))))))=0A+=0A+=20=20=20=20=20=20;;=20= Remove=20-=20(lone=20or=20at=20start=20of=20interval)=0A+=20=20=20=20=20=20= (let=20((dash-l=20(assq=20?-=20items)))=0A+=20=20=20=20=20=20=20=20(when=20= dash-l=0A+=20=20=20=20=20=20=20=20=20=20(if=20(eq=20(cdr=20dash-l)=20?-)=0A= +=20=20=20=20=20=20=20=20=20=20=20=20=20=20(setq=20items=20(delq=20= dash-l=20items))=20=20=20;=20Remove=20lone=20-=0A+=20=20=20=20=20=20=20=20= =20=20=20=20(setcar=20dash-l=20?.))=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20;=20Reduce=20--x=20to=20.-x=0A+=20=20=20=20=20=20=20=20=20= =20(setq=20items=20(nconc=20items=20'((?-=20.=20?-))))))=0A+=0A+=20=20=20= =20=20=20;;=20Deal=20with=20leading=20^=20and=20range=20^-x.=0A+=20=20=20= =20=20=20(when=20(and=20(consp=20(car=20items))=0A+=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20(eq=20(caar=20items)=20?^)=0A+=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20(cdr=20items))=0A+=20=20=20=20=20=20=20=20= ;;=20Move=20^=20and=20^-x=20to=20second=20place.=0A+=20=20=20=20=20=20=20= =20(setq=20items=20(cons=20(cadr=20items)=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(cons=20(car=20items)=20= (cddr=20items)))))=0A+=0A=20=20=20=20=20=20=20(cond=0A-=20=20=20=20=20=20= =20((<=3D=20l=201))=0A-=20=20=20=20=20=20=20((=3D=20l=202)=20(=3D=20= (aref=20r=200)=20?\\))=0A-=20=20=20=20=20=20=20((=3D=20l=203)=20= (string-match=20"\\`\\(?:\\\\[cCsS_]\\|\\[[^^]\\]\\)"=20r))=0A-=20=20=20=20= =20=20=20((null=20lax)=0A-=20=20=20=20=20=20=20=20(cond=0A-=20=20=20=20=20= =20=20=20=20((string-match=20= "\\`\\[\\^?]?\\(?:\\[:[a-z]+:]\\|[^]]\\)*]\\'"=20r))=0A-=20=20=20=20=20=20= =20=20=20((string-match=20"\\`\\\\(\\(?:[^\\]\\|\\\\[^)]\\)*\\\\)\\'"=20= r))))))))=0A-=0A-=0A-(defun=20rx-syntax=20(form)=0A-=20=20"Parse=20and=20= produce=20code=20from=20FORM,=20which=20is=20`(syntax=20SYMBOL)'."=0A-=20= =20(rx-check=20form)=0A-=20=20(let*=20((sym=20(cadr=20form))=0A-=09=20= (syntax=20(cdr=20(assq=20sym=20rx-syntax))))=0A+=20=20=20=20=20=20=20;;=20= Empty=20set:=20if=20negated,=20any=20char,=20otherwise=20match-nothing.=0A= +=20=20=20=20=20=20=20((null=20items)=0A+=20=20=20=20=20=20=20=20(if=20= negated=0A+=20=20=20=20=20=20=20=20=20=20=20=20(rx--translate-symbol=20= 'anything)=0A+=20=20=20=20=20=20=20=20=20=20(rx--empty)))=0A+=20=20=20=20= =20=20=20;;=20Single=20non-negated=20character.=0A+=20=20=20=20=20=20=20= ((and=20(null=20(cdr=20items))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20= (consp=20(car=20items))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20(eq=20= (caar=20items)=20(cdar=20items))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20= (not=20negated))=0A+=20=20=20=20=20=20=20=20(cons=20(list=20= (regexp-quote=20(char-to-string=20(caar=20items))))=0A+=20=20=20=20=20=20= =20=20=20=20=20=20=20=20t))=0A+=20=20=20=20=20=20=20;;=20At=20least=20= one=20character=20or=20class,=20possibly=20negated.=0A+=20=20=20=20=20=20= =20(t=0A+=20=20=20=20=20=20=20=20(cons=0A+=20=20=20=20=20=20=20=20=20= (list=0A+=20=20=20=20=20=20=20=20=20=20(concat=0A+=20=20=20=20=20=20=20=20= =20=20=20"["=0A+=20=20=20=20=20=20=20=20=20=20=20(and=20negated=20"^")=0A= +=20=20=20=20=20=20=20=20=20=20=20(mapconcat=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(cond=20= ((symbolp=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=20(format=20"[:%s:]"=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((eq=20(car=20item)=20(cdr=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=20= (char-to-string=20(car=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((eq=20(1+=20(car=20= item))=20(cdr=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=20(string=20(car=20item)=20= (cdr=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(t=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(string=20(car=20= item)=20?-=20(cdr=20item)))))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20items=20nil)=0A+=20=20=20=20=20=20=20=20=20=20=20= "]"))=0A+=20=20=20=20=20=20=20=20=20t))))))=0A+=0A+(defun=20= rx--translate-not=20(negated=20body)=0A+=20=20"Translate=20a=20(not=20= ...)=20construct.=20=20Return=20(REGEXP=20.=20PRECEDENCE).=0A+If=20= NEGATED,=20negate=20the=20sense=20(thus=20making=20it=20positive)."=0A+=20= =20(unless=20(and=20body=20(null=20(cdr=20body)))=0A+=20=20=20=20(error=20= "rx=20`not'=20form=20takes=20exactly=20one=20argument"))=0A+=20=20(let=20= ((arg=20(car=20body)))=0A+=20=20=20=20(cond=0A+=20=20=20=20=20((consp=20= arg)=0A+=20=20=20=20=20=20(pcase=20(car=20arg)=0A+=20=20=20=20=20=20=20=20= ((or=20'any=20'in=20'char)=20(rx--translate-any=20=20=20=20=20=20(not=20= negated)=20(cdr=20arg)))=0A+=20=20=20=20=20=20=20=20('syntax=20=20=20=20=20= =20=20=20=20=20=20=20=20(rx--translate-syntax=20=20=20(not=20negated)=20= (cdr=20arg)))=0A+=20=20=20=20=20=20=20=20('category=20=20=20=20=20=20=20=20= =20=20=20(rx--translate-category=20(not=20negated)=20(cdr=20arg)))=0A+=20= =20=20=20=20=20=20=20('not=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (rx--translate-not=20=20=20=20=20=20(not=20negated)=20(cdr=20arg)))=0A+=20= =20=20=20=20=20=20=20(_=20(error=20"Illegal=20argument=20to=20rx=20= `not':=20%S"=20arg))))=0A+=20=20=20=20=20((eq=20arg=20'word-boundary)=0A= +=20=20=20=20=20=20(rx--translate-symbol=0A+=20=20=20=20=20=20=20(if=20= negated=20'word-boundary=20'not-word-boundary)))=0A+=20=20=20=20=20(t=0A= +=20=20=20=20=20=20(let=20((class=20(cdr=20(assq=20arg=20= rx--char-classes))))=0A+=20=20=20=20=20=20=20=20(if=20class=0A+=20=20=20=20= =20=20=20=20=20=20=20=20(rx--translate-any=20(not=20negated)=20(list=20= class))=0A+=20=20=20=20=20=20=20=20=20=20(error=20"Illegal=20argument=20= to=20rx=20`not':=20%s"=20arg)))))))=0A+=0A+(defun=20rx--atomic-regexp=20= (item)=0A+=20=20"ITEM=20is=20(REGEXP=20.=20PRECEDENCE);=20return=20a=20= regexp=20of=20precedence=20t."=0A+=20=20(if=20(eq=20(cdr=20item)=20t)=0A= +=20=20=20=20=20=20(car=20item)=0A+=20=20=20=20(rx--bracket=20(car=20= item))))=0A+=0A+(defun=20rx--translate-counted-repetition=20(min-count=20= max-count=20body)=0A+=20=20(let=20((operand=20(rx--translate-seq=20= body)))=0A+=20=20=20=20(if=20(car=20operand)=0A+=20=20=20=20=20=20=20=20= (cons=20(append=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (rx--atomic-regexp=20operand)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20(list=20(concat=20"\\{"=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(number-to-string=20min-count)=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(cond=20((null=20max-count)=20",")=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= =20=20=20((<=20min-count=20max-count)=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=20=20=20=20= (concat=20","=20(number-to-string=20max-count))))=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= "\\}")))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20t)=0A+=20=20=20=20=20= =20operand)))=0A+=0A+(defun=20rx--check-repeat-arg=20(name=20min-args=20= body)=0A+=20=20(unless=20(>=3D=20(length=20body)=20min-args)=0A+=20=20=20= =20(error=20"rx=20`%s'=20requires=20at=20least=20%d=20argument%s"=0A+=20=20= =20=20=20=20=20=20=20=20=20name=20min-args=20(if=20(=3D=20min-args=201)=20= ""=20"s")))=0A+=20=20;;=20There=20seems=20to=20be=20no=20reason=20to=20= disallow=20zero=20counts.=0A+=20=20(unless=20(natnump=20(car=20body))=0A= +=20=20=20=20(error=20"rx=20`%s'=20first=20argument=20must=20be=20= nonnegative"=20name)))=0A+=0A+(defun=20rx--translate-bounded-repetition=20= (name=20body)=0A+=20=20(let=20((min-count=20(car=20body))=0A+=20=20=20=20= =20=20=20=20(max-count=20(cadr=20body))=0A+=20=20=20=20=20=20=20=20= (items=20(cddr=20body)))=0A+=20=20=20=20(unless=20(and=20(natnump=20= min-count)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (natnump=20max-count)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20(<=3D=20min-count=20max-count))=0A+=20=20=20=20=20=20(error=20"rx=20= `%s'=20range=20error"=20name))=0A+=20=20=20=20= (rx--translate-counted-repetition=20min-count=20max-count=20items)))=0A+=0A= +(defun=20rx--translate-repeat=20(body)=0A+=20=20(rx--check-repeat-arg=20= 'repeat=202=20body)=0A+=20=20(if=20(=3D=20(length=20body)=202)=0A+=20=20=20= =20=20=20(rx--translate-counted-repetition=20(car=20body)=20(car=20body)=20= (cdr=20body))=0A+=20=20=20=20(rx--translate-bounded-repetition=20'repeat=20= body)))=0A+=0A+(defun=20rx--translate-**=20(body)=0A+=20=20= (rx--check-repeat-arg=20'**=202=20body)=0A+=20=20= (rx--translate-bounded-repetition=20'**=20body))=0A+=0A+(defun=20= rx--translate->=3D=20(body)=0A+=20=20(rx--check-repeat-arg=20'>=3D=201=20= body)=0A+=20=20(rx--translate-counted-repetition=20(car=20body)=20nil=20= (cdr=20body)))=0A+=0A+(defun=20rx--translate-=3D=20(body)=0A+=20=20= (rx--check-repeat-arg=20'=3D=201=20body)=0A+=20=20= (rx--translate-counted-repetition=20(car=20body)=20(car=20body)=20(cdr=20= body)))=0A+=0A+(defvar=20rx--greedy=20t)=0A+=0A+(defun=20= rx--translate-rep=20(op-string=20greedy=20body)=0A+=20=20"Translate=20a=20= repetition;=20OP-STRING=20is=20one=20of=20\"*\",=20\"+\"=20or=20\"?\".=0A= +GREEDY=20is=20a=20boolean.=20=20Return=20(REGEXP=20.=20PRECEDENCE)."=0A= +=20=20(let=20((operand=20(rx--translate-seq=20body)))=0A+=20=20=20=20= (if=20(car=20operand)=0A+=20=20=20=20=20=20=20=20(cons=20(append=20= (rx--atomic-regexp=20operand)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20(list=20(concat=20op-string=20(unless=20greedy=20= "?"))))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20;;=20The=20result=20= has=20precedence=20seq=20to=20avoid=20(?=20(*=20"a"))=20->=20"a*?"=0A+=20= =20=20=20=20=20=20=20=20=20=20=20=20=20'seq)=0A+=20=20=20=20=20=20= operand)))=0A+=0A+(defun=20rx--control-greedy=20(greedy=20body)=0A+=20=20= "Translate=20the=20sequence=20BODY=20with=20greediness=20GREEDY.=0A= +Return=20(REGEXP=20.=20PRECEDENCE)."=0A+=20=20(let=20((rx--greedy=20= greedy))=0A+=20=20=20=20(rx--translate-seq=20body)))=0A+=0A+(defun=20= rx--translate-group=20(body)=0A+=20=20"Translate=20the=20`group'=20form.=20= =20Return=20(REGEXP=20.=20PRECEDENCE)."=0A+=20=20(cons=20(rx--enclose=20= "\\("=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (car=20(rx--translate-seq=20body))=0A+=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20"\\)")=0A+=20=20=20=20=20=20=20=20t))=0A+=0A= +(defun=20rx--translate-group-n=20(body)=0A+=20=20"Translate=20the=20= `group-n'=20form.=20=20Return=20(REGEXP=20.=20PRECEDENCE)."=0A+=20=20= (unless=20(and=20(integerp=20(car=20body))=20(>=20(car=20body)=200))=0A+=20= =20=20=20(error=20"rx=20`group-n'=20requires=20a=20positive=20number=20= as=20first=20argument"))=0A+=20=20(cons=20(rx--enclose=20(concat=20= "\\(?"=20(number-to-string=20(car=20body))=20":")=0A+=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20(car=20(rx--translate-seq=20= (cdr=20body)))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20"\\)")=0A+=20=20=20=20=20=20=20=20t))=0A+=0A+(defun=20= rx--translate-backref=20(body)=0A+=20=20"Translate=20the=20`backref'=20= form.=20=20Return=20(REGEXP=20.=20PRECEDENCE)."=0A+=20=20(unless=20(and=20= (=3D=20(length=20body)=201)=20(integerp=20(car=20body))=20(<=3D=201=20= (car=20body)=209))=0A+=20=20=20=20(error=20"rx=20`backref'=20requires=20= an=20argument=20in=20the=20range=201..9"))=0A+=20=20(cons=20(list=20"\\"=20= (number-to-string=20(car=20body)))=20t))=0A+=0A+(defconst=20= rx--syntax-codes=0A+=20=20'((whitespace=20=20=20=20=20=20=20=20=20.=20= ?-)=20=20=20=20=20=20=20=20=20=20=20;=20SPC=20also=20accepted=0A+=20=20=20= =20(punctuation=20=20=20=20=20=20=20=20.=20?.)=0A+=20=20=20=20(word=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20.=20?w)=20=20=20=20=20=20=20=20=20= =20=20;=20W=20also=20accepted=0A+=20=20=20=20(symbol=20=20=20=20=20=20=20= =20=20=20=20=20=20.=20?_)=0A+=20=20=20=20(open-parenthesis=20=20=20.=20= ?\()=0A+=20=20=20=20(close-parenthesis=20=20.=20?\))=0A+=20=20=20=20= (expression-prefix=20=20.=20?\')=0A+=20=20=20=20(string-quote=20=20=20=20= =20=20=20.=20?\")=0A+=20=20=20=20(paired-delimiter=20=20=20.=20?$)=0A+=20= =20=20=20(escape=20=20=20=20=20=20=20=20=20=20=20=20=20.=20?\\)=0A+=20=20= =20=20(character-quote=20=20=20=20.=20?/)=0A+=20=20=20=20(comment-start=20= =20=20=20=20=20.=20?<)=0A+=20=20=20=20(comment-end=20=20=20=20=20=20=20=20= .=20?>)=0A+=20=20=20=20(string-delimiter=20=20=20.=20?|)=0A+=20=20=20=20= (comment-delimiter=20=20.=20?!)))=0A+=0A+(defun=20rx--translate-syntax=20= (negated=20body)=0A+=20=20"Translate=20the=20`syntax'=20form.=20=20= Return=20(REGEXP=20.=20PRECEDENCE)."=0A+=20=20(unless=20(and=20body=20= (null=20(cdr=20body)))=0A+=20=20=20=20(error=20"rx=20`syntax'=20form=20= takes=20exactly=20one=20argument"))=0A+=20=20(let*=20((sym=20(car=20= body))=0A+=20=20=20=20=20=20=20=20=20(syntax=20(cdr=20(assq=20sym=20= rx--syntax-codes))))=0A=20=20=20=20=20(unless=20syntax=0A-=20=20=20=20=20= =20;;=20Try=20sregex=20compatibility.=0A=20=20=20=20=20=20=20(cond=0A-=20= =20=20=20=20=20=20((characterp=20sym)=20(setq=20syntax=20sym))=0A+=20=20=20= =20=20=20=20;;=20Syntax=20character=20directly=20(sregex=20= compatibility)=0A+=20=20=20=20=20=20=20((and=20(characterp=20sym)=20= (rassq=20sym=20rx--syntax-codes))=0A+=20=20=20=20=20=20=20=20(setq=20= syntax=20sym))=0A+=20=20=20=20=20=20=20;;=20Syntax=20character=20as=20= symbol=20(sregex=20compatibility)=0A=20=20=20=20=20=20=20=20((symbolp=20= sym)=0A=20=20=20=20=20=20=20=20=20(let=20((name=20(symbol-name=20sym)))=0A= -=20=20=20=20=20=20=20=20=20=20(if=20(=3D=201=20(length=20name))=0A-=20=20= =20=20=20=20=20=20=20=20=20=20=20=20(setq=20syntax=20(aref=20name=20= 0))))))=0A+=20=20=20=20=20=20=20=20=20=20(when=20(=3D=20(length=20name)=20= 1)=0A+=20=20=20=20=20=20=20=20=20=20=20=20(let=20((char=20= (string-to-char=20name)))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (when=20(rassq=20char=20rx--syntax-codes)=0A+=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20(setq=20syntax=20char)))))))=0A=20=20=20=20=20=20=20= (unless=20syntax=0A-=09(error=20"Unknown=20rx=20syntax=20`%s'"=20sym)))=0A= -=20=20=20=20(format=20"\\s%c"=20syntax)))=0A-=0A-=0A-(defun=20= rx-check-category=20(form)=0A-=20=20"Check=20the=20argument=20FORM=20of=20= a=20`(category=20FORM)'."=0A-=20=20(unless=20(or=20(integerp=20form)=0A-=09= =20=20=20=20=20=20(cdr=20(assq=20form=20rx-categories)))=0A-=20=20=20=20= (error=20"Unknown=20category=20`%s'"=20form))=0A-=20=20t)=0A-=0A-=0A= -(defun=20rx-category=20(form)=0A-=20=20"Parse=20and=20produce=20code=20= from=20FORM,=20which=20is=20`(category=20SYMBOL)'."=0A-=20=20(rx-check=20= form)=0A-=20=20(let=20((char=20(if=20(integerp=20(cadr=20form))=0A-=09=09= =20=20(cadr=20form)=0A-=09=09(cdr=20(assq=20(cadr=20form)=20= rx-categories)))))=0A-=20=20=20=20(format=20"\\c%c"=20char)))=0A-=0A-=0A= -(defun=20rx-eval=20(form)=0A-=20=20"Parse=20and=20produce=20code=20from=20= FORM,=20which=20is=20`(eval=20FORM)'."=0A-=20=20(rx-check=20form)=0A-=20=20= (rx-form=20(eval=20(cadr=20form))=20rx-parent))=0A-=0A-=0A-(defun=20= rx-greedy=20(form)=0A-=20=20"Parse=20and=20produce=20code=20from=20FORM.=0A= -If=20FORM=20is=20`(minimal-match=20FORM1)',=20non-greedy=20versions=20= of=20`*',=0A-`+',=20and=20`?'=20operators=20will=20be=20used=20in=20= FORM1.=20=20If=20FORM=20is=0A-`(maximal-match=20FORM1)',=20greedy=20= operators=20will=20be=20used."=0A-=20=20(rx-check=20form)=0A-=20=20(let=20= ((rx-greedy-flag=20(eq=20(car=20form)=20'maximal-match)))=0A-=20=20=20=20= (rx-form=20(cadr=20form)=20rx-parent)))=0A-=0A-=0A-(defun=20rx-regexp=20= (form)=0A-=20=20"Parse=20and=20produce=20code=20from=20FORM,=20which=20= is=20`(regexp=20STRING)'."=0A-=20=20(cond=20((stringp=20(cadr=20form))=0A= -=20=20=20=20=20=20=20=20=20(rx-group-if=20(cadr=20form)=20rx-parent))=0A= -=20=20=20=20=20=20=20=20(rx--compile-to-lisp=0A-=20=20=20=20=20=20=20=20= =20;;=20Always=20group=20non-string=20forms,=20since=20we=20can't=20be=20= sure=20they=0A-=20=20=20=20=20=20=20=20=20;;=20are=20atomic.=0A-=20=20=20= =20=20=20=20=20=20(rx-group-if=20(cdr=20form)=20t))=0A-=20=20=20=20=20=20= =20=20(t=20(rx-check=20form))))=0A-=0A-(defun=20rx-literal=20(form)=0A-=20= =20"Parse=20and=20produce=20code=20from=20FORM,=20which=20is=20`(literal=20= STRING-EXP)'."=0A-=20=20(cond=20((stringp=20(cadr=20form))=0A-=20=20=20=20= =20=20=20=20=20;;=20This=20is=20allowed,=20but=20makes=20little=20sense,=20= you=20could=20just=0A-=20=20=20=20=20=20=20=20=20;;=20use=20STRING=20= directly.=0A-=20=20=20=20=20=20=20=20=20(rx-group-if=20(regexp-quote=20= (cadr=20form))=20rx-parent))=0A-=20=20=20=20=20=20=20=20= (rx--compile-to-lisp=0A-=20=20=20=20=20=20=20=20=20(rx-group-if=20= `((regexp-quote=20,(cadr=20form)))=20rx-parent))=0A-=20=20=20=20=20=20=20= =20(t=20(rx-check=20form))))=0A-=0A-(defun=20rx-form=20(form=20&optional=20= parent)=0A-=20=20"Parse=20and=20produce=20code=20for=20regular=20= expression=20FORM.=0A-FORM=20is=20a=20regular=20expression=20in=20sexp=20= form.=0A-PARENT=20shows=20which=20type=20of=20expression=20calls=20and=20= controls=20putting=20of=0A-shy=20groups=20around=20the=20result=20and=20= some=20more=20in=20other=20functions."=0A-=20=20(let=20((rx-parent=20= parent))=0A-=20=20=20=20(cond=0A-=20=20=20=20=20((stringp=20form)=0A-=20=20= =20=20=20=20(rx-group-if=20(regexp-quote=20form)=0A-=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20(if=20(and=20(eq=20parent=20'*)=20(<=20= 1=20(length=20form)))=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20parent)))=0A-=20=20=20=20=20((integerp=20form)=0A-=20= =20=20=20=20=20(regexp-quote=20(char-to-string=20form)))=0A-=20=20=20=20=20= ((symbolp=20form)=0A-=20=20=20=20=20=20(let=20((info=20(rx-info=20form=20= nil)))=0A-=20=20=20=20=20=20=20=20(cond=20((stringp=20info)=0A-=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20info)=0A-=20=20=20=20=20=20=20=20=20=20=20= =20=20=20((null=20info)=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (error=20"Unknown=20rx=20form=20`%s'"=20form))=0A-=20=20=20=20=20=20=20=20= =20=20=20=20=20=20(t=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (funcall=20(nth=200=20info)=20form)))))=0A-=20=20=20=20=20((consp=20= form)=0A-=20=20=20=20=20=20(let=20((info=20(rx-info=20(car=20form)=20= 'head)))=0A-=20=20=20=20=20=20=20=20(unless=20(consp=20info)=0A-=20=20=20= =20=20=20=20=20=20=20(error=20"Unknown=20rx=20form=20`%s'"=20(car=20= form)))=0A-=20=20=20=20=20=20=20=20(funcall=20(nth=200=20info)=20form)))=0A= -=20=20=20=20=20(t=0A-=20=20=20=20=20=20(error=20"rx=20syntax=20error=20= at=20`%s'"=20form)))))=0A-=0A-(defun=20rx--subforms=20(subforms=20= &optional=20parent=20separator)=0A-=20=20"Produce=20code=20for=20regular=20= expressions=20SUBFORMS.=0A-SUBFORMS=20is=20a=20list=20of=20regular=20= expression=20sexps.=0A-PARENT=20controls=20grouping,=20as=20in=20= `rx-form'.=0A-Insert=20SEPARATOR=20between=20the=20code=20from=20each=20= of=20SUBFORMS."=0A-=20=20(if=20(null=20(cdr=20subforms))=0A-=20=20=20=20=20= =20;;=20Zero=20or=20one=20forms,=20no=20need=20for=20grouping.=0A-=20=20=20= =20=20=20(and=20subforms=20(rx-form=20(car=20subforms)))=0A-=20=20=20=20= (let=20((listify=20(lambda=20(x)=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20(if=20(listp=20x)=20(copy-sequence=20x)=0A-=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(list=20= x)))))=0A-=20=20=20=20=20=20(setq=20subforms=20(mapcar=20(lambda=20(x)=20= (rx-form=20x=20parent))=20subforms))=0A-=20=20=20=20=20=20(cond=20((or=20= (not=20rx--compile-to-lisp)=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20(cl-every=20#'stringp=20subforms))=0A-=20=20=20=20=20=20=20=20=20= =20=20=20=20(mapconcat=20#'identity=20subforms=20separator))=0A-=20=20=20= =20=20=20=20=20=20=20=20=20(separator=0A-=20=20=20=20=20=20=20=20=20=20=20= =20=20(nconc=20(funcall=20listify=20(car=20subforms))=0A-=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20(mapcan=20(lambda=20(x)=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(cons=20separator=20(funcall=20listify=20x)))=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= (cdr=20subforms))))=0A-=20=20=20=20=20=20=20=20=20=20=20=20(t=20(mapcan=20= listify=20subforms))))))=0A+=20=20=20=20=20=20=20=20(error=20"Unknown=20= rx=20syntax=20name=20`%s'"=20sym)))=0A+=20=20=20=20(cons=20(list=20= (string=20?\\=20(if=20negated=20?S=20?s)=20syntax))=0A+=20=20=20=20=20=20= =20=20=20=20t)))=0A+=0A+(defconst=20rx--categories=0A+=20=20= '((space-for-indent=20=20=20=20=20=20=20=20=20=20=20.=20?\s)=0A+=20=20=20= =20(base=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20.=20?.)=0A+=20=20=20=20(consonant=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20.=20?0)=0A+=20=20=20=20(base-vowel=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20.=20?1)=0A+=20=20=20=20= (upper-diacritical-mark=20=20=20=20=20.=20?2)=0A+=20=20=20=20= (lower-diacritical-mark=20=20=20=20=20.=20?3)=0A+=20=20=20=20(tone-mark=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20.=20?4)=0A+=20=20=20=20= (symbol=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20.=20= ?5)=0A+=20=20=20=20(digit=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20.=20?6)=0A+=20=20=20=20= (vowel-modifying-diacritical-mark=20.=20?7)=0A+=20=20=20=20(vowel-sign=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20.=20?8)=0A+=20=20=20=20= (semivowel-lower=20=20=20=20=20=20=20=20=20=20=20=20.=20?9)=0A+=20=20=20=20= (not-at-end-of-line=20=20=20=20=20=20=20=20=20.=20?<)=0A+=20=20=20=20= (not-at-beginning-of-line=20=20=20.=20?>)=0A+=20=20=20=20= (alpha-numeric-two-byte=20=20=20=20=20.=20?A)=0A+=20=20=20=20= (chinese-two-byte=20=20=20=20=20=20=20=20=20=20=20.=20?C)=0A+=20=20=20=20= (chinse-two-byte=20=20=20=20=20=20=20=20=20=20=20=20.=20?C)=20=20=20;=20= A=20typo=20in=20Emacs=2021.1-24.3.=0A+=20=20=20=20(greek-two-byte=20=20=20= =20=20=20=20=20=20=20=20=20=20.=20?G)=0A+=20=20=20=20= (japanese-hiragana-two-byte=20.=20?H)=0A+=20=20=20=20(indian-two-byte=20=20= =20=20=20=20=20=20=20=20=20=20.=20?I)=0A+=20=20=20=20= (japanese-katakana-two-byte=20.=20?K)=0A+=20=20=20=20= (strong-left-to-right=20=20=20=20=20=20=20.=20?L)=0A+=20=20=20=20= (korean-hangul-two-byte=20=20=20=20=20.=20?N)=0A+=20=20=20=20= (strong-right-to-left=20=20=20=20=20=20=20.=20?R)=0A+=20=20=20=20= (cyrillic-two-byte=20=20=20=20=20=20=20=20=20=20.=20?Y)=0A+=20=20=20=20= (combining-diacritic=20=20=20=20=20=20=20=20.=20?^)=0A+=20=20=20=20= (ascii=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= .=20?a)=0A+=20=20=20=20(arabic=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20.=20?b)=0A+=20=20=20=20(chinese=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20.=20?c)=0A+=20=20=20=20(ethiopic=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20.=20?e)=0A+=20=20=20=20= (greek=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= .=20?g)=0A+=20=20=20=20(korean=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20.=20?h)=0A+=20=20=20=20(indian=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20.=20?i)=0A+=20=20=20=20(japanese=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20.=20?j)=0A+=20=20=20=20= (japanese-katakana=20=20=20=20=20=20=20=20=20=20.=20?k)=0A+=20=20=20=20= (latin=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= .=20?l)=0A+=20=20=20=20(lao=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?o)=0A+=20=20=20=20(tibetan=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20.=20?q)=0A+=20=20=20=20= (japanese-roman=20=20=20=20=20=20=20=20=20=20=20=20=20.=20?r)=0A+=20=20=20= =20(thai=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20.=20?t)=0A+=20=20=20=20(vietnamese=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20.=20?v)=0A+=20=20=20=20(hebrew=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20.=20?w)=0A+=20=20=20=20(cyrillic=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20.=20?y)=0A+=20=20=20=20= (can-break=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20.=20= ?|)))=0A+=0A+(defun=20rx--translate-category=20(negated=20body)=0A+=20=20= "Translate=20the=20`category'=20form.=20=20Return=20(REGEXP=20.=20= PRECEDENCE)."=0A+=20=20(unless=20(and=20body=20(null=20(cdr=20body)))=0A= +=20=20=20=20(error=20"rx=20`category'=20form=20takes=20exactly=20one=20= argument"))=0A+=20=20(let*=20((arg=20(car=20body))=0A+=20=20=20=20=20=20=20= =20=20(category=0A+=20=20=20=20=20=20=20=20=20=20(cond=20((symbolp=20= arg)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(let=20((cat=20= (assq=20arg=20rx--categories)))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20(unless=20cat=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20(error=20"Unknown=20rx=20category=20`%s'"=20= arg))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(cdr=20= cat)))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20((characterp=20= arg)=20arg)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(t=20= (error=20"Invalid=20rx=20`category'=20argument=20`%s'"=20arg)))))=0A+=20=20= =20=20(cons=20(list=20(string=20?\\=20(if=20negated=20?C=20?c)=20= category))=0A+=20=20=20=20=20=20=20=20=20=20t)))=0A+=0A+(defvar=20= rx--delayed-evaluation=20nil=0A+=20=20"Whether=20to=20allow=20certain=20= forms=20to=20be=20evaluated=20at=20runtime.")=0A+=0A+(defun=20= rx--translate-literal=20(body)=0A+=20=20"Translate=20the=20`literal'=20= form.=20=20Return=20(REGEXP=20.=20PRECEDENCE)."=0A+=20=20(unless=20(and=20= body=20(null=20(cdr=20body)))=0A+=20=20=20=20(error=20"rx=20`literal'=20= form=20takes=20exactly=20one=20argument"))=0A+=20=20(let=20((arg=20(car=20= body)))=0A+=20=20=20=20(cond=20((stringp=20arg)=0A+=20=20=20=20=20=20=20=20= =20=20=20(cons=20(list=20(regexp-quote=20arg))=20(if=20(=3D=20(length=20= arg)=201)=20t=20'seq)))=0A+=20=20=20=20=20=20=20=20=20=20= (rx--delayed-evaluation=0A+=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(t=20(error=20"rx=20`literal'=20form=20with=20non-string=20= argument")))))=0A+=0A+(defun=20rx--translate-eval=20(body)=0A+=20=20= "Translate=20the=20`eval'=20form.=20=20Return=20(REGEXP=20.=20= PRECEDENCE)."=0A+=20=20(unless=20(and=20body=20(null=20(cdr=20body)))=0A= +=20=20=20=20(error=20"rx=20`eval'=20form=20takes=20exactly=20one=20= argument"))=0A+=20=20(rx--translate=20(eval=20(car=20body))))=0A+=0A= +(defvar=20rx--regexp-atomic-regexp=20nil)=0A+=0A+(defun=20= rx--translate-regexp=20(body)=0A+=20=20"Translate=20the=20`regexp'=20= form.=20=20Return=20(REGEXP=20.=20PRECEDENCE)."=0A+=20=20(unless=20(and=20= body=20(null=20(cdr=20body)))=0A+=20=20=20=20(error=20"rx=20`regexp'=20= form=20takes=20exactly=20one=20argument"))=0A+=20=20(let=20((arg=20(car=20= body)))=0A+=20=20=20=20(cond=20((stringp=20arg)=0A+=20=20=20=20=20=20=20=20= =20=20=20;;=20Generate=20the=20regexp=20when=20needed,=20since=20rx=20= isn't=0A+=20=20=20=20=20=20=20=20=20=20=20;;=20necessarily=20present=20= in=20the=20byte-compilation=20environment.=0A+=20=20=20=20=20=20=20=20=20= =20=20(unless=20rx--regexp-atomic-regexp=0A+=20=20=20=20=20=20=20=20=20=20= =20=20=20(setq=20rx--regexp-atomic-regexp=0A+=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20;;=20Match=20atomic=20(precedence=20t)=20= regexps:=20may=20give=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20;;=20false=20negatives=20but=20no=20false=20positives,=20= assuming=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20;;=20= the=20target=20string=20is=20syntactically=20correct.=0A+=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20(rx-to-string=0A+=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20'(seq=0A+=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20bos=0A+=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20(or=20(seq=20"["=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(opt=20"^")=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(opt=20"]")=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(or=20(seq=20"[:"=20(+=20(any=20"a-z"))=20":]")=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=20=20=20=20=20=20(not=20(any=20"]"))))=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"]")=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=20anything=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(seq=20"\\"=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(or=20anything=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=20=20=20(seq=20(any=20"sScC_")=20anything)=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=20=20=20(seq=20"("=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=20=20=20=20=20=20= =20=20(*=20(or=20(not=20(any=20"\\"))=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=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20(seq=20"\\"=20(not=20(any=20")")))))=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=20=20=20=20=20=20=20=20"\\)"))))=0A+=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20eos)=0A+=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20t)))=0A+=20=20=20=20=20=20= =20=20=20=20=20(cons=20(list=20arg)=0A+=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20(if=20(string-match-p=20rx--regexp-atomic-regexp=20arg)=20= t=20nil)))=0A+=20=20=20=20=20=20=20=20=20=20(rx--delayed-evaluation=0A+=20= =20=20=20=20=20=20=20=20=20=20(cons=20(list=20arg)=20nil))=0A+=20=20=20=20= =20=20=20=20=20=20(t=20(error=20"rx=20`regexp'=20form=20with=20= non-string=20argument")))))=0A+=0A+(defun=20rx--translate-compat-form=20= (def=20form)=0A+=20=20"Translate=20a=20compatibility=20form=20from=20= `rx-constituents'.=0A+DEF=20is=20the=20definition=20tuple.=20=20Return=20= (REGEXP=20.=20PRECEDENCE)."=0A+=20=20(let*=20((fn=20(nth=200=20def))=0A+=20= =20=20=20=20=20=20=20=20(min-args=20(nth=201=20def))=0A+=20=20=20=20=20=20= =20=20=20(max-args=20(nth=202=20def))=0A+=20=20=20=20=20=20=20=20=20= (predicate=20(nth=203=20def))=0A+=20=20=20=20=20=20=20=20=20(nargs=20(1-=20= (length=20form))))=0A+=20=20=20=20(when=20(<=20nargs=20min-args)=0A+=20=20= =20=20=20=20(error=20"The=20`%s'=20form=20takes=20at=20least=20%d=20= argument(s)"=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20(car=20form)=20= min-args))=0A+=20=20=20=20(when=20(and=20max-args=20(>=20nargs=20= max-args))=0A+=20=20=20=20=20=20(error=20"The=20`%s'=20form=20takes=20at=20= most=20%d=20argument(s)"=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20(car=20= form)=20max-args))=0A+=20=20=20=20(when=20(and=20predicate=20(not=20= (rx--every=20predicate=20(cdr=20form))))=0A+=20=20=20=20=20=20(error=20= "The=20`%s'=20form=20requires=20arguments=20satisfying=20`%s'"=0A+=20=20=20= =20=20=20=20=20=20=20=20=20=20(car=20form)=20predicate))=0A+=20=20=20=20= (let=20((regexp=20(funcall=20fn=20form)))=0A+=20=20=20=20=20=20(unless=20= (stringp=20regexp)=0A+=20=20=20=20=20=20=20=20(error=20"The=20`%s'=20= form=20did=20not=20expand=20to=20a=20string"=20(car=20form)))=0A+=20=20=20= =20=20=20(cons=20(list=20regexp)=20nil))))=0A+=0A+(defun=20= rx--substitute=20(bindings=20form)=0A+=20=20"Substitute=20BINDINGS=20in=20= FORM."=0A+=20=20(cond=20((symbolp=20form)=0A+=20=20=20=20=20=20=20=20=20= (let=20((binding=20(assq=20form=20bindings)))=0A+=20=20=20=20=20=20=20=20= =20=20=20(if=20binding=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (cdr=20binding)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20form)))=0A+=20=20= =20=20=20=20=20=20((consp=20form)=0A+=20=20=20=20=20=20=20=20=20(if=20= (listp=20(cdr=20form))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20;;=20= Proper=20list.=20=20We=20substitute=20variables=20even=20in=20the=20head=0A= +=20=20=20=20=20=20=20=20=20=20=20=20=20;;=20position=20--=20who=20= knows,=20might=20be=20handy=20one=20day.=0A+=20=20=20=20=20=20=20=20=20=20= =20=20=20(mapcar=20(lambda=20(x)=20(rx--substitute=20bindings=20x))=20= form)=0A+=20=20=20=20=20=20=20=20=20=20=20;;=20Cons=20pair=20(presumably=20= an=20interval).=0A+=20=20=20=20=20=20=20=20=20=20=20(cons=20= (rx--substitute=20bindings=20(car=20form))=0A+=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20(rx--substitute=20bindings=20(cdr=20form)))))=0A= +=20=20=20=20=20=20=20=20(t=20form)))=0A+=0A+;;=20FIXME:=20Consider=20= adding=20extensions=20in=20Lisp=20macro=20style,=20where=0A+;;=20= arguments=20are=20passed=20unevaluated=20to=20code=20that=20returns=20= the=20rx=20form=0A+;;=20to=20use.=20=20Example:=0A+;;=0A+;;=20=20=20= (rx-let=20((radix-digit=20(radix)=0A+;;=20=20=20=20=20=20=20=20=20=20=20=20= =20:lisp=20(list=20'any=20(cons=20?0=20(+=20?0=20(eval=20radix)=20= -1)))))=0A+;;=20=20=20=20=20(rx=20(radix-digit=20(+=205=203))))=0A+;;=20= =3D>=0A+;;=20=20=20"[0-7]"=0A+;;=0A+;;=20While=20this=20would=20permit=20= more=20powerful=20extensions,=20it's=20unclear=20just=0A+;;=20how=20= often=20they=20would=20be=20used=20in=20practice.=20=20Let's=20wait=20= until=20there=20is=0A+;;=20demand=20for=20it.=0A+=0A+;;=20FIXME:=20An=20= alternative=20binding=20syntax=20would=20be=0A+;;=0A+;;=20=20=20(NAME=20= RXs...)=0A+;;=20and=0A+;;=20=20=20((NAME=20ARGS...)=20RXs...)=0A+;;=0A= +;;=20which=20would=20have=20two=20minor=20advantages:=20multiple=20RXs=20= with=20implicit=0A+;;=20`seq'=20in=20the=20definition,=20and=20the=20= arglist=20is=20no=20longer=20an=20optional=0A+;;=20element=20in=20the=20= middle=20of=20the=20list.=20=20On=20the=20other=20hand,=20it's=20less=0A= +;;=20like=20traditional=20lisp=20arglist=20constructs=20(defun,=20= defmacro).=0A+;;=20Since=20it's=20a=20Scheme-like=20syntax,=20&rest=20= parameters=20could=20be=20done=20using=0A+;;=20dotted=20lists:=0A+;;=20=20= (rx-let=20(((name=20arg1=20arg2=20.=20rest)=20...definition...))=20...)=0A= +=0A+;;=20FIXME:=20We=20currently=20bind=20&rest=20parameters=20to=20= (seq=20...),=0A+;;=20but=20it=20would=20probably=20be=20better=20to=20= make=20them=20auto-splicing=0A+;;=20so=20that=20they=20are=20not=20= forced=20to=20be=20a=20sequence.=20=20For=20example:=0A+;;=20(rx-let=20= ((colour=20(&rest=20choices)=20(or=20"black"=20choices)))=0A+;;=20=20=20= (rx=20(colour=20"brown"=20"beige")))=0A+=0A+(defun=20rx--expand-template=20= (op=20values=20arglist=20template)=0A+=20=20"Return=20TEMPLATE=20with=20= variables=20in=20ARGLIST=20replaced=20with=20VALUES."=0A+=20=20(let=20= ((bindings=20nil)=0A+=20=20=20=20=20=20=20=20(value-tail=20values)=0A+=20= =20=20=20=20=20=20=20(formals=20arglist))=0A+=20=20=20=20(while=20= formals=0A+=20=20=20=20=20=20(pcase=20(car=20formals)=0A+=20=20=20=20=20=20= =20=20('&rest=0A+=20=20=20=20=20=20=20=20=20(unless=20(cdr=20formals)=0A= +=20=20=20=20=20=20=20=20=20=20=20(error=0A+=20=20=20=20=20=20=20=20=20=20= =20=20"Expanding=20rx=20def=20`%s':=20missing=20&rest=20parameter=20= name"=20op))=0A+=20=20=20=20=20=20=20=20=20(push=20(cons=20(cadr=20= formals)=20(cons=20'seq=20value-tail))=20bindings)=0A+=20=20=20=20=20=20=20= =20=20(setq=20formals=20nil)=0A+=20=20=20=20=20=20=20=20=20(setq=20= value-tail=20nil))=0A+=20=20=20=20=20=20=20=20(name=0A+=20=20=20=20=20=20= =20=20=20(unless=20value-tail=0A+=20=20=20=20=20=20=20=20=20=20=20(error=0A= +=20=20=20=20=20=20=20=20=20=20=20=20"Expanding=20rx=20def=20`%s':=20too=20= few=20arguments=20(got=20%d,=20need=20%s%d)"=0A+=20=20=20=20=20=20=20=20=20= =20=20=20op=20(length=20values)=0A+=20=20=20=20=20=20=20=20=20=20=20=20= (if=20(memq=20'&rest=20arglist)=20"at=20least=20"=20"")=0A+=20=20=20=20=20= =20=20=20=20=20=20=20(-=20(length=20arglist)=20(length=20(memq=20'&rest=20= arglist)))))=0A+=20=20=20=20=20=20=20=20=20(push=20(cons=20name=20(car=20= value-tail))=20bindings)=0A+=20=20=20=20=20=20=20=20=20(setq=20= value-tail=20(cdr=20value-tail))))=0A+=20=20=20=20=20=20(setq=20formals=20= (cdr=20formals)))=0A+=20=20=20=20(when=20value-tail=0A+=20=20=20=20=20=20= (error=0A+=20=20=20=20=20=20=20"Expanding=20rx=20def=20`%s':=20too=20= many=20arguments=20(got=20%d,=20need=20%d)"=0A+=20=20=20=20=20=20=20op=20= (length=20values)=20(length=20arglist)))=0A+=20=20=20=20(rx--substitute=20= bindings=20template)))=0A+=0A+(defun=20rx--translate-form=20(form)=0A+=20= =20"Translate=20an=20rx=20form=20(list=20structure).=20=20Return=20= (REGEXP=20.=20PRECEDENCE)."=0A+=20=20(let=20((body=20(cdr=20form)))=0A+=20= =20=20=20(pcase=20(car=20form)=0A+=20=20=20=20=20=20((or=20'seq=20:=20= 'and=20'sequence)=20(rx--translate-seq=20body))=0A+=20=20=20=20=20=20= ((or=20'or=20'|)=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (rx--translate-or=20body))=0A+=20=20=20=20=20=20((or=20'any=20'in=20= 'char)=20=20=20=20=20=20(rx--translate-any=20nil=20body))=0A+=20=20=20=20= =20=20('not-char=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (rx--translate-any=20t=20body))=0A+=20=20=20=20=20=20('not=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(rx--translate-not=20nil=20= body))=0A+=0A+=20=20=20=20=20=20('repeat=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20(rx--translate-repeat=20body))=0A+=20=20=20=20=20=20= ('=3D=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (rx--translate-=3D=20body))=0A+=20=20=20=20=20=20('>=3D=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(rx--translate->=3D=20= body))=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(rx--translate-**=20body))=0A+=0A+=20=20=20=20=20= =20((or=20'zero-or-more=20'0+)=20=20=20=20=20=20=20=20=20=20=20= (rx--translate-rep=20"*"=20rx--greedy=20body))=0A+=20=20=20=20=20=20((or=20= 'one-or-more=20'1+)=20=20=20=20=20=20=20=20=20=20=20=20= (rx--translate-rep=20"+"=20rx--greedy=20body))=0A+=20=20=20=20=20=20((or=20= 'zero-or-one=20'opt=20'optional)=20(rx--translate-rep=20"?"=20rx--greedy=20= body))=0A+=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(rx--translate-rep=20"*"=20t=20body))=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(rx--translate-rep=20"+"=20t=20body))=0A+=20=20=20=20=20=20= ((or=20'\?=20?\s)=20=20=20=20=20=20=20=20=20=20=20=20=20= (rx--translate-rep=20"?"=20t=20body))=0A+=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= (rx--translate-rep=20"*"=20nil=20body))=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= (rx--translate-rep=20"+"=20nil=20body))=0A+=20=20=20=20=20=20((or=20'\??=20= ??)=20=20=20=20=20=20=20=20=20=20=20=20=20(rx--translate-rep=20"?"=20nil=20= body))=0A+=0A+=20=20=20=20=20=20('minimal-match=20=20=20=20=20=20=20=20=20= =20=20(rx--control-greedy=20nil=20body))=0A+=20=20=20=20=20=20= ('maximal-match=20=20=20=20=20=20=20=20=20=20=20(rx--control-greedy=20t=20= =20=20body))=0A+=0A+=20=20=20=20=20=20((or=20'group=20'submatch)=20=20=20= =20=20(rx--translate-group=20body))=0A+=20=20=20=20=20=20((or=20'group-n=20= 'submatch-n)=20(rx--translate-group-n=20body))=0A+=20=20=20=20=20=20= ('backref=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (rx--translate-backref=20body))=0A+=0A+=20=20=20=20=20=20('syntax=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(rx--translate-syntax=20nil=20= body))=0A+=20=20=20=20=20=20('not-syntax=20=20=20=20=20=20=20=20=20=20=20= =20=20=20(rx--translate-syntax=20t=20body))=0A+=20=20=20=20=20=20= ('category=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (rx--translate-category=20nil=20body))=0A+=0A+=20=20=20=20=20=20= ('literal=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (rx--translate-literal=20body))=0A+=20=20=20=20=20=20('eval=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(rx--translate-eval=20= body))=0A+=20=20=20=20=20=20((or=20'regexp=20'regex)=20=20=20=20=20=20= (rx--translate-regexp=20body))=0A+=0A+=20=20=20=20=20=20(op=0A+=20=20=20=20= =20=20=20(let=20((definition=20(rx--lookup-def=20op)))=0A+=20=20=20=20=20= =20=20=20=20(if=20definition=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20= (if=20(cddr=20definition)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20(rx--translate=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20(rx--expand-template=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20op=20body=20(nth=201=20definition)=20(nth=202=20definition)))=0A= +=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(error=20"Not=20an=20`rx'=20= form=20definition:=20%s"=20op))=0A+=0A+=20=20=20=20=20=20=20=20=20=20=20= ;;=20For=20compatibility=20with=20old=20rx.=0A+=20=20=20=20=20=20=20=20=20= =20=20(let=20((entry=20(assq=20op=20rx-constituents)))=0A+=20=20=20=20=20= =20=20=20=20=20=20=20=20(if=20(progn=0A+=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20(while=20(and=20entry=20(not=20(consp=20(cdr=20= entry))))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20(setq=20entry=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(if=20(symbolp=20(cdr=20entry))=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;;=20Alias=20for=20another=20entry.=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(assq=20= (cdr=20entry)=20rx-constituents)=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;;=20Wrong=20type,=20try=20= further=20down=20the=20list.=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(assq=20(car=20entry)=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=20=20=20(cdr=20(memq=20entry=20rx-constituents))))))=0A= +=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20entry)=0A+=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(rx--translate-compat-form=20= (cdr=20entry)=20form)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (error=20"Unknown=20rx=20form=20`%s'"=20op)))))))))=0A+=0A+=0A+(defun=20= rx--translate=20(item)=0A+=20=20"Translate=20the=20rx-expression=20ITEM.=20= =20Return=20(REGEXP=20.=20PRECEDENCE)."=0A+=20=20(cond=0A+=20=20=20= ((stringp=20item)=0A+=20=20=20=20(if=20(=3D=20(length=20item)=200)=0A+=20= =20=20=20=20=20=20=20(cons=20nil=20'seq)=0A+=20=20=20=20=20=20(cons=20= (list=20(regexp-quote=20item))=20(if=20(=3D=20(length=20item)=201)=20t=20= 'seq))))=0A+=20=20=20((characterp=20item)=0A+=20=20=20=20(cons=20(list=20= (regexp-quote=20(char-to-string=20item)))=20t))=0A+=20=20=20((symbolp=20= item)=0A+=20=20=20=20(rx--translate-symbol=20item))=0A+=20=20=20((consp=20= item)=0A+=20=20=20=20(rx--translate-form=20item))=0A+=20=20=20(t=20= (error=20"Bad=20rx=20expression:=20%S"=20item))))=0A=20=0A=20=0A=20= ;;;###autoload=0A=20(defun=20rx-to-string=20(form=20&optional=20= no-group)=0A-=20=20"Parse=20and=20produce=20code=20for=20regular=20= expression=20FORM.=0A-FORM=20is=20a=20regular=20expression=20in=20sexp=20= form.=0A-NO-GROUP=20non-nil=20means=20don't=20put=20shy=20groups=20= around=20the=20result.=0A-=0A-In=20contrast=20to=20the=20`rx'=20macro,=20= subforms=20`literal'=20and=20`regexp'=0A-will=20not=20accept=20= non-string=20arguments,=20i.e.,=20(literal=20STRING)=0A-becomes=20just=20= a=20more=20verbose=20version=20of=20STRING."=0A-=20=20(rx-group-if=20= (rx-form=20form)=20(null=20no-group)))=0A+=20=20"Translate=20FORM=20from=20= `rx'=20sexp=20syntax=20into=20a=20string=20regexp.=0A+The=20arguments=20= to=20`literal'=20and=20`regexp'=20forms=20inside=20FORM=20must=20be=0A= +constant=20strings.=0A+If=20NO-GROUP=20is=20non-nil,=20don't=20bracket=20= the=20result=20in=20a=20non-capturing=0A+group.=0A+=0A+For=20extending=20= the=20`rx'=20notation=20in=20FORM,=20use=20`rx-define'=20or=20= `rx-let-eval'."=0A+=20=20(let*=20((item=20(rx--translate=20form))=0A+=20=20= =20=20=20=20=20=20=20(exprs=20(if=20no-group=0A+=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20(car=20item)=0A+=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20(rx--atomic-regexp=20item))))=0A+=20=20=20=20= (apply=20#'concat=20exprs)))=0A+=0A+(defun=20rx--to-expr=20(form)=0A+=20=20= "Translate=20the=20rx-expression=20FORM=20to=20a=20Lisp=20expression=20= yielding=20a=20regexp."=0A+=20=20(let*=20((rx--delayed-evaluation=20t)=0A= +=20=20=20=20=20=20=20=20=20(elems=20(car=20(rx--translate=20form)))=0A+=20= =20=20=20=20=20=20=20=20(args=20nil))=0A+=20=20=20=20;;=20Merge=20= adjacent=20strings.=0A+=20=20=20=20(while=20elems=0A+=20=20=20=20=20=20= (let=20((strings=20nil))=0A+=20=20=20=20=20=20=20=20(while=20(and=20= elems=20(stringp=20(car=20elems)))=0A+=20=20=20=20=20=20=20=20=20=20= (push=20(car=20elems)=20strings)=0A+=20=20=20=20=20=20=20=20=20=20(setq=20= elems=20(cdr=20elems)))=0A+=20=20=20=20=20=20=20=20(let=20((s=20(apply=20= #'concat=20(nreverse=20strings))))=0A+=20=20=20=20=20=20=20=20=20=20= (unless=20(zerop=20(length=20s))=0A+=20=20=20=20=20=20=20=20=20=20=20=20= (push=20s=20args))))=0A+=20=20=20=20=20=20(when=20elems=0A+=20=20=20=20=20= =20=20=20(push=20(car=20elems)=20args)=0A+=20=20=20=20=20=20=20=20(setq=20= elems=20(cdr=20elems))))=0A+=20=20=20=20(cond=20((null=20args)=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;=200=20args=0A+=20=20=20=20=20=20=20=20=20=20((cdr=20args)=20= (cons=20'concat=20(nreverse=20args)))=20=20;=20=E2=89=A52=20args=0A+=20=20= =20=20=20=20=20=20=20=20(t=20(car=20args)))))=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;=201=20arg=0A=20=0A= =20=0A=20;;;###autoload=0A@@=20-1054,78=20+1045,186=20@@=20rx=0A=20=0A=20= (literal=20EXPR)=20Match=20the=20literal=20string=20from=20evaluating=20= EXPR=20at=20run=20time.=0A=20(regexp=20EXPR)=20=20Match=20the=20string=20= regexp=20from=20evaluating=20EXPR=20at=20run=20time.=0A-(eval=20EXPR)=20=20= =20=20Match=20the=20rx=20sexp=20from=20evaluating=20EXPR=20at=20compile=20= time."=0A-=20=20(let*=20((rx--compile-to-lisp=20t)=0A-=20=20=20=20=20=20=20= =20=20(re=20(cond=20((null=20regexps)=0A-=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20(error=20"No=20regexp"))=0A-=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20((cdr=20regexps)=0A-=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(rx-to-string=20`(and=20= ,@regexps)=20t))=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20(t=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (rx-to-string=20(car=20regexps)=20t)))))=0A-=20=20=20=20(if=20(stringp=20= re)=0A-=20=20=20=20=20=20=20=20re=0A-=20=20=20=20=20=20`(concat=20= ,@re))))=0A+(eval=20EXPR)=20=20=20=20Match=20the=20rx=20sexp=20from=20= evaluating=20EXPR=20at=20compile=20time.=0A+=0A+Additional=20constructs=20= can=20be=20defined=20using=20`rx-define'=20and=20`rx-let',=0A+which=20= see.=0A+=0A+\(fn=20REGEXPS...)"=0A+=20=20;;=20Retrieve=20local=20= definitions=20from=20the=20macroexpansion=20environment.=0A+=20=20;;=20= (It's=20unclear=20whether=20the=20previous=20value=20of=20= `rx--local-definitions'=0A+=20=20;;=20should=20be=20included,=20and=20if=20= so,=20in=20which=20order.)=0A+=20=20(let=20((rx--local-definitions=0A+=20= =20=20=20=20=20=20=20=20(cdr=20(assq=20:rx-locals=20= macroexpand-all-environment))))=0A+=20=20=20=20(rx--to-expr=20(cons=20= 'seq=20regexps))))=0A+=0A+(defun=20rx--make-binding=20(bindspec)=0A+=20=20= "Make=20a=20definitions=20entry=20out=20of=20BINDSPEC.=0A+BINDSPEC=20is=20= on=20the=20form=20(NAME=20[ARGLIST]=20DEFINITION)."=0A+=20=20(unless=20= (consp=20bindspec)=0A+=20=20=20=20(error=20"Bad=20`rx-let'=20binding:=20= %S"=20bindspec))=0A+=20=20(let=20((name=20(car=20bindspec))=0A+=20=20=20=20= =20=20=20=20(tail=20(cdr=20bindspec)))=0A+=20=20=20=20(unless=20(symbolp=20= name)=0A+=20=20=20=20=20=20(error=20"Bad=20`rx'=20definition=20name:=20= %S"=20name))=0A+=20=20=20=20(cons=20name=0A+=20=20=20=20=20=20=20=20=20=20= (pcase=20tail=0A+=20=20=20=20=20=20=20=20=20=20=20=20(`(,def)=0A+=20=20=20= =20=20=20=20=20=20=20=20=20=20(list=20def))=0A+=20=20=20=20=20=20=20=20=20= =20=20=20(`(,args=20,def)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20= (unless=20(and=20(listp=20args)=20(rx--every=20#'symbolp=20args))=0A+=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20(error=20"Bad=20argument=20list=20= for=20`rx'=20definition=20%s:=20%S"=20name=20args))=0A+=20=20=20=20=20=20= =20=20=20=20=20=20=20(list=20args=20def))=0A+=20=20=20=20=20=20=20=20=20=20= =20=20(_=20(error=20"Bad=20`rx'=20definition=20of=20%s:=20%S"=20name=20= tail))))))=0A+=0A+(defun=20rx--extend-local-defs=20(bindspecs)=0A+=20=20= (append=20(mapcar=20#'rx--make-binding=20bindspecs)=0A+=20=20=20=20=20=20= =20=20=20=20rx--local-definitions))=0A=20=0A+;;;###autoload=0A+(defmacro=20= rx-let-eval=20(bindings=20&rest=20body)=0A+=20=20"Evaluate=20BODY=20with=20= local=20BINDINGS=20for=20`rx-to-string'.=0A+BINDINGS,=20after=20= evaluation,=20is=20a=20list=20of=20definitions=20each=20on=20the=20form=0A= +(NAME=20[(ARGS...)]=20RX),=20in=20effect=20for=20calls=20to=20= `rx-to-string'=0A+in=20BODY.=0A+=0A+For=20bindings=20without=20an=20ARGS=20= list,=20NAME=20is=20defined=20as=20an=20alias=0A+for=20the=20`rx'=20= expression=20RX.=20=20Where=20ARGS=20is=20supplied,=20NAME=20is=0A= +defined=20as=20an=20`rx'=20form=20with=20ARGS=20as=20argument=20list.=20= =20The=0A+parameters=20are=20bound=20from=20the=20values=20in=20the=20= (NAME=20...)=20form=20and=0A+are=20substituted=20in=20RX.=20=20ARGS=20= can=20contain=20`&rest'=20parameters,=0A+which=20are=20automatically=20= surrounded=20by=20`(seq=20...)'=20upon=0A+substitution.=0A+=0A+Any=20= previous=20definitions=20with=20the=20same=20names=20are=20shadowed=20= during=0A+the=20expansion=20of=20BODY=20only.=0A+For=20extensions=20when=20= using=20the=20`rx'=20macro,=20use=20`rx-let'.=0A+To=20make=20global=20rx=20= extensions,=20use=20`rx-define'.=0A+For=20more=20details,=20see=20Info=20= node=20`(elisp)=20Extending=20Rx'.=0A+=0A+\(fn=20BINDINGS=20BODY...)"=0A= +=20=20(declare=20(indent=201)=20(debug=20(form=20body)))=0A+=20=20`(let=20= ((rx--local-definitions=20(rx--extend-local-defs=20,bindings)))=0A+=20=20= =20=20=20,@body))=0A+=0A+;;;###autoload=0A+(defmacro=20rx-let=20= (bindings=20&rest=20body)=0A+=20=20"Evaluate=20BODY=20with=20local=20= BINDINGS=20for=20`rx'.=0A+BINDINGS=20is=20an=20unevaluated=20list=20of=20= bindings=20each=20on=20the=20form=0A+(NAME=20[(ARGS...)]=20RX).=0A+They=20= are=20bound=20lexically=20and=20are=20available=20in=20`rx'=20= expressions=20in=0A+BODY=20only.=0A+=0A+For=20bindings=20without=20an=20= ARGS=20list,=20NAME=20is=20defined=20as=20an=20alias=0A+for=20the=20`rx'=20= expression=20RX.=20=20Where=20ARGS=20is=20supplied,=20NAME=20is=0A= +defined=20as=20an=20`rx'=20form=20with=20ARGS=20as=20argument=20list.=20= =20The=0A+parameters=20are=20bound=20from=20the=20values=20in=20the=20= (NAME=20...)=20form=20and=0A+are=20substituted=20in=20RX.=20=20ARGS=20= can=20contain=20`&rest'=20parameters,=0A+which=20are=20automatically=20= surrounded=20by=20`(seq=20...)'=20upon=0A+substitution.=0A+=0A+Any=20= previous=20definitions=20with=20the=20same=20names=20are=20shadowed=20= during=0A+the=20expansion=20of=20BODY=20only.=0A+For=20local=20= extensions=20to=20`rx-to-string',=20use=20`rx-let-eval'.=0A+To=20make=20= global=20rx=20extensions,=20use=20`rx-define'.=0A+For=20more=20details,=20= see=20Info=20node=20`(elisp)=20Extending=20Rx'.=0A+=0A+\(fn=20BINDINGS=20= BODY...)"=0A+=20=20(declare=20(indent=201)=20(debug=20(sexp=20body)))=0A= +=20=20(let=20((prev-locals=20(cdr=20(assq=20:rx-locals=20= macroexpand-all-environment)))=0A+=20=20=20=20=20=20=20=20(new-locals=20= (mapcar=20#'rx--make-binding=20bindings)))=0A+=20=20=20=20= (macroexpand-all=20(cons=20'progn=20body)=0A+=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20(cons=20(cons=20:rx-locals=20(append=20= new-locals=20prev-locals))=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=20macroexpand-all-environment))))=0A+=0A= +;;;###autoload=0A+(defmacro=20rx-define=20(name=20&rest=20definition)=0A= +=20=20"Define=20NAME=20as=20a=20global=20`rx'=20definition.=0A+If=20the=20= ARGS=20list=20is=20omitted,=20define=20NAME=20as=20an=20alias=20for=20= the=20`rx'=0A+expression=20RX.=0A+=0A+If=20the=20ARGS=20list=20is=20= supplied,=20define=20NAME=20as=20an=20`rx'=20form=20with=0A+ARGS=20as=20= argument=20list.=20=20The=20parameters=20are=20bound=20from=20the=20= values=0A+in=20the=20(NAME=20...)=20form=20and=20are=20substituted=20in=20= RX.=0A+ARGS=20can=20contain=20`&rest'=20parameters,=20which=20are=20= automatically=0A+surrounded=20by=20`(seq=20...)'=20upon=20substitution.=0A= +=0A+Any=20previous=20global=20definition=20of=20NAME=20is=20overwritten=20= with=20the=20new=20one.=0A+To=20make=20local=20rx=20extensions,=20use=20= `rx-let'=20for=20`rx',=0A+`rx-let-eval'=20for=20`rx-to-string'.=0A+For=20= more=20details,=20see=20Info=20node=20`(elisp)=20Extending=20Rx'.=0A+=0A= +\(fn=20NAME=20[(ARGS...)]=20RX)"=0A+=20=20(declare=20(indent=201))=0A+=20= =20(setq=20rx--global-definitions=0A+=20=20=20=20=20=20=20=20(cons=20= (rx--make-binding=20(cons=20name=20definition))=0A+=20=20=20=20=20=20=20=20= =20=20=20=20=20=20(delq=20(assq=20name=20rx--global-definitions)=0A+=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= rx--global-definitions)))=0A+=20=20(list=20'quote=20name))=0A+=0A= +(defmacro=20rx--save-definitions=20(&rest=20body)=0A+=20=20"Expand=20= BODY=20and=20restore=20rx=20definitions=20afterwards.=20=20For=20testing=20= only."=0A+=20=20(let=20((rx--global-definitions=20= rx--global-definitions)=0A+=20=20=20=20=20=20=20=20= (rx--local-definitions=20rx--local-definitions))=0A+=20=20=20=20= (macroexpand-all=20`(progn=20,@body)=20macroexpand-all-environment)))=0A= +=0A+;;=20During=20`rx--pcase-transform',=20list=20of=20defined=20= variables=20in=20right-to-left=0A+;;=20order.=0A+(defvar=20= rx--pcase-vars)=0A+=0A+;;=20FIXME:=20The=20rewriting=20strategy=20for=20= pcase=20works=20so-so=20with=20extensions;=0A+;;=20definitions=20cannot=20= expand=20to=20`let'=20or=20named=20`backref'.=20=20If=20this=20ever=0A= +;;=20becomes=20a=20problem,=20we=20can=20handle=20those=20forms=20in=20= the=20ordinary=20parser,=0A+;;=20using=20a=20dynamic=20variable=20for=20= activating=20the=20augmented=20forms.=0A+=0A+(defun=20= rx--pcase-transform=20(rx)=0A+=20=20"Transform=20RX,=20an=20= rx-expression=20augmented=20with=20`let'=20and=20named=20`backref',=0A= +into=20a=20plain=20rx-expression,=20collecting=20names=20into=20= `rx--pcase-vars'."=0A+=20=20(pcase=20rx=0A+=20=20=20=20(`(let=20,name=20= .=20,body)=0A+=20=20=20=20=20(let*=20((index=20(length=20(memq=20name=20= rx--pcase-vars)))=0A+=20=20=20=20=20=20=20=20=20=20=20=20(i=20(if=20= (zerop=20index)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20(length=20(push=20name=20rx--pcase-vars))=0A+=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20index)))=0A+=20=20=20=20=20=20=20`(group-n=20,i=20= ,(rx--pcase-transform=20(cons=20'seq=20body)))))=0A+=20=20=20=20((and=20= `(backref=20,ref)=0A+=20=20=20=20=20=20=20=20=20=20(guard=20(symbolp=20= ref)))=0A+=20=20=20=20=20(let=20((index=20(length=20(memq=20ref=20= rx--pcase-vars))))=0A+=20=20=20=20=20=20=20(when=20(zerop=20index)=0A+=20= =20=20=20=20=20=20=20=20(error=20"rx=20`backref'=20variable=20must=20be=20= one=20of:=20%s"=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (mapconcat=20#'symbol-name=20rx--pcase-vars=20"=20")))=0A+=20=20=20=20=20= =20=20`(backref=20,index)))=0A+=20=20=20=20((and=20`(,head=20.=20,rest)=0A= +=20=20=20=20=20=20=20=20=20=20(guard=20(and=20(symbolp=20head)=0A+=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(not=20(memq=20= head=20'(literal=20regexp=20regex=20eval))))))=0A+=20=20=20=20=20(cons=20= head=20(mapcar=20#'rx--pcase-transform=20rest)))=0A+=20=20=20=20(_=20= rx)))=0A=20=0A=20(pcase-defmacro=20rx=20(&rest=20regexps)=0A-=20=20= "Build=20a=20`pcase'=20pattern=20matching=20`rx'=20REGEXPS=20in=20sexp=20= form.=0A-The=20REGEXPS=20are=20interpreted=20as=20in=20`rx'.=20=20The=20= pattern=20matches=20any=0A-string=20that=20is=20a=20match=20for=20the=20= regular=20expression=20so=20constructed,=0A-as=20if=20by=20= `string-match'.=0A+=20=20"A=20pattern=20that=20matches=20strings=20= against=20`rx'=20REGEXPS=20in=20sexp=20form.=0A+REGEXPS=20are=20= interpreted=20as=20in=20`rx'.=20=20The=20pattern=20matches=20any=0A= +string=20that=20is=20a=20match=20for=20REGEXPS,=20as=20if=20by=20= `string-match'.=0A=20=0A-In=20addition=20to=20the=20usual=20`rx'=20= constructs,=20REGEXPS=20can=20contain=20the=0A+In=20addition=20to=20the=20= usual=20`rx'=20syntax,=20REGEXPS=20can=20contain=20the=0A=20following=20= constructs:=0A=20=0A-=20=20(let=20REF=20SEXP...)=20=20creates=20a=20new=20= explicitly=20named=20reference=20to=0A-=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20a=20submatch=20that=20matches=20regular=20= expressions=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20SEXP,=20and=20binds=20the=20match=20to=20REF.=0A-=20=20(backref=20= REF)=20=20=20=20=20=20creates=20a=20backreference=20to=20the=20submatch=0A= -=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= introduced=20by=20a=20previous=20(let=20REF=20...)=0A-=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20construct.=20=20REF=20can=20be=20= the=20same=20symbol=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20in=20the=20first=20argument=20of=20the=20corresponding=0A-=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(let=20REF=20= ...)=20construct,=20or=20it=20can=20be=20a=0A-=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20submatch=20number.=20=20It=20matches=20= the=20referenced=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20submatch.=0A-=0A-The=20REFs=20are=20associated=20with=20= explicitly=20named=20submatches=20starting=0A-from=201.=20=20Multiple=20= occurrences=20of=20the=20same=20REF=20refer=20to=20the=20same=0A= -submatch.=0A-=0A-If=20a=20case=20matches,=20the=20match=20data=20is=20= modified=20as=20usual=20so=20you=20can=0A-use=20it=20in=20the=20case=20= body,=20but=20you=20still=20have=20to=20pass=20the=20correct=0A-string=20= as=20argument=20to=20`match-string'."=0A-=20=20(let*=20((vars=20())=0A-=20= =20=20=20=20=20=20=20=20(rx-constituents=0A-=20=20=20=20=20=20=20=20=20=20= `((let=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20,(lambda=20(form)=0A-=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(rx-check=20form)=0A-=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20(let=20((var=20(cadr=20form)))=0A= -=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(cl-check-type=20= var=20symbol)=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (let=20((i=20(or=20(cl-position=20var=20vars=20:test=20#'eq)=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(prog1=20(length=20vars)=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=20(setq=20= vars=20`(,@vars=20,var))))))=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20(rx-form=20`(submatch-n=20,(1+=20i)=20,@(cddr=20= form))))))=0A-=20=20=20=20=20=20=20=20=20=20=20=20=201=20nil)=0A-=20=20=20= =20=20=20=20=20=20=20=20=20(backref=0A-=20=20=20=20=20=20=20=20=20=20=20=20= =20,(lambda=20(form)=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (rx-check=20form)=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (rx-backref=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= `(backref=20,(let=20((var=20(cadr=20form)))=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(if=20= (integerp=20var)=20var=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(1+=20(cl-position=20var=20= vars=20:test=20#'eq)))))))=0A-=20=20=20=20=20=20=20=20=20=20=20=20=201=20= 1=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20,(lambda=20(var)=0A-=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20(cond=20((integerp=20var)=20= (rx-check-backref=20var))=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20((memq=20var=20vars)=20t)=0A-=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20(t=20(error=20"rx=20`backref'=20= variable=20must=20be=20one=20of=20%s:=20%s"=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= vars=20var)))))=0A-=20=20=20=20=20=20=20=20=20=20=20=20= ,@rx-constituents))=0A-=20=20=20=20=20=20=20=20=20(regexp=20= (rx-to-string=20`(seq=20,@regexps)=20:no-group)))=0A+=20=20(let=20REF=20= RX...)=20=20binds=20the=20symbol=20REF=20to=20a=20submatch=20that=20= matches=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20the=20= regular=20expressions=20RX.=20=20REF=20is=20bound=20in=0A+=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20CODE=20to=20the=20string=20of=20= the=20submatch=20or=20nil,=20but=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20can=20also=20be=20used=20in=20`backref'.=0A+=20=20= (backref=20REF)=20=20=20=20matches=20whatever=20the=20submatch=20REF=20= matched.=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20REF=20= can=20be=20a=20number,=20as=20usual,=20or=20a=20name=0A+=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20introduced=20by=20a=20previous=20= (let=20REF=20...)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20construct."=0A+=20=20(let*=20((rx--pcase-vars=20nil)=0A+=20=20=20=20=20= =20=20=20=20(regexp=20(rx--to-expr=20(rx--pcase-transform=20(cons=20'seq=20= regexps)))))=0A=20=20=20=20=20`(and=20(pred=20(string-match=20,regexp))=0A= -=20=20=20=20=20=20=20=20=20=20,@(cl-loop=20for=20i=20from=201=0A-=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20for=20var=20in=20= vars=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= collect=20`(app=20(match-string=20,i)=20,var)))))=0A-=0C=0A+=20=20=20=20=20= =20=20=20=20=20,@(let=20((i=200))=0A+=20=20=20=20=20=20=20=20=20=20=20=20= =20=20(mapcar=20(lambda=20(name)=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(setq=20i=20(1+=20i))=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`(app=20= (match-string=20,i)=20,name))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20(reverse=20rx--pcase-vars))))))=0A+=0A=20= (provide=20'rx)=0A=20=0A-;;;=20rx.el=20ends=20here=0A+;;=20rx.el=20ends=20= here=0Adiff=20--git=20a/test/lisp/emacs-lisp/rx-tests.el=20= b/test/lisp/emacs-lisp/rx-tests.el=0Aindex=208845ebf46d..060537496c=20= 100644=0A---=20a/test/lisp/emacs-lisp/rx-tests.el=0A+++=20= b/test/lisp/emacs-lisp/rx-tests.el=0A@@=20-1,4=20+1,4=20@@=0A-;;;=20= rx-tests.el=20---=20test=20for=20rx.el=20functions=20-*-=20= lexical-binding:=20t=20-*-=0A+;;;=20rx-tests.el=20---=20tests=20for=20= rx.el=20=20=20=20=20=20=20=20=20=20=20=20=20=20-*-=20lexical-binding:=20= t=20-*-=0A=20=0A=20;;=20Copyright=20(C)=202016-2019=20Free=20Software=20= Foundation,=20Inc.=0A=20=0A@@=20-17,21=20+17,46=20@@=0A=20;;=20You=20= should=20have=20received=20a=20copy=20of=20the=20GNU=20General=20Public=20= License=0A=20;;=20along=20with=20GNU=20Emacs.=20=20If=20not,=20see=20= .=0A=20=0A-;;;=20Commentary:=0A-=0A=20= (require=20'ert)=0A=20(require=20'rx)=0A=20=0A-;;;=20Code:=0A= +(ert-deftest=20rx-seq=20()=0A+=20=20(should=20(equal=20(rx=20"a.b"=20= "*"=20"c")=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= "a\\.b\\*c"))=0A+=20=20(should=20(equal=20(rx=20(seq=20"a"=20(:=20"b"=20= (and=20"c"=20(sequence=20"d"=20nonl)=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=20=20=20=20= =20=20=20=20=20=20"e")=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=20"f")=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"g"))=0A+=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20"abcd.efg"))=0A+=20=20= (should=20(equal=20(rx=20"a$"=20"b")=0A+=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20"a\\$b"))=0A+=20=20(should=20(equal=20(rx=20bol=20"a"=20= "b"=20?c=20eol)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= "^abc$"))=0A+=20=20(should=20(equal=20(rx=20"a"=20""=20"b")=0A+=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20"ab"))=0A+=20=20(should=20(equal=20= (rx=20(seq))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20""))=0A= +=20=20(should=20(equal=20(rx=20""=20(or=20"ab"=20nonl)=20"")=0A+=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20"ab\\|."))=0A+=20=20)=0A+=0A= +(ert-deftest=20rx-or=20()=0A+=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"ab\\|c\\|.\\|de"))=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= "\\(?:ab\\|abc\\|a\\)"))=0A+=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"\\(?:.\\|a\\)\\(?:b\\|[[:blank:]]\\)"))=0A+=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= "\\`a\\`"))=0A+=20=20)=0A=20=0A=20(ert-deftest=20rx-char-any=20()=0A=20=20= =20"Test=20character=20alternatives=20with=20`]'=20and=20`-'=20= (Bug#25123)."=0A-=20=20(should=20(string-match=0A+=20=20(should=20(equal=0A= =20=20=20=20=20=20=20=20=20=20=20=20(rx=20string-start=20(1+=20(char=20= (?\]=20.=20?\{)=20(?<=20.=20?\])=20(?-=20.=20?:)))=0A=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20string-end)=0A-=20=20=20=20=20=20=20=20=20=20=20= (apply=20#'string=20(nconc=20(number-sequence=20?\]=20?\{)=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=20=20(number-sequence=20?<=20?\])=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=20=20= (number-sequence=20?-=20?:))))))=0A+=20=20=20=20=20=20=20=20=20=20=20= "\\`[.-:<-{-]+\\'")))=0A=20=0A=20(ert-deftest=20rx-char-any-range-nl=20= ()=0A=20=20=20"Test=20character=20alternatives=20with=20LF=20as=20a=20= range=20endpoint."=0A@@=20-40,28=20+65,68=20@@=0A=20=20=20(should=20= (equal=20(rx=20(any=20"\a-\n"))=0A=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20"[\a-\n]")))=0A=20=0A-(ert-deftest=20= rx-char-any-range-bad=20()=0A-=20=20(should-error=20(rx=20(any=20= "0-9a-Z")))=0A-=20=20(should-error=20(rx=20(any=20(?0=20.=20?9)=20(?a=20= .=20?Z)))))=0A-=0A=20(ert-deftest=20rx-char-any-raw-byte=20()=0A=20=20=20= "Test=20raw=20bytes=20in=20character=20alternatives."=0A=20=20=20;;=20= Separate=20raw=20characters.=0A-=20=20(should=20(equal=20(string-match-p=20= (rx=20(any=20"\326A\333B"))=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=20"X\326\333")=0A= -=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=201))=0A+=20=20(should=20= (equal=20(rx=20(any=20"\326A\333B"))=0A+=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20(string-to-multibyte=20"[AB\326\333]")))=0A=20=20=20;;=20= Range=20of=20raw=20characters,=20unibyte.=0A-=20=20(should=20(equal=20= (string-match-p=20(rx=20(any=20"\200-\377"))=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=20= "=C3=BFA\310B")=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= 2))=0A+=20=20(should=20(equal=20(rx=20(any=20"\200-\377"))=0A+=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20(string-to-multibyte=20= "[\200-\377]")))=0A=20=20=20;;=20Range=20of=20raw=20characters,=20= multibyte.=0A-=20=20(should=20(equal=20(string-match-p=20(rx=20(any=20= "=C3=85\211\326-\377\177"))=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=20= "XY\355\177\327")=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= 2))=0A+=20=20(should=20(equal=20(rx=20(any=20"=C3=85\211\326-\377\177"))=0A= +=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= "[\177=C3=85\211\326-\377]"))=0A=20=20=20;;=20Split=20range;=20= \177-\377=C3=BF=20should=20not=20be=20optimised=20to=20\177-\377.=0A-=20=20= (should=20(equal=20(string-match-p=20(rx=20(any=20"\177-\377"=20?=C3=BF))=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=20"=C3=BFA\310B")=0A-=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=200)))=0A+=20=20(should=20(equal=20(rx=20(any=20= "\177-\377"=20?=C3=BF))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20"[\177=C3=BF\200-\377]")))=0A+=0A+(ert-deftest=20rx-any=20()=0A+=20=20= (should=20(equal=20(rx=20(any=20?A=20(?C=20.=20?D)=20"F-H"=20"J-L"=20"M"=20= "N-P"=20"Q"=20"RS"))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= "[ACDF-HJ-S]"))=0A+=20=20(should=20(equal=20(rx=20(in=20"a!f"=20?c)=20= (char=20"q-z"=20"0-3")=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20(not-char=20"a-e1-5")=20(not=20(in=20"A-M"=20?q)))=0A+=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= "[!acf][0-3q-z][^1-5a-e][^A-Mq]"))=0A+=20=20(should=20(equal=20(rx=20= (any=20"^")=20(any=20"]")=20(any=20"-")=0A+=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20(not=20(any=20"^"))=20(not=20(any=20= "]"))=20(not=20(any=20"-")))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20"\\^]-[^^][^]][^-]"))=0A+=20=20(should=20(equal=20(rx=20(any=20= "]"=20"^")=20(any=20"]"=20"-")=20(any=20"-"=20"^")=0A+=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20(not=20(any=20"]"=20"^"))=20= (not=20(any=20"]"=20"-"))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20(not=20(any=20"-"=20"^")))=0A+=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20"[]^][]-][-^][^]^][^]-][^-^]"))=0A+=20=20(should=20= (equal=20(rx=20(any=20"]"=20"^"=20"-")=20(not=20(any=20"]"=20"^"=20= "-")))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= "[]^-][^]^-]"))=0A+=20=20(should=20(equal=20(rx=20(any=20"-"=20ascii)=20= (any=20"^"=20ascii)=20(any=20"]"=20ascii))=0A+=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20"[[:ascii:]-][[:ascii:]^][][:ascii:]]"))=0A+=20=20= (should=20(equal=20(rx=20(not=20(any=20"-"=20ascii))=20(not=20(any=20"^"=20= ascii))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (not=20(any=20"]"=20ascii)))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20"[^[:ascii:]-][^[:ascii:]^][^][:ascii:]]"))=0A+=20=20(should=20= (equal=20(rx=20(any=20"-]"=20ascii)=20(any=20"^]"=20ascii)=20(any=20"-^"=20= ascii))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= "[][:ascii:]-][]^[:ascii:]][[:ascii:]^-]"))=0A+=20=20(should=20(equal=20= (rx=20(not=20(any=20"-]"=20ascii))=20(not=20(any=20"^]"=20ascii))=0A+=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(not=20(any=20= "-^"=20ascii)))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= "[^][:ascii:]-][^]^[:ascii:]][^[:ascii:]^-]"))=0A+=20=20(should=20(equal=20= (rx=20(any=20"-]^"=20ascii)=20(not=20(any=20"-]^"=20ascii)))=0A+=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20= "[]^[:ascii:]-][^]^[:ascii:]-]"))=0A+=20=20(should=20(equal=20(rx=20(any=20= "^"=20lower=20upper)=20(not=20(any=20"^"=20lower=20upper)))=0A+=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20= "[[:lower:]^[:upper:]][^[:lower:]^[:upper:]]"))=0A+=20=20(should=20= (equal=20(rx=20(any=20"-"=20lower=20upper)=20(not=20(any=20"-"=20lower=20= upper)))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= "[[:lower:][:upper:]-][^[:lower:][:upper:]-]"))=0A+=20=20(should=20= (equal=20(rx=20(any=20"]"=20lower=20upper)=20(not=20(any=20"]"=20lower=20= upper)))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= "[][:lower:][:upper:]][^][:lower:][:upper:]]"))=0A+=20=20(should=20= (equal=20(rx=20(any=20"-a"=20"c-"=20"f-f"=20"--/*--"))=0A+=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20"[*-/acf]"))=0A+=20=20(should=20= (equal=20(rx=20(any=20"]-a"=20?-)=20(not=20(any=20"]-a"=20?-)))=0A+=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20"[]-a-][^]-a-]"))=0A+=20=20= (should=20(equal=20(rx=20(any=20"--]")=20(not=20(any=20"--]"))=0A+=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(any=20"-"=20= "^-a")=20(not=20(any=20"-"=20"^-a")))=0A+=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20"[].-\\-][^].-\\-][-^-a][^-^-a]"))=0A+=20=20(should=20= (equal=20(rx=20(not=20(any=20"!a"=20"0-8"=20digit=20nonascii)))=0A+=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= "[^!0-8a[:digit:][:nonascii:]]"))=0A+=20=20(should=20(equal=20(rx=20= (any)=20(not=20(any)))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20"\\`a\\`\\(?:.\\|\n\\)"))=0A+=20=20(should=20(equal=20(rx=20(any=20= "")=20(not=20(any=20"")))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20"\\`a\\`\\(?:.\\|\n\\)"))=0A+=20=20)=0A=20=0A=20(ert-deftest=20= rx-pcase=20()=0A=20=20=20(should=20(equal=20(pcase=20"a=201=202=203=201=20= 1=20b"=0A@@=20-71,7=20+136,12=20@@=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(backref=20u)=20space=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(backref=20= 1))=0A=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (list=20u=20v)))=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= '("1"=20"3"))))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= '("1"=20"3")))=0A+=20=20(let=20((k=20"blue"))=0A+=20=20=20=20(should=20= (equal=20(pcase=20""=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20((rx=20"<"=20(literal=20k)=20">")=20'ok))=0A+=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20'ok)))=0A+=20=20)=0A=20=0A=20= (ert-deftest=20rx-kleene=20()=0A=20=20=20"Test=20greedy=20and=20= non-greedy=20repetition=20operators."=0A@@=20-94,71=20+164,244=20@@=0A=20= =20=20(should=20(equal=20(rx=20(maximal-match=0A=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20(seq=20(*=20"a")=20(+=20"b")=20= (\?=20"c")=20(?\s=20"d")=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"e")=20(+?=20"f")=20(\??=20"g")=20= (??=20"h"))))=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= "a*b+c?d?e*?f+?g??h??")))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20"a*b+c?d?e*?f+?g??h??"))=0A+=20=20(should=20(equal=20(rx=20"a"=20= (*)=20(+=20(*))=20(?=20(*)=20(+))=20"b")=0A+=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20"ab"))=0A+=20=20)=0A=20=0A-(ert-deftest=20rx-or=20= ()=0A-=20=20;;=20Test=20or-pattern=20reordering=20(Bug#34641).=0A-=20=20= (let=20((s=20"abc"))=0A-=20=20=20=20(should=20(equal=20(and=20= (string-match=20(rx=20(or=20"abc"=20"ab"=20"a"))=20s)=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(match-string=200=20= s))=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20"abc"))=0A= -=20=20=20=20(should=20(equal=20(and=20(string-match=20(rx=20(or=20"ab"=20= "abc"=20"a"))=20s)=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(match-string=200=20s))=0A-=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20"ab"))=0A-=20=20=20=20(should=20(equal=20= (and=20(string-match=20(rx=20(or=20"a"=20"ab"=20"abc"))=20s)=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= (match-string=200=20s))=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20"a")))=0A-=20=20;;=20Test=20zero-argument=20`or'.=0A-=20=20= (should=20(equal=20(rx=20(or))=20regexp-unmatchable)))=0A+(ert-deftest=20= rx-repeat=20()=0A+=20=20(should=20(equal=20(rx=20(=3D=203=20"a")=20(>=3D=20= 51=20"b")=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20(**=202=2011=20"c")=20(repeat=206=20"d")=20(repeat=204=208=20"e"))=0A= +=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= "a\\{3\\}b\\{51,\\}c\\{2,11\\}d\\{6\\}e\\{4,8\\}"))=0A+=20=20(should=20= (equal=20(rx=20(=3D=200=20"k")=20(>=3D=200=20"l")=20(**=200=200=20"m")=20= (repeat=200=20"n")=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20(repeat=200=200=20"o"))=0A+=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20"k\\{0\\}l\\{0,\\}m\\{0\\}n\\{0\\}o\\{0\\}"))=0A+=20=20= (should=20(equal=20(rx=20(opt=20(0+=20"a")))=0A+=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20"\\(?:a*\\)?"))=0A+=20=20(should=20(equal=20(rx=20= (opt=20(=3D=204=20"a")))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20"a\\{4\\}?"))=0A+=20=20(should=20(equal=20(rx=20"a"=20(**=203=207)=20= (=3D=204)=20(>=3D=203)=20(=3D=204=20(>=3D=207)=20(=3D=202))=20"b")=0A+=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20"ab"))=0A+=20=20)=0A+=0A= +(ert-deftest=20rx-atoms=20()=0A+=20=20(should=20(equal=20(rx=20= anything)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= ".\\|\n"))=0A+=20=20(should=20(equal=20(rx=20line-start=20not-newline=20= nonl=20any=20line-end)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20"^...$"))=0A+=20=20(should=20(equal=20(rx=20bol=20string-start=20= string-end=20buffer-start=20buffer-end=0A+=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20bos=20eos=20bot=20eot=20eol)=0A+=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20"^\\`\\'\\`\\'\\`\\'\\`\\'$"))=0A= +=20=20(should=20(equal=20(rx=20point=20word-start=20word-end=20bow=20= eow=20symbol-start=20symbol-end=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20word-boundary=20not-word-boundary=20= not-wordchar)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= "\\=3D\\<\\>\\<\\>\\_<\\_>\\b\\B\\W"))=0A+=20=20(should=20(equal=20(rx=20= digit=20numeric=20num=20control=20cntrl)=0A+=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20= "[[:digit:]][[:digit:]][[:digit:]][[:cntrl:]][[:cntrl:]]"))=0A+=20=20= (should=20(equal=20(rx=20hex-digit=20hex=20xdigit=20blank)=0A+=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20= "[[:xdigit:]][[:xdigit:]][[:xdigit:]][[:blank:]]"))=0A+=20=20(should=20= (equal=20(rx=20graph=20graphic=20print=20printing)=0A+=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20= "[[:graph:]][[:graph:]][[:print:]][[:print:]]"))=0A+=20=20(should=20= (equal=20(rx=20alphanumeric=20alnum=20letter=20alphabetic=20alpha)=0A+=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= "[[:alnum:]][[:alnum:]][[:alpha:]][[:alpha:]][[:alpha:]]"))=0A+=20=20= (should=20(equal=20(rx=20ascii=20nonascii=20lower=20lower-case)=0A+=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= "[[:ascii:]][[:nonascii:]][[:lower:]][[:lower:]]"))=0A+=20=20(should=20= (equal=20(rx=20punctuation=20punct=20space=20whitespace=20white)=0A+=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= "[[:punct:]][[:punct:]][[:space:]][[:space:]][[:space:]]"))=0A+=20=20= (should=20(equal=20(rx=20upper=20upper-case=20word=20wordchar)=0A+=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20= "[[:upper:]][[:upper:]][[:word:]][[:word:]]"))=0A+=20=20(should=20(equal=20= (rx=20unibyte=20multibyte)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20"[[:unibyte:]][[:multibyte:]]"))=0A+=20=20)=0A+=0A+(ert-deftest=20= rx-syntax=20()=0A+=20=20(should=20(equal=20(rx=20(syntax=20whitespace)=20= (syntax=20punctuation)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20(syntax=20word)=20(syntax=20symbol)=0A+=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20(syntax=20open-parenthesis)=20= (syntax=20close-parenthesis))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20"\\s-\\s.\\sw\\s_\\s(\\s)"))=0A+=20=20(should=20(equal=20(rx=20= (syntax=20string-quote)=20(syntax=20paired-delimiter)=0A+=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(syntax=20escape)=20(syntax=20= character-quote)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20(syntax=20comment-start)=20(syntax=20comment-end)=0A+=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(syntax=20= string-delimiter)=20(syntax=20comment-delimiter))=0A+=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20"\\s\"\\s$\\s\\\\s/\\s<\\s>\\s|\\s!"))=0A+=20= =20)=0A+=0A+(ert-deftest=20rx-category=20()=0A+=20=20(should=20(equal=20= (rx=20(category=20space-for-indent)=20(category=20base)=0A+=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(category=20consonant)=20= (category=20base-vowel)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20(category=20upper-diacritical-mark)=0A+=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20(category=20= lower-diacritical-mark)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20(category=20tone-mark)=20(category=20symbol)=0A+=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(category=20digit)=0A= +=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (category=20vowel-modifying-diacritical-mark)=0A+=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20(category=20vowel-sign)=20= (category=20semivowel-lower)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20(category=20not-at-end-of-line)=0A+=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(category=20= not-at-beginning-of-line))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20"\\c=20\\c.\\c0\\c1\\c2\\c3\\c4\\c5\\c6\\c7\\c8\\c9\\c<\\c>"))=0A+=20= =20(should=20(equal=20(rx=20(category=20alpha-numeric-two-byte)=0A+=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(category=20= chinese-two-byte)=20(category=20greek-two-byte)=0A+=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20(category=20= japanese-hiragana-two-byte)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20(category=20indian-two-byte)=0A+=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20(category=20= japanese-katakana-two-byte)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20(category=20strong-left-to-right)=0A+=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(category=20= korean-hangul-two-byte)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20(category=20strong-right-to-left)=0A+=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20(category=20cyrillic-two-byte)=0A= +=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (category=20combining-diacritic))=0A+=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20"\\cA\\cC\\cG\\cH\\cI\\cK\\cL\\cN\\cR\\cY\\c^"))=0A+=20=20= (should=20(equal=20(rx=20(category=20ascii)=20(category=20arabic)=20= (category=20chinese)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20(category=20ethiopic)=20(category=20greek)=20(category=20= korean)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (category=20indian)=20(category=20japanese)=0A+=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20(category=20japanese-katakana)=20= (category=20latin)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20(category=20lao)=20(category=20tibetan))=0A+=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20= "\\ca\\cb\\cc\\ce\\cg\\ch\\ci\\cj\\ck\\cl\\co\\cq"))=0A+=20=20(should=20= (equal=20(rx=20(category=20japanese-roman)=20(category=20thai)=0A+=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(category=20= vietnamese)=20(category=20hebrew)=0A+=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20(category=20cyrillic)=20(category=20= can-break))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= "\\cr\\ct\\cv\\cw\\cy\\c|"))=0A+=20=20(should=20(equal=20(rx=20(category=20= ?g)=20(not=20(category=20?~)))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20"\\cg\\C~"))=0A+=20=20)=0A+=0A+(ert-deftest=20rx-not=20()=0A= +=20=20(should=20(equal=20(rx=20(not=20word-boundary))=0A+=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20"\\B"))=0A+=20=20(should=20(equal=20= (rx=20(not=20ascii)=20(not=20lower-case)=20(not=20wordchar))=0A+=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20= "[^[:ascii:]][^[:lower:]][^[:word:]]"))=0A+=20=20(should=20(equal=20(rx=20= (not=20(syntax=20punctuation))=20(not=20(syntax=20escape)))=0A+=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20"\\S.\\S\\"))=0A+=20=20(should=20= (equal=20(rx=20(not=20(category=20tone-mark))=20(not=20(category=20= lao)))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= "\\C4\\Co"))=0A+=20=20)=0A+=0A+(ert-deftest=20rx-group=20()=0A+=20=20= (should=20(equal=20(rx=20(group=20nonl)=20(submatch=20"x")=0A+=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(group-n=203=20"y")=20= (submatch-n=2013=20"z")=20(backref=201))=0A+=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20"\\(.\\)\\(x\\)\\(?3:y\\)\\(?13:z\\)\\1"))=0A+=20=20= (should=20(equal=20(rx=20(group)=20(group-n=202))=0A+=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20"\\(\\)\\(?2:\\)"))=0A+=20=20)=0A+=0A= +(ert-deftest=20rx-regexp=20()=0A+=20=20(should=20(equal=20(rx=20(regexp=20= "abc")=20(regex=20"[de]"))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20"\\(?:abc\\)[de]"))=0A+=20=20(let=20((x=20"a*"))=0A+=20=20=20=20= (should=20(equal=20(rx=20(regexp=20x)=20"b")=0A+=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20"\\(?:a*\\)b"))=0A+=20=20=20=20(should=20= (equal=20(rx=20""=20(regexp=20x)=20(eval=20""))=0A+=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20"a*"))))=0A+=0A+(ert-deftest=20rx-eval=20= ()=0A+=20=20(should=20(equal=20(rx=20(eval=20(list=20'syntax=20= 'symbol)))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= "\\s_"))=0A+=20=20(should=20(equal=20(rx=20"a"=20(eval=20(concat))=20= "b")=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20"ab")))=0A+=0A= +(ert-deftest=20rx-literal=20()=0A+=20=20(should=20(equal=20(rx=20= (literal=20(char-to-string=2042))=20nonl)=0A+=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20"\\*."))=0A+=20=20(let=20((x=20"a+b"))=0A+=20=20=20=20= (should=20(equal=20(rx=20(opt=20(literal=20(upcase=20x))))=0A+=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20"\\(?:A\\+B\\)?"))))=0A+=0A= +(ert-deftest=20rx-to-string=20()=0A+=20=20(should=20(equal=20= (rx-to-string=20'(or=20nonl=20"\nx"))=0A+=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20"\\(?:.\\|\nx\\)"))=0A+=20=20(should=20(equal=20= (rx-to-string=20'(or=20nonl=20"\nx")=20t)=0A+=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20".\\|\nx"))=0A+=20=20)=0A+=0A+(ert-deftest=20rx-let=20= ()=0A+=20=20(rx-let=20((beta=20gamma)=0A+=20=20=20=20=20=20=20=20=20=20=20= (gamma=20delta)=0A+=20=20=20=20=20=20=20=20=20=20=20(delta=20(+=20= digit))=0A+=20=20=20=20=20=20=20=20=20=20=20(epsilon=20(or=20gamma=20= nonl)))=0A+=20=20=20=20(should=20(equal=20(rx=20bol=20delta=20epsilon)=0A= +=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= "^[[:digit:]]+\\(?:[[:digit:]]+\\|.\\)")))=0A+=20=20(rx-let=20((p=20()=20= point)=0A+=20=20=20=20=20=20=20=20=20=20=20(separated=20(x=20sep)=20(seq=20= x=20(*=20sep=20x)))=0A+=20=20=20=20=20=20=20=20=20=20=20(comma-separated=20= (x)=20(separated=20x=20","))=0A+=20=20=20=20=20=20=20=20=20=20=20= (semi-separated=20(x)=20(separated=20x=20";"))=0A+=20=20=20=20=20=20=20=20= =20=20=20(matrix=20(v)=20(semi-separated=20(comma-separated=20v))))=0A+=20= =20=20=20(should=20(equal=20(rx=20(p)=20(matrix=20(+=20"a"))=20eos)=0A+=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= "\\=3Da+\\(?:,a+\\)*\\(?:;a+\\(?:,a+\\)*\\)*\\'")))=0A+=20=20(rx-let=20= ((b=20bol)=0A+=20=20=20=20=20=20=20=20=20=20=20(z=20"B")=0A+=20=20=20=20=20= =20=20=20=20=20=20(three=20(x)=20(=3D=203=20x)))=0A+=20=20=20=20(rx-let=20= ((two=20(x)=20(seq=20x=20x))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20= (z=20"A")=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20(e=20eol))=0A+=20=20=20= =20=20=20(should=20(equal=20(rx=20b=20(two=20(three=20z))=20e)=0A+=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= "^A\\{3\\}A\\{3\\}$"))))=0A+=20=20(rx-let=20((f=20(a=20b=20&rest=20r)=20= (seq=20"<"=20a=20";"=20b=20":"=20r=20">")))=0A+=20=20=20=20(should=20= (equal=20(rx=20bol=20(f=20?x=20?y)=20?!=20(f=20?u=20?v=20?w)=20?!=20(f=20= ?k=20?l=20?m=20?n)=20eol)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20"^!!$")))=0A+=20=20;;=20Currently,=20= rest=20parameters=20are=20sequenced;=20if=20we=20make=20them=0A+=20=20;;=20= auto-splicing,=20this=20test=20will=20need=20to=20be=20updated.=0A+=20=20= (rx-let=20((f=20(&rest=20r)=20(or=20r)))=0A+=20=20=20=20(should=20(equal=20= (rx=20(f=20"a"=20nonl))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20"a.")))=0A+=0A+=20=20;;=20Substitution=20is=20done=20in=20= number=20positions.=0A+=20=20(rx-let=20((stars=20(n)=20(=3D=20n=20?*)))=0A= +=20=20=20=20(should=20(equal=20(rx=20(stars=204))=0A+=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20"\\*\\{4\\}")))=0A+=0A+=20=20;;=20= Substitution=20is=20done=20inside=20dotted=20pairs.=0A+=20=20(rx-let=20= ((f=20(x=20y=20z)=20(any=20x=20(y=20.=20z))))=0A+=20=20=20=20(should=20= (equal=20(rx=20(f=20?*=20?a=20?t))=0A+=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20"[*a-t]")))=0A+=0A+=20=20;;=20Substitution=20is=20= done=20in=20the=20head=20position=20of=20forms.=0A+=20=20(rx-let=20((f=20= (x)=20(x=20"a")))=0A+=20=20=20=20(should=20(equal=20(rx=20(f=20+))=0A+=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20"a+"))))=0A+=0A= +(ert-deftest=20rx-define=20()=0A+=20=20(rx--save-definitions=0A+=20=20=20= (rx-define=20a=20(seq=20"x"=20(opt=20"y")))=0A+=20=20=20(should=20(equal=20= (rx=20bol=20a=20eol)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20"^xy?$"))=0A+=20=20=20(rx-define=20bracket=20(lb=20rb=20&rest=20= stuff)=20(seq=20lb=20stuff=20rb))=0A+=20=20=20(should=20(equal=20(rx=20= bol=20(bracket=20"<"=20">"=20a=20nonl)=20eol)=0A+=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20"^$"))=0A+=20=20=20(rx-define=20b=20= (*=20a))=0A+=20=20=20(should=20(equal=20(rx=20b)=0A+=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20"\\(?:xy?\\)*"))=0A+=20=20=20(rx-define=20= a=20"z")=0A+=20=20=20(should=20(equal=20(rx=20b)=0A+=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20"z*"))))=0A+=0A+(ert-deftest=20= rx-let-define=20()=0A+=20=20(rx--save-definitions=0A+=20=20=20(rx-define=20= a=20"one")=0A+=20=20=20(rx-define=20b=20"eins")=0A+=20=20=20(rx-let=20= ((a=20"two"))=0A+=20=20=20=20=20(should=20(equal=20(rx=20a=20nonl=20b)=20= "two.eins"))=0A+=20=20=20=20=20(rx-define=20a=20"three")=0A+=20=20=20=20=20= (should=20(equal=20(rx=20a)=20"two"))=0A+=20=20=20=20=20(rx-define=20b=20= "zwei")=0A+=20=20=20=20=20(should=20(equal=20(rx=20b)=20"zwei")))=0A+=20=20= =20(should=20(equal=20(rx=20a=20nonl=20b)=20"three.zwei"))))=0A+=0A= +(ert-deftest=20rx-let-eval=20()=0A+=20=20(rx-let-eval=20'((a=20(*=20= digit))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(f=20(x=20= &rest=20r)=20(seq=20x=20nonl=20r)))=0A+=20=20=20=20(should=20(equal=20= (rx-to-string=20'(seq=20a=20(f=20bow=20a=20?b))=20t)=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=20"[[:digit:]]*\\<.[[:digit:]]*b"))))=0A+=0A+(ert-deftest=20= rx-constituents=20()=0A+=20=20(let=20((rx-constituents=0A+=20=20=20=20=20= =20=20=20=20(append=20'((beta=20.=20gamma)=0A+=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20(gamma=20.=20"a*b")=0A+=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20(delta=20.=20((lambda=20(form)=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(regexp-quote=20(format=20"<%S>"=20form)))=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= 1=20nil=20symbolp))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20(epsilon=20.=20delta))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20rx-constituents)))=0A+=20=20=20=20(should=20(equal=20= (rx-to-string=20'(seq=20(+=20beta)=20nonl=20gamma)=20t)=0A+=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20"\\(?:a*b\\)+.\\(?:a*b\\)"))=0A= +=20=20=20=20(should=20(equal=20(rx-to-string=20'(seq=20(delta=20a=20b=20= c)=20(*=20(epsilon=20d=20e)))=20t)=0A+=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20"\\(?:<(delta=20a=20b=20c)>\\)\\(?:<(epsilon=20d=20= e)>\\)*"))))=0A=20=0A-(ert-deftest=20rx-seq=20()=0A-=20=20;;=20Test=20= zero-argument=20`seq'.=0A-=20=20(should=20(equal=20(rx=20(seq))=20"")))=0A= -=0A-(defmacro=20rx-tests--match=20(regexp=20string=20&optional=20match)=0A= -=20=20(macroexp-let2=20nil=20strexp=20string=0A-=20=20=20=20`(ert-info=20= ((format=20"Matching=20%S=20to=20%S"=20',regexp=20,strexp))=0A-=20=20=20=20= =20=20=20(should=20(string-match=20,regexp=20,strexp))=0A-=20=20=20=20=20= =20=20,@(when=20match=0A-=20=20=20=20=20=20=20=20=20=20=20`((should=20= (equal=20(match-string=200=20,strexp)=20,match)))))))=0A-=0A= -(ert-deftest=20rx-nonstring-expr=20()=0A-=20=20(let=20((bee=20"b")=0A-=20= =20=20=20=20=20=20=20(vowel=20"[aeiou]"))=0A-=20=20=20=20= (rx-tests--match=20(rx=20"a"=20(literal=20bee)=20"c")=20"abc")=0A-=20=20=20= =20(rx-tests--match=20(rx=20"a"=20(regexp=20bee)=20"c")=20"abc")=0A-=20=20= =20=20(rx-tests--match=20(rx=20"a"=20(or=20(regexp=20bee)=20"xy")=20"c")=20= "abc")=0A-=20=20=20=20(rx-tests--match=20(rx=20"a"=20(or=20"xy"=20= (regexp=20bee))=20"c")=20"abc")=0A-=20=20=20=20(should-not=20= (string-match=20(rx=20(or=20(regexp=20bee)=20"xy"))=20""))=0A-=20=20=20=20= (rx-tests--match=20(rx=20"a"=20(=3D=203=20(regexp=20bee))=20"c")=20= "abbbc")=0A-=20=20=20=20(rx-tests--match=20(rx=20"x"=20(=3D=203=20= (regexp=20vowel))=20"z")=20"xeoez")=0A-=20=20=20=20(should-not=20= (string-match=20(rx=20"x"=20(=3D=203=20(regexp=20vowel))=20"z")=20= "xe[]z"))=0A-=20=20=20=20(rx-tests--match=20(rx=20"x"=20(=3D=203=20= (literal=20vowel))=20"z")=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20"x[aeiou][aeiou][aeiou]z")=0A-=20=20=20=20= (rx-tests--match=20(rx=20"x"=20(repeat=201=20(regexp=20vowel))=20"z")=20= "xaz")=0A-=20=20=20=20(rx-tests--match=20(rx=20"x"=20(repeat=201=202=20= (regexp=20vowel))=20"z")=20"xaz")=0A-=20=20=20=20(rx-tests--match=20(rx=20= "x"=20(repeat=201=202=20(regexp=20vowel))=20"z")=20"xauz")=0A-=20=20=20=20= (rx-tests--match=20(rx=20"x"=20(>=3D=201=20(regexp=20vowel))=20"z")=20= "xaiiz")=0A-=20=20=20=20(rx-tests--match=20(rx=20"x"=20(**=201=202=20= (regexp=20vowel))=20"z")=20"xaiz")=0A-=20=20=20=20(rx-tests--match=20(rx=20= "x"=20(group=20(regexp=20vowel))=20"z")=20"xaz")=0A-=20=20=20=20= (rx-tests--match=20(rx=20"x"=20(group-n=201=20(regexp=20vowel))=20"z")=20= "xaz")=0A-=20=20=20=20(rx-tests--match=20(rx=20"x"=20(?=20(regexp=20= vowel))=20"z")=20"xz")))=0A-=0A-(ert-deftest=20= rx-nonstring-expr-non-greedy=20()=0A-=20=20"`rx's=20greediness=20can't=20= affect=20runtime=20regexp=20parts."=0A-=20=20(let=20((ad-min=20"[ad]*?")=0A= -=20=20=20=20=20=20=20=20(ad-max=20"[ad]*")=0A-=20=20=20=20=20=20=20=20= (ad=20"[ad]"))=0A-=20=20=20=20(rx-tests--match=20(rx=20"c"=20(regexp=20= ad-min)=20"a")=20"cdaaada"=20"cda")=0A-=20=20=20=20(rx-tests--match=20= (rx=20"c"=20(regexp=20ad-max)=20"a")=20"cdaaada"=20"cdaaada")=0A-=20=20=20= =20(rx-tests--match=20(rx=20"c"=20(minimal-match=20(regexp=20ad-max))=20= "a")=20"cdaaada"=20"cdaaada")=0A-=20=20=20=20(rx-tests--match=20(rx=20= "c"=20(maximal-match=20(regexp=20ad-min))=20"a")=20"cdaaada"=20"cda")=0A= -=20=20=20=20(rx-tests--match=20(rx=20"c"=20(minimal-match=20(0+=20= (regexp=20ad)))=20"a")=20"cdaaada"=20"cda")=0A-=20=20=20=20= (rx-tests--match=20(rx=20"c"=20(maximal-match=20(0+=20(regexp=20ad)))=20= "a")=20"cdaaada"=20"cdaaada")))=0A-=0A-(ert-deftest=20= rx-to-string-lisp-forms=20()=0A-=20=20(rx-tests--match=20(rx-to-string=20= '(seq=20"a"=20(literal=20"b")=20"c"))=20"abc")=0A-=20=20(rx-tests--match=20= (rx-to-string=20'(seq=20"a"=20(regexp=20"b")=20"c"))=20"abc"))=0A=20=0A=20= (provide=20'rx-tests)=0A-;;=20rx-tests.el=20ends=20here.=0A--=20=0A= 2.20.1=20(Apple=20Git-117)=0A=0A= --Apple-Mail=_13F108E5-C9EF-4F5C-9D1D-158EFACFAEE4--