Perl / perl5

🐪 The Perl programming language
https://dev.perl.org/perl5/
Other
1.91k stars 542 forks source link

/(?{CODE})?/ #5712

Open p5pRT opened 22 years ago

p5pRT commented 22 years ago

Migrated from rt.perl.org#10040 (status was 'open')

Searchable as RT10040$

p5pRT commented 22 years ago

From @abigail

Created by @abigail

  $ perl -wle '/(?{1})?/'

results in

  Quantifier unexpected on zero-length expression in regex;   marked by \<-- HERE in m/(?{1})? \<-- HERE / at -e line 1.

While this is a useful (fatal) error for expressions without side-effects\, it's a nuisance for expressions with side-effects. And doing a (?{ }) without side-effects is kind of useless...

The Perl regex machine is a nice framework to do backtracking with. And then it would be useful to be able to do​:

  (?{ CODE })?

There is a workaround of course​:

  (?​:(?{ CODE })|)

but that's more verbose.

Perl Info ``` Flags: category=core severity=medium Site configuration information for perl v5.8.0: Configured by abigail at Fri Jun 21 18:20:52 CEST 2002. Summary of my perl5 (revision 5.0 version 8 subversion 0 patch 17339) configurat ion: Platform: osname=linux, osvers=2.4.5, archname=i686-linux-64int-ld uname='linux hermione 2.4.5 #6 fri jun 22 01:38:20 pdt 2001 i686 unknown ' config_args='-des -Uversiononly -Dmydomain=.foad.org -Dcf_email=abigail@foad ..org -Dperladmin=abigail@foad.org -Doptimize=-g -Dusemorebits -Dusedevel -Dusenm =false -Darchlib=/opt/perl/5.8.0-RC2/lib/5.8.0-RC2/i686-linux -Dprivlib=/opt/per l/5.8.0-RC2/lib/5.8.0-RC2 -Dman1dir=/opt/perl/5.8.0-RC2/man/man1 -Dman3dir=/opt/ perl/5.8.0-RC2/man/man3 -Dprefix=/opt/perl/5.8.0-RC2' hint=recommended, useposix=true, d_sigaction=define usethreads=undef use5005threads=undef useithreads=undef usemultiplicity=unde f useperlio=define d_sfio=undef uselargefiles=define usesocks=undef use64bitint=define use64bitall=undef uselongdouble=define usemymalloc=n, bincompat5005=undef Compiler: cc='cc', ccflags ='-DDEBUGGING -fno-strict-aliasing -I/usr/local/include -I/ opt/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64', optimize='-g', cppflags='-DDEBUGGING -fno-strict-aliasing -I/usr/local/include -I/opt/local /include' ccversion='', gccversion='2.95.3 20010315 (release)', gccosandvers='' intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=12345678 d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=12 ivtype='long long', ivsize=8, nvtype='long double', nvsize=12, Off_t='off_t' , lseeksize=8 alignbytes=4, prototype=define Linker and Libraries: ld='cc', ldflags =' -L/usr/local/lib -L/opt/local/lib' libpth=/usr/local/lib /opt/local/lib /lib /usr/lib libs=-lnsl -lndbm -lgdbm -ldl -lm -lc -lcrypt -lutil perllibs=-lnsl -ldl -lm -lc -lcrypt -lutil libc=/lib/libc-2.2.3.so, so=so, useshrplib=false, libperl=libperl.a gnulibc_version='2.2.3' Dynamic Linking: dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-rdynamic' cccdlflags='-fpic', lddlflags='-shared -L/usr/local/lib -L/opt/local/lib' Locally applied patches: DEVEL17339 @INC for perl v5.8.0: /home/abigail/Perl /home/abigail/Sybase /opt/perl/5.8.0-RC2/lib/5.8.0-RC2/i686-linux /opt/perl/5.8.0-RC2/lib/5.8.0-RC2 /opt/perl/5.8.0-RC2/lib/site_perl/5.8.0/i686-linux-64int-ld /opt/perl/5.8.0-RC2/lib/site_perl/5.8.0 /opt/perl/5.8.0-RC2/lib/site_perl . Environment for perl v5.8.0: HOME=/home/abigail LANG (unset) LANGUAGE (unset) LC_ALL=POSIX LD_LIBRARY_PATH=/home/abigail/Lib:/usr/local/lib:/usr/lib:/lib:/usr/X11R6/li b:/opt/gnome/lib LOGDIR (unset) PATH=/home/abigail/Bin:/opt/perl/bin:/usr/local/bin:/usr/local/X11/bin:/usr/ bin:/bin:/usr/local/sbin:/usr/sbin:/sbin:/usr/X11R6/bin:/usr/games:/opt/povray/b in:/opt/gnome/bin:/opt/opera/bin:/usr/share/texmf/bin:/opt/Acrobat4/bin:/opt/jav a/blackdown/j2sdk1.3.1/bin:/usr/local/games/bin:/opt/gnuplot/bin:/opt/mysql/bin PERL5LIB=/home/abigail/Perl:/home/abigail/Sybase PERLDIR=/opt/perl PERL_BADLANG (unset) SHELL=/usr/bin/bash ```
p5pRT commented 22 years ago

