package MyRegexStuff; use strict; use warnings; use overload; sub import { overload::constant('qr' => \&MungeRegexLiteral) } my $NestedStuffRegex; # This should be predeclared, because it's used in its own definition. $NestedStuffRegex = qr{ (?> (?: # Stuff not parens, not '#', and not an escape . . . [^()\#\\]+ # Escaped stuff . . . | (?s: \\. ) # Regex comment . . . | \#.*\n # Matching parens, with more nested stuff inside . . . | \( (??{ $NestedStuffRegex }) \) )* ) }x; sub SimpleConvert($); # This must be predeclared, as it's used recursively sub SimpleConvert($) { my $re = shift; # Regex to mangle $re =~ s{ \(\? # "(?" < ( (?>\w+) ) > # < $1 > $1 is an identifier ( $NestedStuffRegex ) # $2 - possibly-nested stuff \) # ")" }{ my $id = $1; my $guts = SimpleConvert($2); # We change # (?guts) # to # (?: (guts) # match the guts # (?{ # local($^N{$id}) = $guts # Save to a localized element of %^T # }) # ) "(?:($guts)(?{ local(\$^T{'$id'}) = \$^N }))" }xeog; return $re; # Return mangled regex } sub MungeRegexLiteral($) { my ($RegexLiteral) = @_; # Argument is a string # print "BEFORE: $RegexLiteral\n"; # Uncomment this for debugging my $new = SimpleConvert($RegexLiteral); if ($new ne $RegexLiteral) { my $before = q/(?{ local(%^T) = () })/; # Localize temporary hash my $after = q/(?{ %^N = %^T })/; # Copy temp to "real" hash $RegexLiteral = "$before(?:$new)$after"; } # print "AFTER: $RegexLiteral\n"; # Uncomment this for debugging return $RegexLiteral; } 1; ----------------------------------------------------------------------------- Copyright 1997-2024 Jeffrey Friedl