#include #include #include using namespace std; class Okolina { public: double VrednostPromenljive( const string& s ) const { map::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::const_iterator f = _Promenljive.find(s); return f != _Promenljive.end(); } void DodajPromenljivu( const string& s, double v ) { _Promenljive[s] = v; } private: map _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; }