The path of least resistance as a developer is to just eval the string, letting Perl do the work. But that can be fraught with peril if the input is not completely under your control and known to be syntactically sound, and free from bad behavior. Here's an example:

while( <DATA> ) { chomp; print "( $_ ) = ( ", eval($_), " )\n"; }

But this is almost certainly a bad idea, since your data could contain any arbitrary Perl code -- and we all know how much trouble one can get into with arbitrary Perl code.

So the developer seeking the path of least resistance might then think to gravitate toward the Safe module. Using that module one can cherry-pick those operations that are to be considered well-behaved and benign enough to allow for their execution; a constrained subset of arbitrary user code. And that code is executed in a sort of sand box that minimizes its ability to interact with the underlying system. Safe seems like a fairly safe approach.

But it's really going in the wrong direction. The end goal isn't to get perl to parse and execute a safe subset of Perl. The goal is for your script to parse, comprehend, and evaluate mathematical equations. This is one of those things that every first-year CS student takes on at one point or another. A minimal implementation is discussed within the first couple of chapters in SICP. MJD works his reader through a simple implementation early-on in Higher Order Perl. There may be (though I don't remember for sure) a discussion of an implementation in Mastering Algorithms with Perl, as well. The trick is to tokenize, parse into a tree, and traverse the tree while applying the appropriate operators to the appropriate factors.

While this isn't terribly complex, it's not really worth doing all over again unless you're trying to learn how to do it. It's been done a million times before. And as it turns out, there's at least one (and probably many) solutions on CPAN. One I noticed is authored by mortiz: Math::Expression::Evaluator. This module provides a simple interface to a set of black boxes that do all of the work for you. Here is an example:

use Math::Expression::Evaluator; while( <DATA> ) { chomp; my $m = Math::Expression::Evaluator->new; eval { my $p = $m->parse($_); print "( $_ ) = ( ", $p->val, " )\n"; 1; } or warn "Unable to resolve expression ($_).\n"; } __DATA__ 1+2 1 + 2 2 * 2 + 4 asdf#@fg

When you run that, you get:

( 1+2 ) = ( 3 ) ( 1 + 2 ) = ( 3 ) ( 2 * 2 + 4 ) = ( 8 ) Unable to resolve expression (asdf#@fg).

No need to implement your own, no need to deal with string eval, or Safe. Done. ;)


Dave


In reply to Re: converting from str to int by davido
in thread converting from str to int by Anonymous Monk

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.