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.
Subscribe to:
Post Comments (Atom)
No comments:
Post a Comment