powerman has asked for the wisdom of the Perl Monks concerning the following question:

Is it safe to use die() or croak() in regexp with eval?
$a="qwe"; $a =~ s/(\w)/ $1 ne "w" ? $1 : croak "w is bad" /ge;
It's working, but I'm unable to find any notes in documentation about is it legal and safe. AFAIK die working like longjmp() in C, and I've no idea what can be broken in regular expression engine if I leave it with longjmp().

Replies are listed 'Best First'.
Re: die in regexp
by dave_the_m (Monsignor) on Jul 03, 2006 at 20:49 UTC
    die, anonymous subs and accessing outer lexical vars, within re_evals are all currently very broken (in the sense that they may randomly coredump). Its something I'm still hoping to fix in time for 5.10.

    Dave.

      Uh, his example is not inside a re_eval, is it? I assume that by that you mean (?{...}) and similar constructs inside the regex. (perldebguts talks about "code assertions in regexes", but that's about all I could find about them.)

      The right hand side of a substitution is not inside the regex.

      This piece of code doesn't mention "re_eval" in its error message:

      s/foo/die/e;
      It just says
      Died at test.pl line 3.

      I believe die is safe, there.

        Uh, his example is not inside a re_eval, is it?
        Ugh, that's what happens when reading web sites while having a cold :-(. Yes, I got completely the wrong end of the stick! die is safe in s//die/e.

        Dave.

      Thanks!
Re: die in regexp
by davidrw (Prior) on Jul 03, 2006 at 19:17 UTC
    i don't know, but you could avoid the issue w/something like (esp since you're not modifying the string, so no point in a substitution):
    my $s = "qwe"; croak "w is bad" if $s =~ /w/; # croak if the string contains a w # OR, faster: croak "w is bad" if index($s,'w') >= 0;
    (don't use $a or $b as a varname -- it's a global var for sort)
      I know how I can avoid this issue. :-) I don't know is I should avoid it. :) Also, I can't avoid it so ease - I need to do s/// in some complex template, and I wish to detect errors in this template. Example with "qwe" can be converted to simple m//, but not my real task. My real task can be converted to something like:
      while (1) { $tmpl =~ /\G(...)/gcs && do { if ($1 eq "w") { croak "w is bad"; } else { $result .= process_template($1); } } || $tmpl =~ /\G(...)/gcs && do { ...do.something.else... } || last; }
      You see, it's too complex to replace current single-line s/// just to be able to croak() on errors. :(
        My real task can be converted to something like

        ...this?

        use Tie::IxHash; tie my %dt, 'Tie::IxHash', qr/one/ => \&handle_one, qr/two/ => \&handle_two; my $c="trigger one trigger two"; sub handle_one { print "one: ", shift, "\n"; } sub handle_two { print "two: ", shift, "\n"; } foreach (keys %dt) { $c =~ /\G.+?($_)/gcs and $dt{$_}->($1); }

        --
        David Serrano

Re: die in regexp
by Moron (Curate) on Jul 04, 2006 at 09:09 UTC
    croak or die doesn't need to know the context in which it was called and it's going to exit anyway so in this context it doesn't seem any different from any other die, (if you'll excuse the pun), although it is a good habit to place brackets after function calls when they are used in any ambiguous 'literal vs. function' context such as this.

    Therefore, to open the can of worms a little wider, consider whether loop control can reasonably be put in there, e.g. the following also worked as "expected" when I tested it on 5.6.1:

    while(<>) { s/^\s*(\S)/$1 ne "#" ? $1 : next()/ge; # process non-comment line }
    Update: And just how far can we take it? Can we define a sub in there? declare a variable with my? Or should we assume that anything not found in the documentation is unsupported. Personally I think it is better to document in a reliable context such as this can be proved to be.

    -M

    Free your mind

Re: die in regexp
by ruoso (Curate) on Jul 04, 2006 at 17:21 UTC

    For complex parsings, it's easier to use Perl 6 Rules than simple regexes... Fortunally, this rules are implemented in Perl 5 already... See Pugs::Compiler::Rule... It's really fantastic.

    daniel