Richard Smith
Richard Smith

Reputation: 3454

Whitespace with perl Switch module

The following trivially short perl program works fine (and does nothing, as expected):

use Switch;
switch (1) {}

However if I put the program on one line, as follows,

use Switch; switch (1) {}

I get an error

richard@affric:~$ perl foo.pl
syntax error at foo.pl line 1, near ") {"
Execution of foo.pl aborted due to compilation errors.

Can anyone explain this to me?

(Edit: Yes, I know Switch.pm is deprecated, and, yes, I know that the code is more readable with the line break.)

Upvotes: 0

Views: 92

Answers (1)

Borodin
Borodin

Reputation: 126742

The Switch module is written as a Perl filter, which essentially means that the Switch module gets to see and make changes to the source code before the perl parser gets it.

I believe what you're seeing here is just a bug in the filter. If you use the backend B::Deparse module then you get a chance to see what nasty things Switch has done to your program. For instance, for your initial version

perl -MO=Deparse myswitch.pl

produces

use Switch;

S_W_I_T_C_H: while (1) {
    local $_S_W_I_T_C_H;
    &Switch::switch(1);
}
continue {
    (last);
}

so you can see that there is plenty of scope for error.

If I had to guess I would say that Switch is simply expecting all of the line starting use Switch to contain module options and nothing else. If you use the -M switch to include the module, like this

perl -MO=Deparse -MSwitch -E'switch (1) { }'

then the result is this

use Switch;
S_W_I_T_C_H: while (1) {
    local $_S_W_I_T_C_H;
    &Switch::switch(1);
}
continue {
    last;
}
-e syntax OK

which is different in that neither a compile time nor a run time error is raised.


Update

The problem seems to be an issue with the Filter::Util::Call module, on which Switch is based. The problem is that the text that this module passes to source filters begins only on the line following the use Switch statement. Anything after it on the same line is processed directly by the perl parser as normal.

That means that, in your second case, perl is seeing the (unmodified) program switch (1) {} while Switch has nothing to do as there is no code at all after this line to be filtered.

I think this is highly likely to be an inherent part of perl, and there is no way to intercept the source stream in the mid-line. But it's a non-critical bug and, now that you know the cause, you should be able to work around it easily.

Upvotes: 3

Related Questions