From @tamias

On Thu\, Jul 11\, 2002 at 09​:50​:28AM -0700\, Abigail wrote​:

$ perl \-wle '/\(?\{1\}\)?/'

results in

Quantifier unexpected on zero\-length expression in regex;
marked by \<\-\- HERE in m/\(?\{1\}\)? \<\-\- HERE / at \-e line 1\.

While this is a useful (fatal) error for expressions without side-effects\, it's a nuisance for expressions with side-effects. And doing a (?{ }) without side-effects is kind of useless...

The Perl regex machine is a nice framework to do backtracking with. And then it would be useful to be able to do​:

\(?\{ CODE \}\)?

There is a workaround of course​:

\(?&#8203;:\(?\{ CODE \}\)|\)

But (?{ }) always succeeds. The only way for (?{ }) to be backtracked is for the surrounding regex to backtrack.

Ronald

p5pRT commented 22 years ago

From @vanstyn

Abigail \abigail@&#8203;foad\.org wrote​: : $ perl -wle '/(?{1})?/' : :results in : : Quantifier unexpected on zero-length expression in regex; : marked by \<-- HERE in m/(?{1})? \<-- HERE / at -e line 1. : : :While this is a useful (fatal) error for expressions without side-effects\, :it's a nuisance for expressions with side-effects. And doing a (?{ }) :without side-effects is kind of useless...

Presumably the only relevant side-effects are the ones that occur under backtracking\, ie rollback of local()ised variables. If I understand you correctly you want to be able to say​:   local $count = 0;   "foobar" =~ m{   (?{ local $count = 1 })?   foo   (??{ $count ? 'baz' : 'bar' })   }; ... and have it match 'foobar' the second time through. Is that right?

Do you have a more concrete example that cannot easily be expressed using the currently supported syntax?

What would you want m/(?{1})*/ to do? The same as C\< 1 while 1 >?

:Flags​: : category=core : severity=medium

As far as I am aware we consciously chose to impose this restriction\, so I'd class this as a wishlist item rather than a bug. If the restriction is underdocumented (which is quite likely)\, then the docs need fixing.

Hugo

p5pRT commented 22 years ago

From @abigail

On Thu\, Jul 11\, 2002 at 01​:10​:27PM -0400\, Ronald J Kimball wrote​:

On Thu\, Jul 11\, 2002 at 09​:50​:28AM -0700\, Abigail wrote​:

$ perl \-wle '/\(?\{1\}\)?/'

results in

Quantifier unexpected on zero\-length expression in regex;
marked by \<\-\- HERE in m/\(?\{1\}\)? \<\-\- HERE / at \-e line 1\.

While this is a useful (fatal) error for expressions without side-effects\, it's a nuisance for expressions with side-effects. And doing a (?{ }) without side-effects is kind of useless...

The Perl regex machine is a nice framework to do backtracking with. And then it would be useful to be able to do​:

\(?\{ CODE \}\)?

There is a workaround of course​:

\(?&#8203;:\(?\{ CODE \}\)|\)

But (?{ }) always succeeds. The only way for (?{ }) to be backtracked is for the surrounding regex to backtrack.

Well\, yes. Consider the following code to generate all combinations of a 4 element set​:

"" =~ /(?{ @​x = qw !A B C D!; @​y = (0) x 4; })   (?​:(?{ local $y [0] = 1 })|)   (?​:(?{ local $y [1] = 1 })|)   (?​:(?{ local $y [2] = 1 })|)   (?​:(?{ local $y [3] = 1 })|)   (?(?{ print "@​x[grep {$y [$_]} 0 .. 3]\n" }) fail )/x;

I'd find it more logical to be able to write it as​:

"" =~ /(?{ @​x = qw !A B C D!; @​y = (0) x 4; })   (?{ local $y [0] = 1 })?   (?{ local $y [1] = 1 })?   (?{ local $y [2] = 1 })?   (?{ local $y [3] = 1 })?   (?(?{ print "@​x[grep {$y [$_]} 0 .. 3]\n" }) fail )/x;

 
as '?' indicates "first try matching\, then try without".  
Abigail

p5pRT commented 22 years ago

From @abigail

On Thu\, Jul 11\, 2002 at 06​:28​:02PM +0100\, Hugo van der Sanden wrote​:

Abigail \abigail@&#8203;foad\.org wrote​: : $ perl -wle '/(?{1})?/' : :results in : : Quantifier unexpected on zero-length expression in regex; : marked by \<-- HERE in m/(?{1})? \<-- HERE / at -e line 1. : : :While this is a useful (fatal) error for expressions without side-effects\, :it's a nuisance for expressions with side-effects. And doing a (?{ }) :without side-effects is kind of useless...

Presumably the only relevant side-effects are the ones that occur under backtracking\, ie rollback of local()ised variables. If I understand you correctly you want to be able to say​: local $count = 0; "foobar" =~ m{ (?{ local $count = 1 })? foo (??{ $count ? 'baz' : 'bar' }) }; .. and have it match 'foobar' the second time through. Is that right?

Yes.

Do you have a more concrete example that cannot easily be expressed using the currently supported syntax?

Well\, as I said\, there's a workaround\, so it's always expressable in the currently supported syntax. But expressing (?{ CODE }){100\,200} as a sequence of | clauses is a bit awkward.

What would you want m/(?{1})*/ to do? The same as C\< 1 while 1 >?

Yes.

Abigail

p5pRT commented 22 years ago

From @vanstyn

Abigail \abigail@&#8203;foad\.org wrote​: :On Thu\, Jul 11\, 2002 at 06​:28​:02PM +0100\, Hugo van der Sanden wrote​: :> Do you have a more concrete example that cannot easily be expressed :> using the currently supported syntax? : :Well\, as I said\, there's a workaround\, so it's always expressable in :the currently supported syntax. But expressing (?{ CODE }){100\,200} :as a sequence of | clauses is a bit awkward.

Hence 'cannot _easily_ be expressed'.

:> What would you want m/(?{1})*/ to do? The same as C\< 1 while 1 >? : :Yes.

I think this is in large part what the current behaviour aims to guard against.

I could imagine supporting this in 5.10 by way of a new switch\, but I do not think it would be wise to change the default behaviour. I would also be tempted to allow any such switch also to turn on the currently disabled backtracking through assertions\, which would allow patterns such as /(?=.*(.))/ to backtrack and find alternate ways of matching the assertion.

Hugo

p5pRT commented 12 years ago

From @iabyn

removing this ticket from the (?{}) metabug\, as its a wishlist rather than a bug