Помогите разобраться с заданием:
В этой задаче вам необходимо реализовать сворачивание констант в дереве (constant folding). Например, у нас есть выражение (точнее, дерево, описывающее это выражение) abs(var * sqrt(32.0 - 16.0)), на выходе мы должны получить дерево для следующего выражения abs(var * 4.0), т. е. подвыражение sqrt(32.0 - 16.0) было вычислено.
Для того, чтобы определить, что выражение (Expression) на самом деле является числом (Number), используйте оператор dynamic_cast.
Все промежуточные узлы дерева, которые вы создали, нужно освободить.
#include <cassert>
#include <string>
#include <cmath>
struct Transformer;
struct Number;
struct BinaryOperation;
struct FunctionCall;
struct Variable;
struct Expression
{
virtual ~Expression() { }
virtual double evaluate() const = 0;
virtual Expression *transform(Transformer *tr) const = 0;
};
struct Transformer
{
virtual ~Transformer() { }
virtual Expression *transformNumber(Number const *) = 0;
virtual Expression *transformBinaryOperation(BinaryOperation const *) = 0;
virtual Expression *transformFunctionCall(FunctionCall const *) = 0;
virtual Expression *transformVariable(Variable const *) = 0;
};
struct Number : Expression
{
Number(double value);
double value() const;
double evaluate() const;
Expression *transform(Transformer *tr) const;
private:
double value_;
};
struct BinaryOperation : Expression
{
enum {
PLUS = '+',
MINUS = '-',
DIV = '/',
MUL = '*'
};
BinaryOperation(Expression const *left, int op, Expression const *right);
~BinaryOperation();
double evaluate() const;
Expression *transform(Transformer *tr) const;
Expression const *left() const;
Expression const *right() const;
int operation() const;
private:
Expression const *left_;
Expression const *right_;
int op_;
};
struct FunctionCall : Expression
{
FunctionCall(std::string const &name, Expression const *arg);
~FunctionCall();
double evaluate() const;
Expression *transform(Transformer *tr) const;
std::string const &name() const;
Expression const *arg() const;
private:
std::string const name_;
Expression const *arg_;
};
struct Variable : Expression
{
Variable(std::string const name);
std::string const & name() const;
double evaluate() const;
Expression *transform(Transformer *tr) const;
private:
std::string const name_;
};
/**
* реализйте все необходимые методы
* если считаете нужным, то можете
* заводить любые вспомогетльные
* методы
*/
struct FoldConstants : Transformer
{
Expression *transformNumber(Number const *number)
{ }
Expression *transformBinaryOperation(BinaryOperation const *binop)
{ }
Expression *transformFunctionCall(FunctionCall const *fcall)
{ }
Expression *transformVariable(Variable const *var)
{ }
};
Вот мое решение, но оно не проходит тест:
struct FoldConstants : Transformer
{
Expression *transformNumber(Number const *number)
{
return new Number(number->value());
}
Expression *transformBinaryOperation(BinaryOperation const *binop)
{
Expression * a;
Expression * b;
if (dynamic_cast<Number*>(binop->left()->transform(this)))
{a = binop->left()->transform(this);}
else
{a = (Number*)(binop->left()->transform(this));}
if (dynamic_cast<Number*>(binop->right()->transform(this)))
{b = binop->right()->transform(this);}
else
{b = (Number*)(binop->right()->transform(this));}
BinaryOperation * c = new BinaryOperation(a, binop->operation(), b);
return new Number(c->evaluate());
delete c;
}
Expression *transformFunctionCall(FunctionCall const *fcall)
{
Expression * a;
if (dynamic_cast<Number*>(fcall->arg()->transform(this)))
{a = fcall->arg()->transform(this);}
else
{a = (Number*)(fcall->arg()->transform(this));}
FunctionCall * b = new FunctionCall(fcall->name(), a);
return new Number(b->evaluate());
delete b;
}
Expression *transformVariable(Variable const *var)
{
return new Variable(var->name());
}
};