### Using overload to parse arithmetic terms

by esskar (Deacon)
 on Feb 07, 2006 at 12:01 UTC 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

Replies are listed 'Best First'.
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(
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;
}

@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::Term->new(6),
Op::Term->new(7)
)
)->display;
# 5 * (6 + 7)

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.

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.
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
'-' => \&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

Create A New User
Node Status?
node history
Node Type: perlquestion [id://528475]
Approved by Tomte
help
Chatterbox?
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others taking refuge in the Monastery: (2)
As of 2018-05-23 02:18 GMT
Sections?
Information?
Find Nodes?
Leftovers?
Voting Booth?
World peace can best be achieved by:

Results (166 votes). Check out past polls.

Notices?