Spent some time playing with
perl Switch bug.
Well, let's start from the begging.
The sort of main parsing routine in
Switch.pm is
sub filter_blocks, which tries to parse
$source and create
$text.
failter_blocks calls
Text::Balanced::_match_* to distinguish code blocks
from quoted, to validate variables, etc... and that's the point where the
whole thing hits the fan.
Text::Balanced::_match_variable call is too
early here, since
_match_variable validates
$#,
$$,
$^ and fails to
validate
$). In other words, suppose, we are parsing
sub foo($) {
switch($_[0]) {
case /ACK/i {
return "ACK";
}
case /NACK/i {
return "NACK";
}
}
}
Text::Balanced::_match_variable will return the whole block, since
it doesn't know what to do with
$). Yet it works for
$$,
$,, etc. quite
well. My first solution was change
m{\G\$\s*(?!::)(\d+|[][&`'+*./|,";%=~:?!\@<>()-]|\^[a-z]?)}gci)
to
m{\G\$\)\?\s*(?!::)(\d+|[][&`'+*./|,";%=~:?!\@<>()-]|\^[a-z]?)}gci)
so, we now parse
$) correctly. However, I didn't like it much.
What we (
IMHO) really should do - is to teach
filter_blocks what
subroutine is. I did very simple and general (
which may fail for
some sophisticated cases) thing:
diff --git a/Switch.pm b/Switch.pm
index 2189ae0..781bae8 100755
--- a/Switch.pm
+++ b/Switch.pm
@@ -111,6 +111,11 @@ sub filter_blocks
}
next component;
}
+ if ($source =~ m/\G(\s*sub.+)\{/) {
+ $text .= $1;
+ pos $source += length($1);
+ next component;
+ }
if ($source =~ m/(\G\s*$pod_or_DATA)/gc) {
$text .= $1;
next component;
which shifts position in currently parsed
$source to avoid wrong
Text::Balanced::_match_variable call on subroutine declaration.
Of course, this is not tested at all, except for my simple script.
Just playing.