Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation
 
PerlMonks  

eval, but syntax-check only -- like perl -c

by dpuu (Chaplain)
on Apr 24, 2003 at 17:46 UTC ( [id://252961]=perlquestion: print w/replies, xml ) Need Help??

dpuu has asked for the wisdom of the Perl Monks concerning the following question:

Hi,

I'm writing a script that processes an "executable spec" document that contains embedded code fragments. The script is designed to be a lint tool. I want to extract these fragments, and check that they are valid perl. The extraction part is easy; but how do I check the syntax?

One way to do this is something like

system( qw(perl -c -e), $my_text);
But I was wondering if its possible to do this without the system-call. Basically, I want to call eval($my_text), but I want it to act like it had a -c option (i.e. don't eval, just compile). I can assume there are no "BEGIN" blocks, nor other such nasties that would cause code to be executed during the compile.

Any thoughts? --Dave.

Replies are listed 'Best First'.
Re: eval, but syntax-check only -- like perl -c
by bbfu (Curate) on Apr 24, 2003 at 18:16 UTC

    If you're certain that there will be no code that can execute during the compile (a big assumtion... Have you considered use, modules, etc? How do you ensure it?), then why not just something like this:

    $code = 'whatever'; eval qq(return 1; $code); if($@) { chomp($@); print "Syntax error: `$@'\n"; } else { print "Syntax ok\n"; }

    bbfu
    Black flowers blossom
    Fearless on my breath

Re: eval, but syntax-check only -- like perl -c
by bluto (Curate) on Apr 24, 2003 at 18:19 UTC
    Will wrapping this in a non-executable construct work for you ...
    my $snippet = ... eval "if (0) { $snippet }"; die if $@;
    It *seems* to work.

    bluto

Re: eval, but syntax-check only -- like perl -c
by particle (Vicar) on Apr 24, 2003 at 19:42 UTC

    why run without the external call? without your reasoning, it's hard for me to see why any of the solutions posted so far are better... they're full of caveats. if you use File::Temp and perl -c the file, it will work, and can even be configured to clean up after itself. to a user, it should look the same, except it's probably less of a maintenance headache.

    ~Particle *accelerates*

      I guess there's nothing particularly wrong with the system call: indeed, in some ways it works better. For example, "use strict" doesn't work inside an eval.

      One of the nice things about the 'eval "sub { $txt }"' approach is that it gives me a code ref that I can call later if I want. This means that I can have a two-pass approach: in the first I gather/check all my fragments; and in the second I run selected ones. This isn't my current plan, but is nice to have the flexibility.

      --Dave

        there's room for that here, as well. create a hash with nice names as keys, and filehandles or filenames or the code snippets themselves as values. you still have the two-pass approach, but if you write to disk and keep the filehandles or filenames around, you can always slurp them in quickly to run them. heck, you can do with them what you will.

        ~Particle *accelerates*

Re: eval, but syntax-check only -- like perl -c
by vladb (Vicar) on Apr 24, 2003 at 18:16 UTC
    What if you try embedding your code snippets inside a subroutine and doing eval on that? This would not cause the code to execute and would give you various warning messages (by inspecting the $@ variable) that you may be looking for?

    Update: Missed bbfu's reply, but essentially that's what I was trying to say here ;-)

    _____________________
    # Under Construction
Re: eval, but syntax-check only -- like perl -c
by dpuu (Chaplain) on Apr 24, 2003 at 18:57 UTC
    Thanks all: I think I'll go with wrapping it in an anonymous sub -- eval will then return something that I can actually run, later, if I want. I'll probably run some rexen on the code to ensure it doesn't contain things like "BEGIN", "CHECK", "use" or named-sub defns. If I overly constrain, then someone will complain and I can fix it later. --Dave
      You're probably aware of this already, but there will still be ways for sneaky programmers to get around restrictions like that. For instance:
      my @backward_chars = ('e', 's', 'u'); my $watch_out = (reverse join "",@backward_chars) . " Data::Dumper;"; eval $watch_out; my $x = Dumper([1,2,3]); print $x;

      I've managed to use Data::Dumper without "use" every appearing explicitly in the code.

      Update: D'oh, I forgot to consider the all-important "wrap in an anonymous subroutine" part, which would seem to defer actual execution of the code. My bad.

              $perlmonks{seattlejohn} = 'John Clyman';

Re: eval, but syntax-check only -- like perl -c
by eduardo (Curate) on Apr 24, 2003 at 18:05 UTC

    UPDATE: on second thought, I can't figure out how you would use B::Deparse intelligently, so don't pay much attention to my post :)

    As far as I can tell, as you probably know, only perl can parse Perl. You might have a good shot at trying to use something crazy like B::Deparse (look in the USING B::Deparse AS A MODULE section), but even that's not going to successfully figure out the syntax of "all of perl."

    Unless one of the considerably more knowledgable monks corrects me, and I hope they do, you are pretty much stuck with "perl -c" (though I would usually do "perl -wc" :)

      There are intelligent ways to use B::Deparse but none of them apply to checking perl for syntactical correctness. The canonically correct way is to invoke the parser somehow whether through eval "sub { $code }" or through perl -c tempfile.txt.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://252961]
Approved by The Mad Hatter
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: (2)
As of 2024-04-26 00:25 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found