Solution: Arithmetic Expression Interpreter

#pragma once

#include <string>
#include <map>


class Context
{
public:
    int get(const std::string& name) const;
    void set(const std::string& name, int value);

private:
    std::map<std::string, int> _variables;
};

class Expression
{
public:
    virtual ~Expression() {}
    virtual int evaluate() = 0;
};

class Literal : public Expression
{
public:
    Literal(int value) : _value(value) {}
    int evaluate() override;

private:
    int _value;
};

class Addition : public Expression
{
public:
    Addition(Expression& lhs, Expression& rhs)
    : _lhs(lhs), _rhs(rhs) {}

    int evaluate() override;

private:
    Expression& _lhs;
    Expression& _rhs;
};

class Subtraction : public Expression
{
public:
    Subtraction(Expression& lhs, Expression& rhs)
    : _lhs(lhs), _rhs(rhs) {}

    int evaluate() override;

private:
    Expression& _lhs;
    Expression& _rhs;
};

class Multiplication : public Expression
{
public:
    Multiplication(Expression& lhs, Expression& rhs)
    : _lhs(lhs), _rhs(rhs) {}

    int evaluate() override;

private:
    Expression& _lhs;
    Expression& _rhs;
};

class Division : public Expression
{
public:
    Division(Expression& lhs, Expression& rhs)
    : _lhs(lhs), _rhs(rhs) {}

    int evaluate() override;

private:
    Expression& _lhs;
    Expression& _rhs;
};

class Variable : public Expression
{
public:
    Variable(Context& context, const std::string& name)
    : _context(context), _name(name) {}

    int evaluate() override;
    void set(int value);

private:
    Context& _context;
    std::string _name;
};

class Assignment : public Expression
{
public:
    Assignment(Variable& var, Expression& exp)
    : _var(var), _exp(exp) {}

    int evaluate() override;

private:
    Variable& _var;
    Expression& _exp;
};
#include "expression.h"

#include <stdexcept>
#include <iostream>


int Context::get(const std::string& name) const
{
    auto found = _variables.find(name);
    if (found == _variables.end())
        return 0;
    return found->second;
}

void Context::set(const std::string& name, int value)
{
    _variables[name] = value;
}

int Literal::evaluate()
{
    return _value;
}

int Addition::evaluate()
{
    return _lhs.evaluate() + _rhs.evaluate();
}

int Subtraction::evaluate()
{
    return _lhs.evaluate() - _rhs.evaluate();
}

int Multiplication::evaluate()
{
    return _lhs.evaluate() * _rhs.evaluate();
}

int Division::evaluate()
{
    return _lhs.evaluate() / _rhs.evaluate();
}

int Variable::evaluate()
{
    return _context.get(_name);
}

void Variable::set(int value)
{
    _context.set(_name, value);
}

int Assignment::evaluate()
{
    int value = _exp.evaluate();
    _var.set(value);
    return value;
}