#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; }
virtual Izraz* IzvodPo( const string& s ) const = 0;
static Izraz* Procitaj( istream& istr );
};
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; }
Izraz* IzvodPo( const string& s ) const
{ return new Konstanta(0); }
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();
}
Izraz* IzvodPo( const string& s ) const
{ return new Konstanta( s==_Naziv ? 1 : 0); }
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;
const Izraz* Levi() const
{ return _I1; }
const Izraz* Desni() const
{ return _I2; }
private:
Izraz *_I1, *_I2;
};
class Zbir : public BinarniOperator
{
public:
Zbir( Izraz* i1, Izraz* i2 )
: BinarniOperator( i1, i2 )
{}
Zbir* Kopija() const
{ return new Zbir(*this); }
Izraz* IzvodPo( const string& s ) const
{ return new Zbir( Levi()->IzvodPo(s), Desni()->IzvodPo(s)); }
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); }
Izraz* IzvodPo( const string& s ) const
{ return new Razlika( Levi()->IzvodPo(s), Desni()->IzvodPo(s)); }
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); }
Izraz* IzvodPo( const string& s ) const
{
return new Zbir(
new Proizvod( Levi()->IzvodPo(s), Desni()->Kopija() ),
new Proizvod( Levi()->Kopija(), Desni()->IzvodPo(s))
);
}
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); }
Izraz* IzvodPo( const string& s ) const
{
return
new Kolicnik(
new Razlika(
new Proizvod( Levi()->IzvodPo(s), Desni()->Kopija() ),
new Proizvod( Levi()->Kopija(), Desni()->IzvodPo(s))
),
new Proizvod(
Desni()->Kopija(),
Desni()->Kopija()
)
);
}
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"; }
};
Izraz* Izraz::Procitaj( istream& istr )
{
Izraz* i = 0;
istr >> ws;
char c = istr.peek();
if( c == '(' ){
istr.get();
string op;
istr >> ws >> op;
Izraz* op1 = Procitaj( istr );
Izraz* op2 = Procitaj( istr );
if( op1 && op2 ){
if( op=="PLUS" )
i = new Zbir( op1, op2 );
else if( op=="MINUS" )
i = new Razlika( op1, op2 );
else if( op=="PUTA" )
i = new Proizvod( op1, op2 );
else if( op=="PODELJENO" )
i = new Kolicnik( op1, op2 );
}
if( !i ){
delete op1;
delete op2;
}
istr >> ws;
istr.get();
}else if( (c>='a' && c<='z') || (c>='A' && c<='Z') ){
string s;
istr >> s;
if( istr )
i = new Promenljiva(s);
}else{
double f;
istr >> f;
if( istr )
i = new Konstanta(f);
}
return i;
}
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;
Izraz* i6 = i4->IzvodPo("x");
Izraz* i7 = i6->Uprosti(o);
cout << (*i4) << " ' = " << (*i6) << " = " << *i7 << endl;
delete i4;
delete i5;
delete i6;
delete i7;
*/
Izraz* i = Izraz::Procitaj( cin );
Izraz* iz = i->IzvodPo("x");
Izraz* u = iz->Uprosti(o);
cout << (*i) << " ' = " << (*iz) << " = " << *u << endl;
delete u;
delete iz;
delete i;
return 0;
}