#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; } }; 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; }