mirror of
https://github.com/aportelli/LatAnalyze.git
synced 2024-11-10 08:55:37 +00:00
general cleaning/consolidation of the math interpreter
This commit is contained in:
parent
50d21ae904
commit
ce6469cdd7
@ -14,11 +14,16 @@ if CXX_INTEL
|
|||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
noinst_PROGRAMS = \
|
noinst_PROGRAMS = \
|
||||||
exMathCompiler
|
exMathInterpreter \
|
||||||
|
exCompiledDoubleFunction
|
||||||
|
|
||||||
exMathCompiler_SOURCES = exMathCompiler.cpp
|
exMathInterpreter_SOURCES = exMathInterpreter.cpp
|
||||||
exMathCompiler_CFLAGS = -g -O2
|
exMathInterpreter_CFLAGS = -g -O2
|
||||||
exMathCompiler_LDFLAGS = -L../latan/.libs -llatan
|
exMathInterpreter_LDFLAGS = -L../latan/.libs -llatan
|
||||||
|
|
||||||
|
exCompiledDoubleFunction_SOURCES = exCompiledDoubleFunction.cpp
|
||||||
|
exCompiledDoubleFunction_CFLAGS = -g -O2
|
||||||
|
exCompiledDoubleFunction_LDFLAGS = -L../latan/.libs -llatan
|
||||||
|
|
||||||
ACLOCAL_AMFLAGS = -I .buildutils/m4
|
ACLOCAL_AMFLAGS = -I .buildutils/m4
|
||||||
|
31
examples/exCompiledDoubleFunction.cpp
Normal file
31
examples/exCompiledDoubleFunction.cpp
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#include <iostream>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <latan/CompiledFunction.hpp>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace Latan;
|
||||||
|
|
||||||
|
int main(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
string source;
|
||||||
|
|
||||||
|
if (argc != 2)
|
||||||
|
{
|
||||||
|
cerr << "usage: " << argv[0] << " <function>" << endl;
|
||||||
|
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
source = argv[1];
|
||||||
|
|
||||||
|
CompiledDoubleFunction f(1, source);
|
||||||
|
|
||||||
|
cout << "-- Program:" << endl << f << endl;
|
||||||
|
cout << "-- Values:" << endl;
|
||||||
|
for (double x = 0.0; x < 10.0; x += 0.5)
|
||||||
|
{
|
||||||
|
cout << "f(" << right << setw(6) << strFrom<double>(x) << ")= "
|
||||||
|
<< f(x) << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
75
examples/exMathInterpreter.cpp
Normal file
75
examples/exMathInterpreter.cpp
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
#include <iostream>
|
||||||
|
#include <latan/Math.hpp>
|
||||||
|
#include <latan/MathInterpreter.hpp>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace Latan;
|
||||||
|
|
||||||
|
int main(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
string source;
|
||||||
|
|
||||||
|
if (argc != 2)
|
||||||
|
{
|
||||||
|
cerr << "usage: " << argv[0] << " <program>" << endl;
|
||||||
|
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
source = argv[1];
|
||||||
|
|
||||||
|
MathInterpreter interpreter(source);
|
||||||
|
RunContext context;
|
||||||
|
|
||||||
|
cout << "-- Source code:" << endl << source << endl << endl;
|
||||||
|
interpreter.compile();
|
||||||
|
cout << "-- Abstract Syntax Tree:" << endl;
|
||||||
|
if (interpreter.getAST())
|
||||||
|
{
|
||||||
|
cout << *interpreter.getAST() << endl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cout << "<null>" << endl << endl;
|
||||||
|
}
|
||||||
|
cout << "-- Program:" << endl << interpreter << endl;
|
||||||
|
StdMath::addStdMathFunc(context.fTable);
|
||||||
|
interpreter(context);
|
||||||
|
if (!context.dStack.empty())
|
||||||
|
{
|
||||||
|
cout << "-- Result: " << context.dStack.top() << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*int main(void)
|
||||||
|
{
|
||||||
|
ASCIIFile F;
|
||||||
|
DMat A,B;
|
||||||
|
|
||||||
|
F.Open("foo.boot",FileMode::Read);
|
||||||
|
A = F.Read<DMat>("bla");
|
||||||
|
B = F.Read<DMat>("bli");
|
||||||
|
cout << A << endl;
|
||||||
|
cout << B << endl;
|
||||||
|
cout << A*B << endl;
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
DMat m(2,2);
|
||||||
|
|
||||||
|
m(0,6) = 3;
|
||||||
|
m(1,0) = 2.5;
|
||||||
|
m(0,1) = -1;
|
||||||
|
m(1,1) = m(1,0) + m(0,1);
|
||||||
|
cout << "Here is the matrix m:\n" << m << endl;
|
||||||
|
DVec v(2);
|
||||||
|
v(0) = 4;
|
||||||
|
v(1) = v(0) - 1;
|
||||||
|
cout << "Here is the vector v:\n" << v << endl;
|
||||||
|
}
|
||||||
|
*/
|
69
latan/CompiledFunction.cpp
Normal file
69
latan/CompiledFunction.cpp
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
#include <latan/CompiledFunction.hpp>
|
||||||
|
#include <latan/Math.hpp>
|
||||||
|
#include <latan/includes.hpp>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace Latan;
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
* Compiled double function implementation *
|
||||||
|
******************************************************************************/
|
||||||
|
// constructor/destructor //////////////////////////////////////////////////////
|
||||||
|
CompiledDoubleFunction::CompiledDoubleFunction(const unsigned nArg)
|
||||||
|
: DoubleFunction(nArg)
|
||||||
|
{}
|
||||||
|
|
||||||
|
CompiledDoubleFunction::CompiledDoubleFunction(const unsigned nArg,
|
||||||
|
const string &code)
|
||||||
|
: DoubleFunction(nArg)
|
||||||
|
{
|
||||||
|
setCode(code);
|
||||||
|
}
|
||||||
|
|
||||||
|
CompiledDoubleFunction::~CompiledDoubleFunction(void)
|
||||||
|
{}
|
||||||
|
|
||||||
|
// access //////////////////////////////////////////////////////////////////////
|
||||||
|
void CompiledDoubleFunction::setCode(const string &code)
|
||||||
|
{
|
||||||
|
interpreter_.setCode(code);
|
||||||
|
StdMath::addStdMathFunc(context_.fTable);
|
||||||
|
}
|
||||||
|
|
||||||
|
// function call ///////////////////////////////////////////////////////////////
|
||||||
|
double CompiledDoubleFunction::operator()(vector<double> &arg)
|
||||||
|
{
|
||||||
|
double result;
|
||||||
|
|
||||||
|
if (arg.size() != getNArg())
|
||||||
|
{
|
||||||
|
LATAN_ERROR(Size, "function argument vector has a wrong size (got " +
|
||||||
|
strFrom(arg.size()) + ", expected " + strFrom(getNArg()) +
|
||||||
|
")");
|
||||||
|
}
|
||||||
|
for (unsigned int i = 0; i < getNArg(); ++i)
|
||||||
|
{
|
||||||
|
context_.vTable["x_" + strFrom(i)] = arg[i];
|
||||||
|
}
|
||||||
|
interpreter_(context_);
|
||||||
|
if (!context_.dStack.empty())
|
||||||
|
{
|
||||||
|
result = context_.dStack.top();
|
||||||
|
context_.dStack.pop();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = 0.0;
|
||||||
|
LATAN_ERROR(Program, "program execution resulted in an empty stack");
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// IO //////////////////////////////////////////////////////////////////////////
|
||||||
|
ostream &Latan::operator<<(ostream &out, CompiledDoubleFunction &f)
|
||||||
|
{
|
||||||
|
out << f.interpreter_;
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
39
latan/CompiledFunction.hpp
Normal file
39
latan/CompiledFunction.hpp
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
#ifndef LATAN_COMPILED_FUNCTION_HPP_
|
||||||
|
#define LATAN_COMPILED_FUNCTION_HPP_
|
||||||
|
|
||||||
|
#include <latan/Global.hpp>
|
||||||
|
#include <latan/Function.hpp>
|
||||||
|
#include <latan/MathInterpreter.hpp>
|
||||||
|
#include <stack>
|
||||||
|
#include <vector>
|
||||||
|
#include <cstdarg>
|
||||||
|
|
||||||
|
LATAN_BEGIN_CPPDECL
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
* Compiled double function class *
|
||||||
|
******************************************************************************/
|
||||||
|
class CompiledDoubleFunction: public DoubleFunction
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// constructor/destructor
|
||||||
|
explicit CompiledDoubleFunction(const unsigned nArg);
|
||||||
|
explicit CompiledDoubleFunction(const unsigned nArg,
|
||||||
|
const std::string &code);
|
||||||
|
virtual ~CompiledDoubleFunction(void);
|
||||||
|
// access
|
||||||
|
void setCode(const std::string &code);
|
||||||
|
// function call
|
||||||
|
using DoubleFunction::operator();
|
||||||
|
virtual double operator()(std::vector<double> &arg);
|
||||||
|
// IO
|
||||||
|
friend std::ostream &operator<<(std::ostream &out,
|
||||||
|
CompiledDoubleFunction &f);
|
||||||
|
private:
|
||||||
|
MathInterpreter interpreter_;
|
||||||
|
RunContext context_;
|
||||||
|
};
|
||||||
|
|
||||||
|
LATAN_END_CPPDECL
|
||||||
|
|
||||||
|
#endif
|
@ -8,7 +8,7 @@
|
|||||||
#define ERR_SUFF " (" + loc + ")"
|
#define ERR_SUFF " (" + loc + ")"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define CONST_EXC(name,init) \
|
#define CONST_EXC(name, init) \
|
||||||
name::name(string msg, string loc)\
|
name::name(string msg, string loc)\
|
||||||
:init\
|
:init\
|
||||||
{}
|
{}
|
||||||
@ -18,13 +18,16 @@ using namespace Latan;
|
|||||||
using namespace Exceptions;
|
using namespace Exceptions;
|
||||||
|
|
||||||
// logic errors
|
// logic errors
|
||||||
CONST_EXC(Logic,logic_error(ERR_PREF+msg+ERR_SUFF))
|
CONST_EXC(Logic, logic_error(ERR_PREF+msg+ERR_SUFF))
|
||||||
CONST_EXC(Implementation,Logic("implementation error: "+msg,loc))
|
CONST_EXC(Definition, Logic("definition error: "+msg,loc))
|
||||||
CONST_EXC(Range,Logic("range error: "+msg,loc))
|
CONST_EXC(Implementation, Logic("implementation error: "+msg,loc))
|
||||||
|
CONST_EXC(Range, Logic("range error: "+msg,loc))
|
||||||
|
CONST_EXC(Size, Logic("size error: "+msg,loc))
|
||||||
// runtime errors
|
// runtime errors
|
||||||
CONST_EXC(Runtime,runtime_error(ERR_PREF+msg+ERR_SUFF))
|
CONST_EXC(Runtime, runtime_error(ERR_PREF+msg+ERR_SUFF))
|
||||||
CONST_EXC(Compilation,Runtime("compilation error: "+msg,loc))
|
CONST_EXC(Compilation, Runtime("compilation error: "+msg,loc))
|
||||||
CONST_EXC(Io,Runtime("IO error: "+msg,loc))
|
CONST_EXC(Io, Runtime("IO error: "+msg,loc))
|
||||||
CONST_EXC(Parsing,Runtime(msg,loc))
|
CONST_EXC(Parsing, Runtime(msg,loc))
|
||||||
CONST_EXC(Syntax,Runtime("syntax error: "+msg,loc))
|
CONST_EXC(Program, Runtime(msg,loc))
|
||||||
|
CONST_EXC(Syntax, Runtime("syntax error: "+msg,loc))
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
+ strFrom<const char*>(__FILE__) + ":" + strFrom<int>(__LINE__)
|
+ strFrom<const char*>(__FILE__) + ":" + strFrom<int>(__LINE__)
|
||||||
#define LATAN_ERROR(exc,msg) throw(Exceptions::exc(msg,SRC_LOC))
|
#define LATAN_ERROR(exc,msg) throw(Exceptions::exc(msg,SRC_LOC))
|
||||||
|
|
||||||
#define DECL_EXC(name,base) \
|
#define DECL_EXC(name, base) \
|
||||||
class name: public base\
|
class name: public base\
|
||||||
{\
|
{\
|
||||||
public:\
|
public:\
|
||||||
@ -22,15 +22,18 @@ LATAN_BEGIN_CPPDECL
|
|||||||
namespace Exceptions
|
namespace Exceptions
|
||||||
{
|
{
|
||||||
// logic errors
|
// logic errors
|
||||||
DECL_EXC(Logic,std::logic_error);
|
DECL_EXC(Logic, std::logic_error);
|
||||||
DECL_EXC(Implementation,Logic);
|
DECL_EXC(Definition, Logic);
|
||||||
DECL_EXC(Range,Logic);
|
DECL_EXC(Implementation, Logic);
|
||||||
|
DECL_EXC(Range, Logic);
|
||||||
|
DECL_EXC(Size, Logic);
|
||||||
// runtime errors
|
// runtime errors
|
||||||
DECL_EXC(Runtime,std::runtime_error);
|
DECL_EXC(Runtime, std::runtime_error);
|
||||||
DECL_EXC(Compilation,Runtime);
|
DECL_EXC(Compilation, Runtime);
|
||||||
DECL_EXC(Io,Runtime);
|
DECL_EXC(Io, Runtime);
|
||||||
DECL_EXC(Parsing,Runtime);
|
DECL_EXC(Parsing, Runtime);
|
||||||
DECL_EXC(Syntax,Runtime);
|
DECL_EXC(Program, Runtime);
|
||||||
|
DECL_EXC(Syntax, Runtime);
|
||||||
}
|
}
|
||||||
|
|
||||||
LATAN_END_CPPDECL
|
LATAN_END_CPPDECL
|
||||||
|
@ -34,7 +34,7 @@ Function::~Function(void)
|
|||||||
{}
|
{}
|
||||||
|
|
||||||
// access //////////////////////////////////////////////////////////////////////
|
// access //////////////////////////////////////////////////////////////////////
|
||||||
unsigned int Function::getNArg(void)
|
unsigned int Function::getNArg(void) const
|
||||||
{
|
{
|
||||||
return nArg_;
|
return nArg_;
|
||||||
}
|
}
|
||||||
@ -77,5 +77,3 @@ double DoubleFunction::operator()(const double x0, ...)
|
|||||||
|
|
||||||
return (*this)(buffer_);
|
return (*this)(buffer_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -16,9 +16,9 @@ class Function
|
|||||||
public:
|
public:
|
||||||
// constructor/destructor
|
// constructor/destructor
|
||||||
explicit Function(const unsigned nArg);
|
explicit Function(const unsigned nArg);
|
||||||
~Function(void);
|
virtual ~Function(void);
|
||||||
// access
|
// access
|
||||||
unsigned int getNArg(void);
|
unsigned int getNArg(void) const;
|
||||||
private:
|
private:
|
||||||
const unsigned int nArg_;
|
const unsigned int nArg_;
|
||||||
};
|
};
|
||||||
|
@ -24,30 +24,32 @@ BUILT_SOURCES = IoAsciiParser.hpp MathParser.hpp
|
|||||||
|
|
||||||
lib_LTLIBRARIES = liblatan.la
|
lib_LTLIBRARIES = liblatan.la
|
||||||
|
|
||||||
liblatan_la_SOURCES = \
|
liblatan_la_SOURCES = \
|
||||||
Exceptions.cpp \
|
CompiledFunction.cpp\
|
||||||
Function.cpp \
|
Exceptions.cpp \
|
||||||
Global.cpp \
|
Function.cpp \
|
||||||
includes.hpp \
|
Global.cpp \
|
||||||
Io.cpp \
|
includes.hpp \
|
||||||
IoAsciiParser.ypp \
|
Io.cpp \
|
||||||
IoAsciiLexer.lpp \
|
IoAsciiParser.ypp \
|
||||||
Mat.cpp \
|
IoAsciiLexer.lpp \
|
||||||
Math.cpp \
|
Mat.cpp \
|
||||||
MathCompiler.cpp \
|
Math.cpp \
|
||||||
MathParser.ypp \
|
MathInterpreter.cpp \
|
||||||
MathLexer.lpp \
|
MathParser.ypp \
|
||||||
Sample.cpp \
|
MathLexer.lpp \
|
||||||
|
Sample.cpp \
|
||||||
../config.h
|
../config.h
|
||||||
liblatan_ladir = $(pkgincludedir)
|
liblatan_ladir = $(pkgincludedir)
|
||||||
liblatan_la_HEADERS = \
|
liblatan_la_HEADERS = \
|
||||||
Function.hpp \
|
CompiledFunction.hpp\
|
||||||
Global.hpp \
|
Function.hpp \
|
||||||
Io.hpp \
|
Global.hpp \
|
||||||
IoObject.hpp \
|
Io.hpp \
|
||||||
Mat.hpp \
|
IoObject.hpp \
|
||||||
Math.hpp \
|
Mat.hpp \
|
||||||
MathCompiler.hpp \
|
Math.hpp \
|
||||||
|
MathInterpreter.hpp \
|
||||||
Sample.hpp
|
Sample.hpp
|
||||||
liblatan_la_CFLAGS = $(COM_CFLAGS)
|
liblatan_la_CFLAGS = $(COM_CFLAGS)
|
||||||
liblatan_la_CXXFLAGS = $(COM_CXXFLAGS)
|
liblatan_la_CXXFLAGS = $(COM_CXXFLAGS)
|
||||||
|
534
latan/MathInterpreter.cpp
Normal file
534
latan/MathInterpreter.cpp
Normal file
@ -0,0 +1,534 @@
|
|||||||
|
#include <latan/MathInterpreter.hpp>
|
||||||
|
#include <latan/includes.hpp>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace Latan;
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
* MathNode implementation *
|
||||||
|
******************************************************************************/
|
||||||
|
// constructor /////////////////////////////////////////////////////////////////
|
||||||
|
MathNode::MathNode(const string &name, const unsigned int type)
|
||||||
|
: name_(name)
|
||||||
|
, type_(type)
|
||||||
|
, parent_(NULL)
|
||||||
|
{}
|
||||||
|
|
||||||
|
MathNode::MathNode(const std::string &name, const unsigned int type,\
|
||||||
|
const unsigned int nArg, ...)
|
||||||
|
: name_(name)
|
||||||
|
, type_(type)
|
||||||
|
, arg_(nArg)
|
||||||
|
, parent_(NULL)
|
||||||
|
{
|
||||||
|
va_list va;
|
||||||
|
|
||||||
|
va_start(va, nArg);
|
||||||
|
for (unsigned int i = 0; i < nArg; ++i)
|
||||||
|
{
|
||||||
|
arg_[i] = va_arg(va, MathNode *);
|
||||||
|
arg_[i]->parent_ = this;
|
||||||
|
}
|
||||||
|
va_end(va);
|
||||||
|
}
|
||||||
|
|
||||||
|
// destructor //////////////////////////////////////////////////////////////////
|
||||||
|
MathNode::~MathNode(void)
|
||||||
|
{
|
||||||
|
vector<MathNode *>::iterator i;
|
||||||
|
|
||||||
|
for (i = arg_.begin(); i != arg_.end(); ++i)
|
||||||
|
{
|
||||||
|
delete *i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// access //////////////////////////////////////////////////////////////////////
|
||||||
|
const string &MathNode::getName(void) const
|
||||||
|
{
|
||||||
|
return name_;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int MathNode::getType(void) const
|
||||||
|
{
|
||||||
|
return type_;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int MathNode::getNArg(void) const
|
||||||
|
{
|
||||||
|
return static_cast<unsigned int>(arg_.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
const MathNode * MathNode::getParent(void) const
|
||||||
|
{
|
||||||
|
return parent_;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int MathNode::getLevel(void) const
|
||||||
|
{
|
||||||
|
if (getParent())
|
||||||
|
{
|
||||||
|
return getParent()->getLevel() + 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MathNode::setName(const std::string &name)
|
||||||
|
{
|
||||||
|
name_ = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MathNode::pushArg(MathNode *node)
|
||||||
|
{
|
||||||
|
arg_.push_back(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
// operators ///////////////////////////////////////////////////////////////////
|
||||||
|
const MathNode &MathNode::operator[](const unsigned int i) const
|
||||||
|
{
|
||||||
|
return *arg_[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
ostream &Latan::operator<<(ostream &out, const MathNode &n)
|
||||||
|
{
|
||||||
|
unsigned int level = n.getLevel();
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i <= level; ++i)
|
||||||
|
{
|
||||||
|
if (i == level)
|
||||||
|
{
|
||||||
|
out << "_";
|
||||||
|
}
|
||||||
|
else if (i == level - 1)
|
||||||
|
{
|
||||||
|
out << "|";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
out << " ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out << " " << n.getName() << " (type " << n.getType() << ")" << endl;
|
||||||
|
for (unsigned int i = 0; i < n.getNArg(); ++i)
|
||||||
|
{
|
||||||
|
out << n[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
* Instruction set *
|
||||||
|
******************************************************************************/
|
||||||
|
#define CODE_WIDTH 6
|
||||||
|
#define CODE_MOD setw(CODE_WIDTH) << left
|
||||||
|
|
||||||
|
Instruction::~Instruction(void)
|
||||||
|
{}
|
||||||
|
|
||||||
|
ostream &Latan::operator<<(ostream& out, const Instruction& ins)
|
||||||
|
{
|
||||||
|
ins.print(out);
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
Push::Push(const double val)
|
||||||
|
: type_(ArgType::Constant)
|
||||||
|
, val_(val)
|
||||||
|
, name_("")
|
||||||
|
{}
|
||||||
|
|
||||||
|
Push::Push(const string &name)
|
||||||
|
: type_(ArgType::Variable)
|
||||||
|
, val_(0.0)
|
||||||
|
, name_(name)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void Push::operator()(RunContext &context) const
|
||||||
|
{
|
||||||
|
if (type_ == ArgType::Constant)
|
||||||
|
{
|
||||||
|
context.dStack.push(val_);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (keyExists(name_, context.vTable))
|
||||||
|
{
|
||||||
|
context.dStack.push(context.vTable[name_]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LATAN_ERROR(Range, "unknown variable '" + name_ + "'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
context.insIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Push::print(std::ostream &out) const
|
||||||
|
{
|
||||||
|
out << CODE_MOD << "push";
|
||||||
|
if (type_ == ArgType::Constant)
|
||||||
|
{
|
||||||
|
out << CODE_MOD << val_;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
out << CODE_MOD << name_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Pop::Pop(const string &name)
|
||||||
|
: name_(name)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void Pop::operator()(RunContext &context) const
|
||||||
|
{
|
||||||
|
if (!name_.empty())
|
||||||
|
{
|
||||||
|
context.vTable[name_] = context.dStack.top();
|
||||||
|
}
|
||||||
|
context.dStack.pop();
|
||||||
|
context.insIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Pop::print(std::ostream &out) const
|
||||||
|
{
|
||||||
|
out << CODE_MOD << "pop" << CODE_MOD << name_;
|
||||||
|
}
|
||||||
|
|
||||||
|
Store::Store(const string &name)
|
||||||
|
: name_(name)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void Store::operator()(RunContext &context) const
|
||||||
|
{
|
||||||
|
if (!name_.empty())
|
||||||
|
{
|
||||||
|
context.vTable[name_] = context.dStack.top();
|
||||||
|
}
|
||||||
|
context.insIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Store::print(std::ostream &out) const
|
||||||
|
{
|
||||||
|
out << CODE_MOD << "store" << CODE_MOD << name_;
|
||||||
|
}
|
||||||
|
|
||||||
|
Call::Call(const string &name)
|
||||||
|
: name_(name)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void Call::operator()(RunContext &context) const
|
||||||
|
{
|
||||||
|
if (keyExists(name_, context.fTable))
|
||||||
|
{
|
||||||
|
context.dStack.push((*context.fTable[name_])(context.dStack));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LATAN_ERROR(Range, "unknown function '" + name_ + "'");
|
||||||
|
}
|
||||||
|
context.insIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Call::print(std::ostream &out) const
|
||||||
|
{
|
||||||
|
out << CODE_MOD << "call" << CODE_MOD << name_;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define DEF_OP(name, nArg, exp, insName)\
|
||||||
|
void name::operator()(RunContext &context) const\
|
||||||
|
{\
|
||||||
|
double x[nArg];\
|
||||||
|
for (int i = 0; i < nArg; ++i)\
|
||||||
|
{\
|
||||||
|
x[nArg-1-i] = context.dStack.top();\
|
||||||
|
context.dStack.pop();\
|
||||||
|
}\
|
||||||
|
context.dStack.push(exp);\
|
||||||
|
context.insIndex++;\
|
||||||
|
}\
|
||||||
|
void name::print(std::ostream &out) const\
|
||||||
|
{\
|
||||||
|
out << CODE_MOD << insName;\
|
||||||
|
}
|
||||||
|
|
||||||
|
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")
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
* MathInterpreter implementation *
|
||||||
|
******************************************************************************/
|
||||||
|
// MathParserState constructor /////////////////////////////////////////////////
|
||||||
|
MathInterpreter::MathParserState::MathParserState(istream *stream, string *name,
|
||||||
|
MathNode **data)
|
||||||
|
: ParserState<MathNode *>(stream, name, data)
|
||||||
|
{
|
||||||
|
initScanner();
|
||||||
|
}
|
||||||
|
|
||||||
|
// MathParserState destructor //////////////////////////////////////////////////
|
||||||
|
MathInterpreter::MathParserState::~MathParserState(void)
|
||||||
|
{
|
||||||
|
destroyScanner();
|
||||||
|
}
|
||||||
|
|
||||||
|
// constructors ////////////////////////////////////////////////////////////////
|
||||||
|
MathInterpreter::MathInterpreter(void)
|
||||||
|
: code_(NULL)
|
||||||
|
, codeName_("<no_code>")
|
||||||
|
, state_(NULL)
|
||||||
|
, root_(NULL)
|
||||||
|
, gotReturn_(false)
|
||||||
|
, status_(Status::none)
|
||||||
|
{}
|
||||||
|
|
||||||
|
MathInterpreter::MathInterpreter(const std::string &code)
|
||||||
|
: code_(NULL)
|
||||||
|
, codeName_("<string>")
|
||||||
|
, state_(NULL)
|
||||||
|
, root_(NULL)
|
||||||
|
, gotReturn_(false)
|
||||||
|
, status_(Status::none)
|
||||||
|
{
|
||||||
|
setCode(code);
|
||||||
|
}
|
||||||
|
|
||||||
|
// destructor //////////////////////////////////////////////////////////////////
|
||||||
|
MathInterpreter::~MathInterpreter(void)
|
||||||
|
{
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
// access //////////////////////////////////////////////////////////////////////
|
||||||
|
const Instruction * MathInterpreter::operator[](const unsigned int i) const
|
||||||
|
{
|
||||||
|
return program_[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
const MathNode * MathInterpreter::getAST(void) const
|
||||||
|
{
|
||||||
|
if (root_)
|
||||||
|
{
|
||||||
|
return root_;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MathInterpreter::push(const Instruction *i)
|
||||||
|
{
|
||||||
|
program_.push_back(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
// initialization //////////////////////////////////////////////////////////////
|
||||||
|
void MathInterpreter::setCode(const std::string &code)
|
||||||
|
{
|
||||||
|
if (status_)
|
||||||
|
{
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
code_ = new stringstream(code);
|
||||||
|
codeName_ = "<string>";
|
||||||
|
state_ = new MathParserState(code_, &codeName_, &root_);
|
||||||
|
status_ = Status::initialised;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MathInterpreter::reset(void)
|
||||||
|
{
|
||||||
|
InstructionContainer::iterator i;
|
||||||
|
|
||||||
|
delete code_;
|
||||||
|
codeName_ = "<no_code>";
|
||||||
|
delete state_;
|
||||||
|
delete root_;
|
||||||
|
for (i = program_.begin(); i != program_.end(); ++i)
|
||||||
|
{
|
||||||
|
delete *i;
|
||||||
|
}
|
||||||
|
program_.clear();
|
||||||
|
status_ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// parser //////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Bison/Flex parser declaration
|
||||||
|
int _math_parse(MathInterpreter::MathParserState* state);
|
||||||
|
|
||||||
|
void MathInterpreter::parse(void)
|
||||||
|
{
|
||||||
|
_math_parse(state_);
|
||||||
|
}
|
||||||
|
|
||||||
|
// interpreter /////////////////////////////////////////////////////////////////
|
||||||
|
void MathInterpreter::compile(void)
|
||||||
|
{
|
||||||
|
if (!(status_ & Status::parsed))
|
||||||
|
{
|
||||||
|
parse();
|
||||||
|
status_ |= Status::parsed;
|
||||||
|
status_ -= status_ & Status::compiled;
|
||||||
|
}
|
||||||
|
gotReturn_ = false;
|
||||||
|
if (root_)
|
||||||
|
{
|
||||||
|
compileNode(*root_);
|
||||||
|
}
|
||||||
|
if (!root_||!gotReturn_)
|
||||||
|
{
|
||||||
|
LATAN_ERROR(Syntax, "expected 'return' in program '" + codeName_ + "'");
|
||||||
|
}
|
||||||
|
status_ |= Status::compiled;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define IFNODE(name, nArg) if ((n.getName() == (name))&&(n.getNArg() == nArg))
|
||||||
|
#define ELIFNODE(name, nArg) else IFNODE(name, nArg)
|
||||||
|
#define ELSE else
|
||||||
|
|
||||||
|
void MathInterpreter::compileNode(const MathNode& n)
|
||||||
|
{
|
||||||
|
if (!gotReturn_)
|
||||||
|
{
|
||||||
|
switch (n.getType())
|
||||||
|
{
|
||||||
|
case MathNode::Type::cst:
|
||||||
|
program_.push_back(new Push(strTo<double>(n.getName())));
|
||||||
|
break;
|
||||||
|
case MathNode::Type::var:
|
||||||
|
program_.push_back(new Push(n.getName()));
|
||||||
|
break;
|
||||||
|
case MathNode::Type::op:
|
||||||
|
// semicolon
|
||||||
|
if (n.getName() == ";")
|
||||||
|
{
|
||||||
|
// compile relevant statements
|
||||||
|
for (unsigned int i = 0; i < n.getNArg(); ++i)
|
||||||
|
{
|
||||||
|
bool isAssign =
|
||||||
|
((n[i].getType() == MathNode::Type::op)&&
|
||||||
|
(n[i].getName() == "="));
|
||||||
|
bool isSemiColumn =
|
||||||
|
((n[i].getType() == MathNode::Type::op)&&
|
||||||
|
(n[i].getName() == ";"));
|
||||||
|
bool isKeyword =
|
||||||
|
(n[i].getType() == MathNode::Type::keyw);
|
||||||
|
|
||||||
|
if (isAssign||isSemiColumn||isKeyword)
|
||||||
|
{
|
||||||
|
compileNode(n[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// assignment
|
||||||
|
else if (n.getName() == "=")
|
||||||
|
{
|
||||||
|
// variable assignement
|
||||||
|
if (n[0].getType() == MathNode::Type::var)
|
||||||
|
{
|
||||||
|
bool hasSemicolonParent = ((n.getParent() != NULL) &&
|
||||||
|
(n.getParent()->getType()
|
||||||
|
== MathNode::Type::op)&&
|
||||||
|
(n.getParent()->getName()
|
||||||
|
== ";"));
|
||||||
|
// compile the RHS
|
||||||
|
compileNode(n[1]);
|
||||||
|
// pop instruction if at the end of a statement
|
||||||
|
if (hasSemicolonParent)
|
||||||
|
{
|
||||||
|
program_.push_back(new Pop(n[0].getName()));
|
||||||
|
}
|
||||||
|
// store instruction else
|
||||||
|
else
|
||||||
|
{
|
||||||
|
program_.push_back(new Store(n[0].getName()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LATAN_ERROR(Compilation, "invalid LHS for '='");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// arithmetic operators
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (unsigned int i = 0; i < n.getNArg(); ++i)
|
||||||
|
{
|
||||||
|
compileNode(n[i]);
|
||||||
|
}
|
||||||
|
IFNODE("-", 1) program_.push_back(new Neg);
|
||||||
|
ELIFNODE("+", 2) program_.push_back(new Add);
|
||||||
|
ELIFNODE("-", 2) program_.push_back(new Sub);
|
||||||
|
ELIFNODE("*", 2) program_.push_back(new Mul);
|
||||||
|
ELIFNODE("/", 2) program_.push_back(new Div);
|
||||||
|
ELIFNODE("^", 2) program_.push_back(new Pow);
|
||||||
|
ELSE LATAN_ERROR(Compilation, "unknown operator '"
|
||||||
|
+ n.getName() + "'");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MathNode::Type::keyw:
|
||||||
|
if (n.getName() == "return")
|
||||||
|
{
|
||||||
|
compileNode(n[0]);
|
||||||
|
gotReturn_ = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LATAN_ERROR(Compilation, "unknown keyword '" + n.getName()
|
||||||
|
+ "'");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MathNode::Type::func:
|
||||||
|
for (unsigned int i = 0; i < n.getNArg(); ++i)
|
||||||
|
{
|
||||||
|
compileNode(n[i]);
|
||||||
|
}
|
||||||
|
program_.push_back(new Call(n.getName()));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LATAN_ERROR(Compilation,
|
||||||
|
"unknown node type (node named '" + n.getName()
|
||||||
|
+ "')");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// execution ///////////////////////////////////////////////////////////////////
|
||||||
|
void MathInterpreter::operator()(RunContext &context)
|
||||||
|
{
|
||||||
|
if (!(status_ & Status::compiled))
|
||||||
|
{
|
||||||
|
compile();
|
||||||
|
}
|
||||||
|
execute(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MathInterpreter::execute(RunContext &context) const
|
||||||
|
{
|
||||||
|
context.insIndex = 0;
|
||||||
|
while (context.insIndex != program_.size())
|
||||||
|
{
|
||||||
|
(*(program_[context.insIndex]))(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// IO //////////////////////////////////////////////////////////////////////////
|
||||||
|
ostream &Latan::operator<<(ostream &out, const MathInterpreter &program)
|
||||||
|
{
|
||||||
|
for (unsigned int i = 0; i < program.program_.size(); ++i)
|
||||||
|
{
|
||||||
|
out << *(program.program_[i]) << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
251
latan/MathInterpreter.hpp
Normal file
251
latan/MathInterpreter.hpp
Normal file
@ -0,0 +1,251 @@
|
|||||||
|
#ifndef LATAN_MATHCOMPILER_HPP_
|
||||||
|
#define LATAN_MATHCOMPILER_HPP_
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <map>
|
||||||
|
#include <queue>
|
||||||
|
#include <string>
|
||||||
|
#include <stack>
|
||||||
|
#include <latan/Function.hpp>
|
||||||
|
#include <latan/Global.hpp>
|
||||||
|
#include <latan/ParserState.hpp>
|
||||||
|
|
||||||
|
#define MAXIDLENGTH 256
|
||||||
|
|
||||||
|
LATAN_BEGIN_CPPDECL
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
* Parser classes *
|
||||||
|
******************************************************************************/
|
||||||
|
class MathNode
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
class Type
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
undef = -1,
|
||||||
|
cst = 0,
|
||||||
|
op = 1,
|
||||||
|
var = 2,
|
||||||
|
keyw = 3,
|
||||||
|
func = 4
|
||||||
|
};
|
||||||
|
};
|
||||||
|
public:
|
||||||
|
// constructor
|
||||||
|
MathNode(const std::string &name, const unsigned int type);
|
||||||
|
MathNode(const std::string &name, const unsigned int type,
|
||||||
|
const unsigned int nArg, ...);
|
||||||
|
// destructor
|
||||||
|
virtual ~MathNode();
|
||||||
|
// access
|
||||||
|
const std::string& getName(void) const;
|
||||||
|
unsigned int getType(void) const;
|
||||||
|
unsigned int getNArg(void) const;
|
||||||
|
const MathNode * getParent(void) const;
|
||||||
|
unsigned int getLevel(void) const;
|
||||||
|
void setName(const std::string &name);
|
||||||
|
void pushArg(MathNode *node);
|
||||||
|
// operator
|
||||||
|
const MathNode &operator[](const unsigned int i) const;
|
||||||
|
private:
|
||||||
|
std::string name_;
|
||||||
|
unsigned int type_;
|
||||||
|
std::vector<MathNode *> arg_;
|
||||||
|
const MathNode * parent_;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::ostream &operator<<(std::ostream &out, const MathNode &n);
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
* Instruction classes *
|
||||||
|
******************************************************************************/
|
||||||
|
typedef std::map<std::string, double> VarTable;
|
||||||
|
typedef std::map<std::string, DoubleFunction *> FunctionTable;
|
||||||
|
|
||||||
|
struct RunContext
|
||||||
|
{
|
||||||
|
unsigned int insIndex;
|
||||||
|
std::stack<double> dStack;
|
||||||
|
VarTable vTable;
|
||||||
|
FunctionTable fTable;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Abstract base
|
||||||
|
class Instruction
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~Instruction();
|
||||||
|
// instruction execution
|
||||||
|
virtual void operator()(RunContext &context) const = 0;
|
||||||
|
friend std::ostream& operator<<(std::ostream &out, const Instruction &ins);
|
||||||
|
private:
|
||||||
|
virtual void print(std::ostream &out) const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Push
|
||||||
|
class Push: public Instruction
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
class ArgType
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
Constant = 0,
|
||||||
|
Variable = 1
|
||||||
|
};
|
||||||
|
};
|
||||||
|
public:
|
||||||
|
//constructors
|
||||||
|
explicit Push(const double val);
|
||||||
|
explicit Push(const std::string &name);
|
||||||
|
// instruction execution
|
||||||
|
virtual void operator()(RunContext &context) const;
|
||||||
|
private:
|
||||||
|
virtual void print(std::ostream& out) const;
|
||||||
|
private:
|
||||||
|
unsigned int type_;
|
||||||
|
double val_;
|
||||||
|
std::string name_;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Pop
|
||||||
|
class Pop: public Instruction
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//constructor
|
||||||
|
explicit Pop(const std::string &name);
|
||||||
|
// instruction execution
|
||||||
|
virtual void operator()(RunContext &context) const;
|
||||||
|
private:
|
||||||
|
virtual void print(std::ostream& out) const;
|
||||||
|
private:
|
||||||
|
std::string name_;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Store
|
||||||
|
class Store: public Instruction
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//constructor
|
||||||
|
explicit Store(const std::string &name);
|
||||||
|
// instruction execution
|
||||||
|
virtual void operator()(RunContext &context) const;
|
||||||
|
private:
|
||||||
|
virtual void print(std::ostream& out) const;
|
||||||
|
private:
|
||||||
|
std::string name_;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Call function
|
||||||
|
class Call: public Instruction
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//constructor
|
||||||
|
explicit Call(const std::string &name);
|
||||||
|
// instruction execution
|
||||||
|
virtual void operator()(RunContext &context) const;
|
||||||
|
private:
|
||||||
|
virtual void print(std::ostream& out) const;
|
||||||
|
private:
|
||||||
|
std::string name_;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Floating point operations
|
||||||
|
#define DECL_OP(name)\
|
||||||
|
class name: public Instruction\
|
||||||
|
{\
|
||||||
|
public:\
|
||||||
|
virtual void operator()(RunContext &context) const;\
|
||||||
|
private:\
|
||||||
|
virtual void print(std::ostream &out) const;\
|
||||||
|
}
|
||||||
|
|
||||||
|
DECL_OP(Neg);
|
||||||
|
DECL_OP(Add);
|
||||||
|
DECL_OP(Sub);
|
||||||
|
DECL_OP(Mul);
|
||||||
|
DECL_OP(Div);
|
||||||
|
DECL_OP(Pow);
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
* Compiler class *
|
||||||
|
******************************************************************************/
|
||||||
|
class MathInterpreter
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
// parser state
|
||||||
|
class MathParserState: public ParserState<MathNode *>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// constructor
|
||||||
|
explicit MathParserState(std::istream *stream, std::string *name,
|
||||||
|
MathNode **data);
|
||||||
|
// destructor
|
||||||
|
virtual ~MathParserState(void);
|
||||||
|
private:
|
||||||
|
// allocation/deallocation functions defined in MathLexer.lpp
|
||||||
|
virtual void initScanner(void);
|
||||||
|
virtual void destroyScanner(void);
|
||||||
|
};
|
||||||
|
private:
|
||||||
|
// status flags
|
||||||
|
class Status
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
none = 0,
|
||||||
|
initialised = 1 << 0,
|
||||||
|
parsed = 1 << 1,
|
||||||
|
compiled = 1 << 2
|
||||||
|
};
|
||||||
|
};
|
||||||
|
// instruction container
|
||||||
|
typedef std::vector<const Instruction *> InstructionContainer;
|
||||||
|
public:
|
||||||
|
// constructors
|
||||||
|
MathInterpreter(void);
|
||||||
|
MathInterpreter(const std::string &code);
|
||||||
|
// destructor
|
||||||
|
~MathInterpreter(void);
|
||||||
|
// access
|
||||||
|
const Instruction * operator[](const unsigned int i) const;
|
||||||
|
const MathNode * getAST(void) const;
|
||||||
|
// initialization
|
||||||
|
void setCode(const std::string &code);
|
||||||
|
// interpreter
|
||||||
|
void compile(void);
|
||||||
|
// execution
|
||||||
|
void operator()(RunContext &context);
|
||||||
|
// IO
|
||||||
|
friend std::ostream &operator<<(std::ostream &out,
|
||||||
|
const MathInterpreter &program);
|
||||||
|
private:
|
||||||
|
// initialization
|
||||||
|
void reset(void);
|
||||||
|
// access
|
||||||
|
void push(const Instruction *i);
|
||||||
|
// parser
|
||||||
|
void parse(void);
|
||||||
|
// interpreter
|
||||||
|
void compileNode(const MathNode &node);
|
||||||
|
// execution
|
||||||
|
void execute(RunContext &context) const;
|
||||||
|
private:
|
||||||
|
std::istream *code_;
|
||||||
|
std::string codeName_;
|
||||||
|
MathParserState *state_;
|
||||||
|
MathNode *root_;
|
||||||
|
bool gotReturn_;
|
||||||
|
InstructionContainer program_;
|
||||||
|
unsigned int status_;
|
||||||
|
};
|
||||||
|
|
||||||
|
LATAN_END_CPPDECL
|
||||||
|
|
||||||
|
#endif
|
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
%{
|
%{
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <latan/MathCompiler.hpp>
|
#include <latan/MathInterpreter.hpp>
|
||||||
#include <latan/MathParser.hpp>
|
#include <latan/MathParser.hpp>
|
||||||
#pragma GCC diagnostic ignored "-Wsign-compare"
|
#pragma GCC diagnostic ignored "-Wsign-compare"
|
||||||
#pragma GCC diagnostic ignored "-Wunused-function"
|
#pragma GCC diagnostic ignored "-Wunused-function"
|
||||||
@ -16,7 +16,7 @@
|
|||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace Latan;
|
using namespace Latan;
|
||||||
|
|
||||||
#define YY_EXTRA_TYPE MathCompiler::MathParserState *
|
#define YY_EXTRA_TYPE MathInterpreter::MathParserState *
|
||||||
#define YY_USER_ACTION \
|
#define YY_USER_ACTION \
|
||||||
yylloc->first_line = yylloc->last_line = yylineno;\
|
yylloc->first_line = yylloc->last_line = yylineno;\
|
||||||
yylloc->first_column = yylloc->last_column + 1;\
|
yylloc->first_column = yylloc->last_column + 1;\
|
||||||
@ -62,13 +62,13 @@ return {RETTOK(RETURN);}
|
|||||||
|
|
||||||
%%
|
%%
|
||||||
|
|
||||||
void MathCompiler::MathParserState::initScanner()
|
void MathInterpreter::MathParserState::initScanner()
|
||||||
{
|
{
|
||||||
yylex_init(&scanner);
|
yylex_init(&scanner);
|
||||||
yyset_extra(this, scanner);
|
yyset_extra(this, scanner);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MathCompiler::MathParserState::destroyScanner()
|
void MathInterpreter::MathParserState::destroyScanner()
|
||||||
{
|
{
|
||||||
yylex_destroy(scanner);
|
yylex_destroy(scanner);
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <latan/Global.hpp>
|
#include <latan/Global.hpp>
|
||||||
#include <latan/MathCompiler.hpp>
|
#include <latan/MathInterpreter.hpp>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace Latan;
|
using namespace Latan;
|
||||||
@ -14,7 +14,7 @@
|
|||||||
%locations
|
%locations
|
||||||
%defines
|
%defines
|
||||||
%error-verbose
|
%error-verbose
|
||||||
%parse-param { Latan::MathCompiler::MathParserState *state }
|
%parse-param { Latan::MathInterpreter::MathParserState *state }
|
||||||
%initial-action {yylloc.last_column = 0;}
|
%initial-action {yylloc.last_column = 0;}
|
||||||
%lex-param { void* scanner }
|
%lex-param { void* scanner }
|
||||||
|
|
||||||
@ -42,7 +42,7 @@
|
|||||||
%{
|
%{
|
||||||
int _math_lex(YYSTYPE *lvalp, YYLTYPE *llocp, void *scanner);
|
int _math_lex(YYSTYPE *lvalp, YYLTYPE *llocp, void *scanner);
|
||||||
|
|
||||||
void _math_error(YYLTYPE *locp, MathCompiler::MathParserState *state,
|
void _math_error(YYLTYPE *locp, MathInterpreter::MathParserState *state,
|
||||||
const char *err)
|
const char *err)
|
||||||
{
|
{
|
||||||
stringstream buf;
|
stringstream buf;
|
||||||
|
Loading…
Reference in New Issue
Block a user