#ifndef __STRING_EXPRESSION_H__
#define __STRING_EXPRESSION_H__

#include <map>
#include <string>
#include <sstream>
using namespace std;

#include "Program.h"

extern Program program;

/**
 *   Bazna klasa za sve izraze
 */
class StringExpression {
 public:
    virtual ~StringExpression() {}    

    /**
     *   Metoda kojom se izracunava vrednost izraza
     */
    virtual string value() = 0;
};

/**
 *   Klasa kojom se predstavljaju string literali ("....")
 */
class StringLiteral : public StringExpression {
 public:
    StringLiteral(string argument) 
	: _argument(argument) {
    }

    virtual string value() {
	return _argument;
    }
 private:
    string _argument;
};

/**
 *   Klasa kojom se predstavlja operacija konkatenacije
 */
class Plus : public StringExpression {
 public:
    Plus(StringExpression* op1, StringExpression* op2) 
	: _op1(op1), _op2(op2) {
    }

    ~Plus() {
	delete _op1;
	delete _op2;
    }

    virtual string value() {
	return _op1->value() + _op2->value();
    }

 private:
    StringExpression *_op1, *_op2;
};


/**
 *   Klasa kojom se predstavljaju string promenljive (var$)
 */
class StringVar : public StringExpression {
 public:
    StringVar(string var) 
	: _var(var) {
    }

    virtual string value() {
	return program.getStringVar(_var);
    }

 private:
    string _var;
};

/**
 *   Klasa kojom se predstavljaju int promenljive (var)
 */
class IntVar : public StringExpression {
 public:
    IntVar(string var) 
	: _var(var) {
    }

    virtual string value() {
	    ostringstream stream;
	    stream << program.getIntVar(_var);
	    return stream.str();
    }

 private:
    string _var;
};

/**
 *   Klasa predstavlja operaciju izdvajanja sufiksa (right$)
 */
class Right : public StringExpression {
 public:
    Right(StringExpression* op, int num) 
	: _op(op), _num(num) {
    }

    ~Right() {
	delete _op;
    }

    virtual string value() {
	string value = _op->value();
	return value.substr(value.size() - _num);
    }

 private:
    StringExpression* _op;
    int _num;
};

/**
 *   Klasa predstavlja operaciju izdvajanja prefiksa (left$)
 */
class Left : public StringExpression {
 public:
    Left(StringExpression* op, int num) 
	: _op(op), _num(num) {
    }

    ~Left() {
	delete _op;
    }

    virtual string value() {
	return _op->value().substr(0, _num);
    }

 private:
    StringExpression* _op;
    int _num;
};

#endif
