Beefy Boxes and Bandwidth Generously Provided by pair Networks
Clear questions and runnable code
get the best and fastest answer
 
PerlMonks  

Re: Help Debug Switch.pm!

by btrott (Parson)
on Apr 23, 2001 at 10:35 UTC ( [id://74645]=note: print w/replies, xml ) Need Help??


in reply to Help Debug Switch.pm!

Okay, I went through and did some debugging. I'm running in 5.005_03, like you, so I got the same error. I stepped through the code using print statements, and it looks like the error is basically that, in Switch.pm, when the filter is running over the program source, it can't find any case statements.

Which means that the source isn't getting filtered properly, and so the filtered source ends up with the same case statements that are in your original source--but case isn't a valid Perl bareword, so that's why you get that error.

But that's simply the symptom, really.

The *real* problem is this: Text::Balanced::_match_quotelike is being called, and it matches from the first '?' to the last (the one in the comment), and it sees that as a valid regex. In case this doesn't quite make sense, it sees this:

? 'foo' : 'bar'; switch('x'){ case 'y' {print "y\n"} else {print "x\n"} } # ?
Question marks ('?') are valid regex delimiters; valid in the sense that you don't need a 'm' in front of them. They're like '/'. You can just say:
if ($foo =~ ?bar?)
That's legal.

Here's a runthrough of what's going on, essentially; it makes the most sense if you follow along in the original source.

  • Switch.pm receives your program source, which looks like this:
    my $x = 2 ? 'foo' : 'bar'; switch('x'){ case 'y' {print "y\n"} else {print "x\n"} } # ?
    It steps through that source, matching against regular expressions, in the form /\Gpattern/gc. This means that each time the regex engine tries to do a match, it starts in the source string *after* the last successful match. So using pos, I tried to figure out what it was doing.

  • The first match is at the end of the lexing loop. It's supposed to match what looks like whitespace followed by non-whitespace, and it matches this:
    my
    That's three characters: a newline, then 'my'. (I realize it's hard to see the newline. :) This puts pos at 3.
  • The next thing it matches is done using Text::Balanced::_match_variable, and it matches:
    $x
    Which is also three characters: a space, then '$x'. This puts pos at 6.
  • After this we go through a few other match attempts, then are back down to the non-whitespace followed by whitespace, which matches:
    =
    Which is two chars: a space, followed by '='. This puts pos at 8.
  • Go through again, get back to non-whitespace followed by whitespace. We match:
    2
    Which is two chars: a space, then '2'. This puts pos at 10.
  • All of this matching is going on in a loop, and each time through the loop we're trying to match against a bunch of other things, as well. One rather important thing is each time we try to match switch/case statements. We haven't done so yet, because we've been doing other things. :)

    We've also been trying to match "things that look like quotes", using Text::Balanced::_match_quotelike. Nothing has matched yet, but the next time we go through, we do:

    In _match_quotelike we first match the '$pre' condition, which is optional whitespace. This moves pos to 11. The next thing in the string is '?': _match_quotelike looks at this and enters an if condition, looking to see if this could be a regex match. It looks to see if there's another '?' in the string--and there is! It's hidden in a comment, but _match_quotelike doesn't notice, and so the "quote" matched is:

    ? 'foo' : 'bar'; switch('x'){ case 'y' {print "y\n"} else {print "x\n"} } # ?
    This puts pos at 124. _match_quotelike returns this match, and this puts us at the end of the string: we're done.
  • Since we're done, that means we didn't match any of the switch/case statements, which means that they got through unfiltered. They get passed directly to Perl, which doesn't like them, hence the error.
So this is my theory/observation on what's happening. I haven't checked yet on 5.6 to see why it's working there; I really have no idea why.

But it seems to fit pretty well.

UPDATE: I just tested this on Perl 5.6.0, and I got errors there, as well. So it looks like it's matching in 5.6.0 as a '?'-delimited regex as well. The error is slighty different:

syntax error at t.pl line 9, near "){" String found where operator expected at t.pl line 10, near "case 'y'" (Do you need to predeclare case?) Execution of t.pl aborted due to compilation errors.
But it's certainly the same idea: it doesn't understand what either switch or case is, which means that they didn't get filtered properly. And stepping through using the same debugging statements shows me that it's matching the same things in 5.005_03 as in 5.6.0.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://74645]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others making s'mores by the fire in the courtyard of the Monastery: (6)
As of 2024-03-28 12:14 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found