2013-09-15 18:39:22 +01:00
|
|
|
#include <latan/MathCompiler.hpp>
|
|
|
|
#include <latan/includes.hpp>
|
|
|
|
|
|
|
|
using namespace std;
|
|
|
|
using namespace Latan;
|
|
|
|
|
|
|
|
// Math Bison/Flex parser declaration
|
2014-01-22 15:57:47 +00:00
|
|
|
int _math_parse(MathParserState* state);
|
2013-09-15 18:39:22 +01:00
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
* MathNode implementation *
|
|
|
|
******************************************************************************/
|
|
|
|
// constructor /////////////////////////////////////////////////////////////////
|
2014-01-22 15:57:47 +00:00
|
|
|
MathNode::MathNode(const string &name, const unsigned int type)
|
|
|
|
: name_(name)
|
|
|
|
, type_(type)
|
2013-09-15 18:39:22 +01:00
|
|
|
{}
|
|
|
|
|
2014-01-22 15:57:47 +00:00
|
|
|
MathNode::MathNode(const std::string &name, const unsigned int type,\
|
|
|
|
const unsigned int nArg, ...)
|
|
|
|
: name_(name)
|
|
|
|
, type_(type)
|
|
|
|
, arg_(nArg)
|
2013-09-15 18:39:22 +01:00
|
|
|
{
|
|
|
|
va_list va;
|
|
|
|
|
2014-01-22 15:57:47 +00:00
|
|
|
va_start(va, nArg);
|
|
|
|
for (unsigned int i = 0; i < nArg; ++i)
|
2013-09-15 18:39:22 +01:00
|
|
|
{
|
2014-01-22 15:57:47 +00:00
|
|
|
arg_[i] = va_arg(va, MathNode*);
|
2013-09-15 18:39:22 +01:00
|
|
|
}
|
|
|
|
va_end(va);
|
|
|
|
}
|
|
|
|
|
|
|
|
// destructor //////////////////////////////////////////////////////////////////
|
|
|
|
MathNode::~MathNode(void)
|
|
|
|
{
|
|
|
|
vector<MathNode*>::iterator i;
|
|
|
|
|
2014-01-22 15:57:47 +00:00
|
|
|
for (i = arg_.begin(); i != arg_.end(); ++i)
|
2013-09-15 18:39:22 +01:00
|
|
|
{
|
|
|
|
delete *i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// access //////////////////////////////////////////////////////////////////////
|
2014-01-22 15:57:47 +00:00
|
|
|
const string &MathNode::getName(void) const
|
2013-09-15 18:39:22 +01:00
|
|
|
{
|
2014-01-22 15:57:47 +00:00
|
|
|
return name_;
|
2013-09-15 18:39:22 +01:00
|
|
|
}
|
|
|
|
|
2014-01-22 15:57:47 +00:00
|
|
|
unsigned int MathNode::getType(void) const
|
2013-09-15 18:39:22 +01:00
|
|
|
{
|
2014-01-22 15:57:47 +00:00
|
|
|
return type_;
|
2013-09-15 18:39:22 +01:00
|
|
|
}
|
|
|
|
|
2014-01-22 15:57:47 +00:00
|
|
|
unsigned int MathNode::getNArg(void) const
|
2013-09-15 18:39:22 +01:00
|
|
|
{
|
2014-01-22 15:57:47 +00:00
|
|
|
return static_cast<unsigned int>(arg_.size());
|
2013-09-15 18:39:22 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// operator ////////////////////////////////////////////////////////////////////
|
2014-01-22 15:57:47 +00:00
|
|
|
const MathNode &MathNode::operator[](const unsigned int i) const
|
2013-09-15 18:39:22 +01:00
|
|
|
{
|
2014-01-22 15:57:47 +00:00
|
|
|
return *arg_[i];
|
2013-09-15 18:39:22 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
* MathParserState implementation *
|
|
|
|
******************************************************************************/
|
|
|
|
// constructor /////////////////////////////////////////////////////////////////
|
2014-01-22 15:57:47 +00:00
|
|
|
MathParserState::MathParserState(std::istream *stream, std::string *name,
|
|
|
|
MathNode **data)
|
|
|
|
: ParserState<MathNode *>(stream, name, data)
|
2013-09-15 18:39:22 +01:00
|
|
|
{
|
2014-01-22 15:57:47 +00:00
|
|
|
initScanner();
|
2013-09-15 18:39:22 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// destructor //////////////////////////////////////////////////////////////////
|
|
|
|
MathParserState::~MathParserState(void)
|
|
|
|
{
|
2014-01-22 15:57:47 +00:00
|
|
|
destroyScanner();
|
2013-09-15 18:39:22 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
* Instruction set *
|
|
|
|
******************************************************************************/
|
|
|
|
#define CODE_WIDTH 6
|
|
|
|
#define CODE_MOD setw(CODE_WIDTH) << left
|
|
|
|
|
2013-09-28 19:04:15 +01:00
|
|
|
Instruction::~Instruction(void)
|
|
|
|
{}
|
|
|
|
|
2014-01-22 15:57:47 +00:00
|
|
|
ostream &Latan::operator<<(ostream& out, const Instruction& ins)
|
2013-09-15 18:39:22 +01:00
|
|
|
{
|
2014-01-22 15:57:47 +00:00
|
|
|
ins.print(out);
|
2013-09-15 18:39:22 +01:00
|
|
|
|
|
|
|
return out;
|
|
|
|
}
|
|
|
|
|
2014-01-22 15:57:47 +00:00
|
|
|
Push::Push(const double val)
|
|
|
|
: type_(ArgType::Constant)
|
|
|
|
, val_(val)
|
|
|
|
, name_("")
|
2013-09-15 18:39:22 +01:00
|
|
|
{}
|
|
|
|
|
2014-01-22 15:57:47 +00:00
|
|
|
Push::Push(const string &name)
|
|
|
|
: type_(ArgType::Variable)
|
|
|
|
, val_(0.0)
|
|
|
|
, name_(name)
|
2013-09-15 18:39:22 +01:00
|
|
|
{}
|
|
|
|
|
2014-01-22 15:57:47 +00:00
|
|
|
void Push::operator()(std::stack<double> &dStack, VarTable &vTable)
|
2013-09-15 18:39:22 +01:00
|
|
|
{
|
2014-01-22 15:57:47 +00:00
|
|
|
if (type_ == ArgType::Constant)
|
2013-09-15 18:39:22 +01:00
|
|
|
{
|
2014-01-22 15:57:47 +00:00
|
|
|
dStack.push(val_);
|
2013-09-15 18:39:22 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2014-01-22 15:57:47 +00:00
|
|
|
dStack.push(vTable[name_]);
|
2013-09-15 18:39:22 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-01-22 15:57:47 +00:00
|
|
|
void Push::print(std::ostream &out) const
|
2013-09-15 18:39:22 +01:00
|
|
|
{
|
|
|
|
out << CODE_MOD << "push";
|
2014-01-22 15:57:47 +00:00
|
|
|
if (type_ == ArgType::Constant)
|
2013-09-15 18:39:22 +01:00
|
|
|
{
|
2014-01-22 15:57:47 +00:00
|
|
|
out << CODE_MOD << val_;
|
2013-09-15 18:39:22 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2014-01-22 15:57:47 +00:00
|
|
|
out << CODE_MOD << name_;
|
2013-09-15 18:39:22 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-01-22 15:57:47 +00:00
|
|
|
Pop::Pop(const string &name)
|
|
|
|
: name_(name)
|
2013-09-15 18:39:22 +01:00
|
|
|
{}
|
|
|
|
|
2014-01-22 15:57:47 +00:00
|
|
|
void Pop::operator()(std::stack<double> &dStack, VarTable &vTable)
|
2013-09-15 18:39:22 +01:00
|
|
|
{
|
2014-01-22 15:57:47 +00:00
|
|
|
vTable[name_] = dStack.top();
|
|
|
|
dStack.pop();
|
2013-09-15 18:39:22 +01:00
|
|
|
}
|
|
|
|
|
2014-01-22 15:57:47 +00:00
|
|
|
void Pop::print(std::ostream &out) const
|
2013-09-15 18:39:22 +01:00
|
|
|
{
|
2014-01-22 15:57:47 +00:00
|
|
|
out << CODE_MOD << "pop" << CODE_MOD << name_;
|
2013-09-15 18:39:22 +01:00
|
|
|
}
|
|
|
|
|
2014-01-22 15:57:47 +00:00
|
|
|
#define DEF_OP(name, nArg, exp, insName)\
|
|
|
|
void name::operator()(stack<double> &dStack, VarTable &vTable __dumb)\
|
2013-09-15 18:39:22 +01:00
|
|
|
{\
|
2014-01-22 15:57:47 +00:00
|
|
|
double x[nArg];\
|
|
|
|
for (int i = 0; i < nArg; ++i)\
|
2013-09-15 18:39:22 +01:00
|
|
|
{\
|
2014-01-22 15:57:47 +00:00
|
|
|
x[nArg-1-i] = dStack.top();\
|
|
|
|
dStack.pop();\
|
2013-09-15 18:39:22 +01:00
|
|
|
}\
|
2014-01-22 15:57:47 +00:00
|
|
|
dStack.push(exp);\
|
2013-09-15 18:39:22 +01:00
|
|
|
}\
|
2014-01-22 15:57:47 +00:00
|
|
|
void name::print(std::ostream &out) const\
|
2013-09-15 18:39:22 +01:00
|
|
|
{\
|
2014-01-22 15:57:47 +00:00
|
|
|
out << CODE_MOD << insName;\
|
2013-09-15 18:39:22 +01:00
|
|
|
}
|
|
|
|
|
2014-01-22 15:57:47 +00:00
|
|
|
DEF_OP(Neg, 1, -x[0], "neg")
|
|
|
|
DEF_OP(Add, 2, x[0]+x[1], "add")
|
|
|
|
DEF_OP(Sub, 2, x[0]-x[1], "sub")
|
|
|
|
DEF_OP(Mul, 2, x[0]*x[1], "mul")
|
|
|
|
DEF_OP(Div, 2, x[0]/x[1], "div")
|
|
|
|
DEF_OP(Pow, 2, pow(x[0],x[1]), "pow")
|
2013-09-15 18:39:22 +01:00
|
|
|
|
|
|
|
VirtualProgram::VirtualProgram(void)
|
2014-01-22 15:57:47 +00:00
|
|
|
: vector<Instruction *>(0)
|
2013-09-15 18:39:22 +01:00
|
|
|
{}
|
|
|
|
|
2014-01-22 15:57:47 +00:00
|
|
|
ostream &Latan::operator<<(ostream &out, const VirtualProgram &prog)
|
2013-09-15 18:39:22 +01:00
|
|
|
{
|
2014-01-22 15:57:47 +00:00
|
|
|
for (unsigned int i = 0; i < prog.size(); ++i)
|
2013-09-15 18:39:22 +01:00
|
|
|
{
|
|
|
|
out << *(prog[i]) << endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
return out;
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
* MathCompiler implementation *
|
|
|
|
******************************************************************************/
|
|
|
|
// constructors ////////////////////////////////////////////////////////////////
|
|
|
|
MathCompiler::MathCompiler(void)
|
2014-01-22 15:57:47 +00:00
|
|
|
: code_(NULL)
|
|
|
|
, codeName_("<no_code>")
|
|
|
|
, state_(NULL)
|
|
|
|
, root_(NULL)
|
|
|
|
, out_()
|
2014-01-22 16:29:52 +00:00
|
|
|
, status_(Status::none)
|
2013-09-15 18:39:22 +01:00
|
|
|
{}
|
|
|
|
|
2014-01-22 15:57:47 +00:00
|
|
|
MathCompiler::MathCompiler(const std::string &code)
|
2013-09-15 18:39:22 +01:00
|
|
|
{
|
2014-01-22 15:57:47 +00:00
|
|
|
init(code);
|
2013-09-15 18:39:22 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// destructor //////////////////////////////////////////////////////////////////
|
|
|
|
MathCompiler::~MathCompiler(void)
|
|
|
|
{
|
2014-01-22 15:57:47 +00:00
|
|
|
reset();
|
2013-09-15 18:39:22 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// public methods //////////////////////////////////////////////////////////////
|
2014-01-22 15:57:47 +00:00
|
|
|
void MathCompiler::init(const std::string &code)
|
2013-09-15 18:39:22 +01:00
|
|
|
{
|
2014-01-22 15:57:47 +00:00
|
|
|
if (status_)
|
2013-09-15 18:39:22 +01:00
|
|
|
{
|
2014-01-22 15:57:47 +00:00
|
|
|
reset();
|
2013-09-15 18:39:22 +01:00
|
|
|
}
|
2014-01-22 15:57:47 +00:00
|
|
|
code_ = new stringstream(code);
|
|
|
|
codeName_ = "<string>";
|
|
|
|
state_ = new MathParserState(code_, &codeName_, &root_);
|
2014-01-22 16:29:52 +00:00
|
|
|
status_ |= Status::initialised;
|
2013-09-15 18:39:22 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
const VirtualProgram& MathCompiler::operator()(void)
|
|
|
|
{
|
2014-01-22 16:29:52 +00:00
|
|
|
if (!(status_ & Status::parsed))
|
2013-09-15 18:39:22 +01:00
|
|
|
{
|
2014-01-22 15:57:47 +00:00
|
|
|
parse();
|
2013-09-15 18:39:22 +01:00
|
|
|
}
|
2014-01-22 16:29:52 +00:00
|
|
|
if (!(status_ & Status::compiled))
|
2013-09-15 18:39:22 +01:00
|
|
|
{
|
2014-01-22 15:57:47 +00:00
|
|
|
compile(*root_);
|
2013-09-15 18:39:22 +01:00
|
|
|
}
|
|
|
|
|
2014-01-22 15:57:47 +00:00
|
|
|
return out_;
|
2013-09-15 18:39:22 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// private methods /////////////////////////////////////////////////////////////
|
2014-01-22 15:57:47 +00:00
|
|
|
void MathCompiler::parse(void)
|
2013-09-15 18:39:22 +01:00
|
|
|
{
|
2014-01-22 15:57:47 +00:00
|
|
|
_math_parse(state_);
|
2014-01-22 16:29:52 +00:00
|
|
|
status_ |= Status::parsed;
|
|
|
|
status_ -= status_ & Status::compiled;
|
2013-09-15 18:39:22 +01:00
|
|
|
}
|
|
|
|
|
2014-01-22 15:57:47 +00:00
|
|
|
#define IFOP(name, nArg) if ((n.getName() == (name))&&(n.getNArg() == nArg))
|
|
|
|
#define ELIFOP(name, nArg) else IFOP(name, nArg)
|
2013-09-15 18:39:22 +01:00
|
|
|
#define ELSE else
|
2014-01-22 15:57:47 +00:00
|
|
|
void MathCompiler::compile(const MathNode& n)
|
2013-09-15 18:39:22 +01:00
|
|
|
{
|
2014-01-22 15:57:47 +00:00
|
|
|
switch (n.getType())
|
2013-09-15 18:39:22 +01:00
|
|
|
{
|
2014-01-22 15:57:47 +00:00
|
|
|
case MathNode::Type::Constant:
|
|
|
|
out_.push_back(new Push(ato<double>(n.getName())));
|
2013-09-15 18:39:22 +01:00
|
|
|
break;
|
2014-01-22 15:57:47 +00:00
|
|
|
case MathNode::Type::Variable:
|
|
|
|
out_.push_back(new Push(n.getName()));
|
2013-09-15 18:39:22 +01:00
|
|
|
break;
|
2014-01-22 15:57:47 +00:00
|
|
|
case MathNode::Type::Operator:
|
|
|
|
for (unsigned int i = 0; i < n.getNArg(); ++i)
|
2013-09-15 18:39:22 +01:00
|
|
|
{
|
2014-01-22 15:57:47 +00:00
|
|
|
compile(n[i]);
|
2013-09-15 18:39:22 +01:00
|
|
|
}
|
2014-01-22 15:57:47 +00:00
|
|
|
IFOP("-",1) out_.push_back(new Neg);
|
|
|
|
ELIFOP("+",2) out_.push_back(new Add);
|
|
|
|
ELIFOP("-",2) out_.push_back(new Sub);
|
|
|
|
ELIFOP("*",2) out_.push_back(new Mul);
|
|
|
|
ELIFOP("/",2) out_.push_back(new Div);
|
|
|
|
ELIFOP("^",2) out_.push_back(new Pow);
|
|
|
|
ELSE LATAN_ERROR(Compilation,
|
|
|
|
"unknown operator (node '" + n.getName() + "')");
|
2013-09-15 18:39:22 +01:00
|
|
|
break;
|
|
|
|
default:
|
2014-01-22 15:57:47 +00:00
|
|
|
LATAN_ERROR(Compilation,
|
|
|
|
"unknown node type (node '" + n.getName() + "')");
|
2013-09-15 18:39:22 +01:00
|
|
|
break;
|
|
|
|
}
|
2014-01-22 16:29:52 +00:00
|
|
|
status_ |= Status::compiled;
|
2013-09-15 18:39:22 +01:00
|
|
|
}
|
|
|
|
|
2014-01-22 15:57:47 +00:00
|
|
|
void MathCompiler::reset(void)
|
2013-09-15 18:39:22 +01:00
|
|
|
{
|
|
|
|
VirtualProgram::iterator i;
|
|
|
|
|
2014-01-22 15:57:47 +00:00
|
|
|
delete code_;
|
|
|
|
codeName_ = "<no_code>";
|
|
|
|
delete state_;
|
|
|
|
delete root_;
|
|
|
|
for (i = out_.begin(); i != out_.end(); ++i)
|
2013-09-15 18:39:22 +01:00
|
|
|
{
|
|
|
|
delete *i;
|
|
|
|
}
|
2014-01-22 15:57:47 +00:00
|
|
|
out_.clear();
|
|
|
|
status_ = 0;
|
2013-09-15 18:39:22 +01:00
|
|
|
}
|
|
|
|
|