#include <string>
#include <map>
#include <iostream>
using namespace std;
class Okolina
{
public:
double VrednostPromenljive( const string& s ) const
{
map<string,double>::const_iterator
f = _Promenljive.find(s);
if( f != _Promenljive.end() )
return f->second;
else{
// ovde bi trebalo da se napravi izuzetak
return 0;
}
}
bool DefinisanaPromenljiva( const string& s ) const
{
map<string,double>::const_iterator
f = _Promenljive.find(s);
return f != _Promenljive.end();
}
void DodajPromenljivu( const string& s, double v )
{ _Promenljive[s] = v; }
private:
map<string,double> _Promenljive;
};
class Izraz
{
public:
virtual ~Izraz()
{}
virtual double Vrednost( const Okolina& o ) const = 0;
virtual void Ispisi( ostream& ostr ) const = 0;
virtual Izraz* Kopija() const = 0;
virtual Izraz* Uprosti( const Okolina& o ) const = 0;
virtual bool JesteKonstanta() const
{ return false; }
};
ostream& operator << ( ostream& ostr, const Izraz& i )
{
i.Ispisi( ostr );
return ostr;
}
class Konstanta : public Izraz
{
public:
Konstanta( double d )
: _Vrednost(d)
{}
double Vrednost( const Okolina& o ) const
{ return _Vrednost; }
void Ispisi( ostream& ostr ) const
{ ostr << _Vrednost; }
Konstanta* Kopija() const
{ return new Konstanta(*this); }
Izraz* Uprosti( const Okolina& o ) const
{ return Kopija(); }
bool JesteKonstanta() const
{ return true; }
private:
double _Vrednost;
};
class Promenljiva : public Izraz
{
public:
Promenljiva( const string& s )
: _Naziv(s)
{}
double Vrednost( const Okolina& o ) const
{ return o.VrednostPromenljive( _Naziv ); }
void Ispisi( ostream& ostr ) const
{ ostr << _Naziv; }
Promenljiva* Kopija() const
{ return new Promenljiva(*this); }
Izraz* Uprosti( const Okolina& o ) const
{
if( o.DefinisanaPromenljiva(_Naziv) )
return new Konstanta( o.VrednostPromenljive(_Naziv));
else
return Kopija();
}
private:
string _Naziv;
};
class BinarniOperator : public Izraz
{
public:
BinarniOperator( Izraz* i1, Izraz* i2 )
: _I1(i1), _I2(i2)
{}
~BinarniOperator()
{
delete _I1;
delete _I2;
}
BinarniOperator( const BinarniOperator& z )
: _I1( z._I1->Kopija() ),
_I2( z._I2->Kopija() )
{}
BinarniOperator& operator = ( const BinarniOperator& z )
{
if( this != &z ){
delete _I1;
delete _I2;
_I1 = z._I1->Kopija();
_I2 = z._I2->Kopija();
}
return *this;
}
double Vrednost( const Okolina& o ) const
{ return Izracunaj( _I1->Vrednost(o), _I2->Vrednost(o)); }
Izraz* Uprosti( const Okolina& o ) const
{
Izraz* i1 = _I1->Uprosti(o);
Izraz* i2 = _I2->Uprosti(o);
if( i1->JesteKonstanta() && i2->JesteKonstanta() ){
Izraz* r = new Konstanta( Izracunaj( i1->Vrednost(o), i2->Vrednost(o)) );
delete i1;
delete i2;
return r;
}
else
return NapraviNovi( i1, i2 );
}
void Ispisi( ostream& ostr ) const
{ ostr << "( " << Naziv() << ' ' << *_I1 << ' ' << *_I2 << " )"; }
protected:
virtual double Izracunaj( double x, double y ) const = 0;
virtual Izraz* NapraviNovi( Izraz* i1, Izraz* i2 ) const = 0;
virtual string Naziv() const = 0;
private:
Izraz *_I1, *_I2;
};
class Zbir : public BinarniOperator
{
public:
Zbir( Izraz* i1, Izraz* i2 )
: BinarniOperator( i1, i2 )
{}
Zbir* Kopija() const
{ return new Zbir(*this); }
protected:
double Izracunaj( double x, double y ) const
{ return x + y; }
Izraz* NapraviNovi( Izraz* i1, Izraz* i2 ) const
{ return new Zbir( i1, i2 ); }
string Naziv() const
{ return "PLUS"; }
};
class Razlika : public BinarniOperator
{
public:
Razlika( Izraz* i1, Izraz* i2 )
: BinarniOperator( i1, i2 )
{}
Razlika* Kopija() const
{ return new Razlika(*this); }
protected:
double Izracunaj( double x, double y ) const
{ return x - y; }
Izraz* NapraviNovi( Izraz* i1, Izraz* i2 ) const
{ return new Razlika( i1, i2 ); }
string Naziv() const
{ return "MINUS"; }
};
class Proizvod : public BinarniOperator
{
public:
Proizvod( Izraz* i1, Izraz* i2 )
: BinarniOperator( i1, i2 )
{}
Proizvod* Kopija() const
{ return new Proizvod(*this); }
protected:
double Izracunaj( double x, double y ) const
{ return x * y; }
Izraz* NapraviNovi( Izraz* i1, Izraz* i2 ) const
{ return new Proizvod( i1, i2 ); }
string Naziv() const
{ return "PUTA"; }
};
class Kolicnik : public BinarniOperator
{
public:
Kolicnik( Izraz* i1, Izraz* i2 )
: BinarniOperator( i1, i2 )
{}
Kolicnik* Kopija() const
{ return new Kolicnik(*this); }
protected:
double Izracunaj( double x, double y ) const
{ return x / y; }
Izraz* NapraviNovi( Izraz* i1, Izraz* i2 ) const
{ return new Kolicnik( i1, i2 ); }
string Naziv() const
{ return "PODELJENO"; }
};
main()
{
Okolina o;
o.DodajPromenljivu( "x", 5 );
// izraz (x/2)+(y-(3.14*z))
Izraz* i1 = new Kolicnik( new Promenljiva("x"), new Konstanta(2));
Izraz* i2 = new Proizvod( new Konstanta(3.14), new Promenljiva("z"));
Izraz* i3 = new Razlika( new Promenljiva("y"), i2 );
Izraz* i4 = new Zbir( i1, i3 );
cout << (*i4) << " = " << i4->Vrednost( o ) << endl;
Izraz* i5 = i4->Uprosti(o);
cout << (*i4) << " -> " << (*i5) << endl;
delete i4;
delete i5;
return 0;
}