#ifndef MATHFUNCTION_HPP
#define MATHFUNCTION_HPP

const int NUMUNARYOPERATORS = 16;
const int NUMBINARYOPERATORS = 5;

enum {
LEFT_ASSOCIATIVE,
RIGHT_ASSOCIATIVE
};

char *SubString(const char *s, int Pos, int Length);

typedef double (*TUnaryOperator)(double);
typedef double (*TBinaryOperator)(double, double);
union TOperator {
TUnaryOperator UnaryOperator;
TBinaryOperator BinaryOperator;
};

struct TUnaryOperatorInfo {
char *Name;
TUnaryOperator UnaryOperator;
};

struct TBinaryOperatorInfo {
char Symbol;
int Precedence;
int Associativity;
TBinaryOperator BinaryOperator;
};

struct TMathFunctionNode;

struct TOperatorWithArguments {
TMathFunctionNode *Argument1;
TMathFunctionNode *Argument2; //NULL in the case of a unary operator.
TOperator Operator;
};

union TMathFunctionNodeValue {
double Constant;
int VariableID;
TOperatorWithArguments OperatorWithArguments;
};

struct TMathFunctionNode {
int Type; //1 for a constant, 2 for a variable, 3 for a unary operator, 4 for a binary operator.
TMathFunctionNodeValue Value;
};

class TMathFunction {
private:
TUnaryOperatorInfo *UnaryOperatorTable;
TBinaryOperatorInfo *BinaryOperatorTable;
TMathFunctionNode *First;
void CreateBinaryTree(const char *s, TMathFunctionNode *CurrentNode);
double Traverse(TMathFunctionNode *CurrentNode, double x, double y);
public:
TMathFunction(const char *s);
~TMathFunction();
double operator()(double x, double y);
};

#endif
