Beefy Boxes and Bandwidth Generously Provided by pair Networks
Syntactic Confectionery Delight
 
PerlMonks  

Using overload to parse arithmetic terms

by esskar (Deacon)
on Feb 07, 2006 at 12:01 UTC ( #528475=perlquestion: print w/ replies, xml ) Need Help??
esskar has asked for the wisdom of the Perl Monks concerning the following question:

hi,

i wrote a package Foo::Expression::Arithmetic, a package Foo::Number and a package Foo::Variable. I used overload to be able to do the following:
my $x1 = Foo::Number->new()->value( 10 ); my $x2 = Foo::Number->new()->value( 20 ); my $x3 = Foo::Number->new()->value( 30 ); my $x4 = Foo::Number->new()->value( 40 ); my $v1 = Foo::Variable->new()->name( 'a' )->value( 50 ); my $c1 = $v1 - $x1 + $x2 + $x3 - $x4; my $c2 = $c1 * $v1;
$c1 and $c2 are now objects of type Foo::Expression::Arithmetic. Foo::Expression::Arithmetic has a output function, so outputing $c1 and $c2 gives me the following:
a - 10 + 20 + 30 - 40      # $c1
a - 10 + 20 + 30 - 40 * a  # $c2
Now i want to be able to do the following:
my $c3 = ( $x1 + $x2 ) * $v1;
not achieve the following output:
( 10 + 20 ) * a   # $c3
use overload '(' => \&left_parenthesis, ')' => \&right_parenthesis,
is not working. :-( Any ideas?

2006-02-07 Retitled by Arunbear, as per Monastery guidelines
Original title: 'overload'

Comment on Using overload to parse arithmetic terms
Select or Download Code
Re: Using overload to parse arithmetic terms
by Tomte (Priest) on Feb 07, 2006 at 12:30 UTC

    I may be completely mistaken, but IMHO parenthesis aren't things overload can overload - they're at least not mentioned in overload

    To get better qualified help you should specify the code you wrote and mention what exactly "didn't work" in which way- your post is almost in the worst form you can ask such a question: state at least what you did, what you expected and what you got.

    regards,
    tomte


    An intellectual is someone whose mind watches itself.
    -- Albert Camus

      well i, did that:
      use overload '+' => \&add, '-' => \&sub, '*' => \&mul;
      so, i'm able to build a expression that uses +, - and * . Now, i want to be able to detect when the user uses parenthesis as shown above. I know that overload does not support parenthesis, but i hope that somebody has a idea how i can detect those parenthesis.

        Hmm, how do you store the expressions? If you store them as a tree, you already have the information necessary, because you can always generate parenthesis for an <+|->-Node with to children on the fly - that's what I meant with showing relevant code - do you store the expression as a tree - otherwise this is a useless info on my part *g*?


        regards,
        tomte


        An intellectual is someone whose mind watches itself.
        -- Albert Camus

Re: Using overload to parse arithmetic terms
by japhy (Canon) on Feb 07, 2006 at 12:52 UTC
    If you want to output a properly parenthesized mathematical expression, you'll have to do so on the fly, examining the tree that I assume you have in your Arithmetic object. For example, if you have $x = ($a + $b) * $c;, then you probably have a tree like:
    Arithmetic::Multiply( Arithmetic::Add( Variable('a'), Variable('b') ), Variable('c') )
    When you're walking that tree, when you get to a Multiply or Divide node, you have to check to see if its children are Add or Subtract nodes; if they are, those child nodes need to be surrounded by parentheses when output.

    Jeff japhy Pinyan, P.L., P.M., P.O.D, X.S.: Perl, regex, and perl hacker
    How can we ever be the sold short or the cheated, we who for every service have long ago been overpaid? ~~ Meister Eckhart
      To expand (and generalize) on this a bit, let each type of operation have a precedence. Then as you walk the expression tree, you need to parenthesize operations that have a lower precedence than the expression they appear within.

      A good way to do this is via OO, representing your operation types as subclasses:

      package Op; sub new { my $pkg = shift; bless [@_], $pkg; } sub children { @{ $_[0] } } sub display { my ($self, $precedence) = @_; $precedence = 0 if not defined $precedence; my $s = join $self->op, map { $_->display($self->precedence) } $self->children; $s = "($s)" if $precedence > $self->precedence; return $s; } package Op::Addition; @ISA = qw[Op]; sub precedence { 10 } sub op { " + " } package Op::Multiplication; @ISA = qw[Op]; sub precedence { 20 } sub op { " * " } # ... package Op::Term; @ISA = qw[Op]; sub precedence { 100 } sub display { $_[0][0] }
      Then you just call the display method on an Op tree. For example,
      Op::Multiplication->new( Op::Term->new(5), Op::Addition->new( Op::Term->new(6), Op::Term->new(7) ) )->display; # 5 * (6 + 7) Op::Addition->new( Op::Term->new(5), Op::Multiplication->new( Op::Term->new(6), Op::Term->new(7) ) )->display; # 5 + 6 * 7
      And you can see how easy it would be to add new types of operations, due to the beauty of subclassing.

      blokhead

        That is a beautiful approach and technique. ++ well deserved.

        Jeff japhy Pinyan, P.L., P.M., P.O.D, X.S.: Perl, regex, and perl hacker
        How can we ever be the sold short or the cheated, we who for every service have long ago been overpaid? ~~ Meister Eckhart
        perfect ... thanks.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://528475]
Approved by Tomte
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others exploiting the Monastery: (4)
As of 2014-09-20 03:45 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    How do you remember the number of days in each month?











    Results (152 votes), past polls