#include <iostream>
#include <string>
#include <map>

using namespace std;

// Wyrażenia //////////////////////////////////////////////////////

typedef map<string, int> Memory;

class Expression
{
  public:
    virtual int eval(Memory& m) = 0;
};

class Constant : public Expression
{
    int value;

  public:
    Constant(int v) : value(v) {}

    virtual int eval(Memory& m)
    {
      return value;
    }
};

class Unknown_operator { };

class Binary_operator : public Expression
{
    char symbol;
    Expression* left, * right;

  public:
    Binary_operator(char s, Expression* l, Expression* r)
      : symbol(s), left(l), right(r) {}

    virtual int eval(Memory& m)
    {
      switch (symbol)
      {
        case '*': return left->eval(m) * right->eval(m);
        case '+': return left->eval(m) + right->eval(m);
        case '-': return left->eval(m) - right->eval(m);
        case '/': return left->eval(m) / right->eval(m);
        case '%': return left->eval(m) % right->eval(m);
        default : throw Unknown_operator();
      }
    }
};

class Variable_not_found { };

class Variable : public Expression
{
    string name;

  public:
    Variable(string n) : name(n) { }
  
    virtual int eval(Memory& m)
    {
      Memory::iterator it = m.find(name);
      if (it == m.end())
        throw Variable_not_found();
      return it->second;
    }
};

// Main /////////////////////////////////////////////////////////////

int main()
{
  Memory m;

  Expression* f = new Binary_operator('+', new Constant(2),
    new Binary_operator('*',
      new Binary_operator('+', new Constant(1), new Constant(7)),
      new Binary_operator('*', new Constant(4), new Constant(5))));

  cout << "2 + (1 + 7) * (4 * 5) = " << f->eval(m) << endl;


  Expression* e = new Binary_operator('+',
    new Binary_operator('*', new Constant(2), new Variable("x")),
    new Variable("y"));

  m["x"] = 10;
  m["y"] = 5;
  
  cout << "2 * x + y (gdzie x = 10, y = 5) = " << e->eval(m) << endl;


  return 0;
}

