mirror of
https://github.com/aportelli/LatAnalyze.git
synced 2025-04-11 03:20:46 +01:00
first working version of the math compiler
This commit is contained in:
parent
c0b8ec6ecd
commit
2efc4ef6c5
6
.gitignore
vendored
6
.gitignore
vendored
@ -41,9 +41,9 @@ stamp-h1
|
|||||||
myconfig.sh
|
myconfig.sh
|
||||||
|
|
||||||
# bison/flex generated sources
|
# bison/flex generated sources
|
||||||
latan/IOASCIILexer.cpp
|
latan/*Lexer.cpp
|
||||||
latan/IOASCIIParser.cpp
|
latan/*Parser.cpp
|
||||||
latan/IOASCIIParser.hpp
|
latan/*Parser.hpp
|
||||||
|
|
||||||
# Eigen headers
|
# Eigen headers
|
||||||
latan/Eigen/*
|
latan/Eigen/*
|
||||||
|
@ -1,10 +1,27 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <latan/IO.hpp>
|
#include <latan/MathCompiler.hpp>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace Latan;
|
using namespace Latan;
|
||||||
|
|
||||||
int main(void)
|
int main(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
MathCompiler C(argv[1]);
|
||||||
|
VarTable vtable;
|
||||||
|
stack<double> dstack;
|
||||||
|
const VirtualProgram& P = C();
|
||||||
|
|
||||||
|
cout << P << endl;
|
||||||
|
for (int i=0;i<P.size();++i)
|
||||||
|
{
|
||||||
|
(*(P[i]))(dstack,vtable);
|
||||||
|
}
|
||||||
|
cout << "result= " << dstack.top() << endl;
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*int main(void)
|
||||||
{
|
{
|
||||||
ASCIIFile F;
|
ASCIIFile F;
|
||||||
DMat A,B;
|
DMat A,B;
|
||||||
@ -17,7 +34,7 @@ int main(void)
|
|||||||
cout << A*B << endl;
|
cout << A*B << endl;
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
int main(void)
|
int main(void)
|
||||||
|
@ -23,6 +23,7 @@ CONST_EXC(Implementation,Logic("implementation error: "+msg,loc))
|
|||||||
CONST_EXC(Range,Logic("range error: "+msg,loc))
|
CONST_EXC(Range,Logic("range 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(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(Syntax,Runtime("syntax error: "+msg,loc))
|
||||||
|
@ -27,6 +27,7 @@ namespace Exceptions
|
|||||||
DECL_EXC(Range,Logic);
|
DECL_EXC(Range,Logic);
|
||||||
// runtime errors
|
// runtime errors
|
||||||
DECL_EXC(Runtime,std::runtime_error);
|
DECL_EXC(Runtime,std::runtime_error);
|
||||||
|
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(Syntax,Runtime);
|
||||||
|
@ -50,9 +50,9 @@ void File::DeleteData(void)
|
|||||||
* ASCIIParserState implementation *
|
* ASCIIParserState implementation *
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
// constructor /////////////////////////////////////////////////////////////////
|
// constructor /////////////////////////////////////////////////////////////////
|
||||||
ASCIIParserState::ASCIIParserState(istream* pt_istream, string* name,\
|
ASCIIParserState::ASCIIParserState(istream* pt_istream, string* pt_name,\
|
||||||
IODataTable* pt_data)
|
IODataTable* pt_data)
|
||||||
: data(pt_data), stream(pt_istream), stream_name(name)
|
: ParserState<IODataTable>(pt_istream, pt_name, pt_data)
|
||||||
{
|
{
|
||||||
init_scanner();
|
init_scanner();
|
||||||
}
|
}
|
||||||
@ -158,4 +158,5 @@ void ASCIIFile::CloseASCII(void)
|
|||||||
void ASCIIFile::Parse()
|
void ASCIIFile::Parse()
|
||||||
{
|
{
|
||||||
_IOASCII_parse(state);
|
_IOASCII_parse(state);
|
||||||
|
is_parsed = true;
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#include <latan/Global.hpp>
|
#include <latan/Global.hpp>
|
||||||
#include <latan/IOObject.hpp>
|
#include <latan/IOObject.hpp>
|
||||||
#include <latan/Mat.hpp>
|
#include <latan/Mat.hpp>
|
||||||
|
#include <latan/ParserState.hpp>
|
||||||
#include <latan/Sample.hpp>
|
#include <latan/Sample.hpp>
|
||||||
|
|
||||||
LATAN_BEGIN_CPPDECL
|
LATAN_BEGIN_CPPDECL
|
||||||
@ -76,7 +77,7 @@ const IOObj& File::GetData(const std::string data_name)
|
|||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* ASCII datafile class *
|
* ASCII datafile class *
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
class ASCIIParserState
|
class ASCIIParserState: public ParserState<IODataTable>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// constructor
|
// constructor
|
||||||
@ -85,12 +86,8 @@ public:
|
|||||||
// destructor
|
// destructor
|
||||||
virtual ~ASCIIParserState(void);
|
virtual ~ASCIIParserState(void);
|
||||||
// public members
|
// public members
|
||||||
IODataTable* data;
|
|
||||||
std::stack<DMat> dmat_buf;
|
std::stack<DMat> dmat_buf;
|
||||||
std::stack<double> double_buf;
|
std::stack<double> double_buf;
|
||||||
void* scanner;
|
|
||||||
std::istream* stream;
|
|
||||||
std::string* stream_name;
|
|
||||||
private:
|
private:
|
||||||
// allocation/deallocation functions defined in IOASCIILexer.lpp
|
// allocation/deallocation functions defined in IOASCIILexer.lpp
|
||||||
void init_scanner(void);
|
void init_scanner(void);
|
||||||
@ -136,7 +133,6 @@ const IOObj& ASCIIFile::Read(const std::string data_name)
|
|||||||
if (!is_parsed)
|
if (!is_parsed)
|
||||||
{
|
{
|
||||||
Parse();
|
Parse();
|
||||||
is_parsed = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return GetData<IOObj>(data_name);
|
return GetData<IOObj>(data_name);
|
||||||
|
@ -20,7 +20,7 @@ AM_YFLAGS = -d
|
|||||||
include eigen_files.mk
|
include eigen_files.mk
|
||||||
nobase_dist_pkginclude_HEADERS = $(eigen_files)
|
nobase_dist_pkginclude_HEADERS = $(eigen_files)
|
||||||
|
|
||||||
BUILT_SOURCES = IOASCIIParser.hpp
|
BUILT_SOURCES = IOASCIIParser.hpp MathParser.hpp
|
||||||
|
|
||||||
lib_LTLIBRARIES = liblatan.la
|
lib_LTLIBRARIES = liblatan.la
|
||||||
|
|
||||||
@ -33,6 +33,9 @@ liblatan_la_SOURCES = \
|
|||||||
IOASCIILexer.lpp \
|
IOASCIILexer.lpp \
|
||||||
IOObject.cpp \
|
IOObject.cpp \
|
||||||
Mat.cpp \
|
Mat.cpp \
|
||||||
|
MathCompiler.cpp \
|
||||||
|
MathParser.ypp \
|
||||||
|
MathLexer.lpp \
|
||||||
Sample.cpp \
|
Sample.cpp \
|
||||||
../config.h
|
../config.h
|
||||||
liblatan_ladir = $(pkgincludedir)
|
liblatan_ladir = $(pkgincludedir)
|
||||||
@ -41,6 +44,7 @@ liblatan_la_HEADERS = \
|
|||||||
IO.hpp \
|
IO.hpp \
|
||||||
IOObject.hpp \
|
IOObject.hpp \
|
||||||
Mat.hpp \
|
Mat.hpp \
|
||||||
|
MathCompiler.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)
|
||||||
|
289
latan/MathCompiler.cpp
Normal file
289
latan/MathCompiler.cpp
Normal file
@ -0,0 +1,289 @@
|
|||||||
|
#include <latan/MathCompiler.hpp>
|
||||||
|
#include <latan/includes.hpp>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace Latan;
|
||||||
|
|
||||||
|
// Math Bison/Flex parser declaration
|
||||||
|
int _Math_parse(MathParserState* state);
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
* MathNode implementation *
|
||||||
|
******************************************************************************/
|
||||||
|
// constructor /////////////////////////////////////////////////////////////////
|
||||||
|
MathNode::MathNode(const string& init_str, NodeType::Type init_type)
|
||||||
|
: str(init_str), type(init_type)
|
||||||
|
{}
|
||||||
|
|
||||||
|
MathNode::MathNode(const std::string& init_str, NodeType::Type init_type,\
|
||||||
|
const unsigned int narg, ...)
|
||||||
|
: str(init_str), type(init_type), arg(narg)
|
||||||
|
{
|
||||||
|
va_list va;
|
||||||
|
|
||||||
|
va_start(va,narg);
|
||||||
|
for (unsigned int i=0;i<narg;++i)
|
||||||
|
{
|
||||||
|
arg[i] = va_arg(va,MathNode*);
|
||||||
|
}
|
||||||
|
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::String(void) const
|
||||||
|
{
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeType::Type MathNode::Type(void) const
|
||||||
|
{
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int MathNode::NArg(void) const
|
||||||
|
{
|
||||||
|
return static_cast<unsigned int>(arg.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
// operator ////////////////////////////////////////////////////////////////////
|
||||||
|
const MathNode& MathNode::operator[](const unsigned int i) const
|
||||||
|
{
|
||||||
|
return *arg[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
* MathParserState implementation *
|
||||||
|
******************************************************************************/
|
||||||
|
// constructor /////////////////////////////////////////////////////////////////
|
||||||
|
MathParserState::MathParserState(std::istream* pt_stream, std::string* pt_name,\
|
||||||
|
MathNode** pt_data)
|
||||||
|
: ParserState<MathNode*>(pt_stream,pt_name,pt_data)
|
||||||
|
{
|
||||||
|
init_scanner();
|
||||||
|
}
|
||||||
|
|
||||||
|
// destructor //////////////////////////////////////////////////////////////////
|
||||||
|
MathParserState::~MathParserState(void)
|
||||||
|
{
|
||||||
|
destroy_scanner();
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
* Instruction set *
|
||||||
|
******************************************************************************/
|
||||||
|
#define CODE_WIDTH 6
|
||||||
|
#define CODE_MOD setw(CODE_WIDTH) << left
|
||||||
|
|
||||||
|
void Instruction::Print(std::ostream &out) const
|
||||||
|
{
|
||||||
|
out << CODE_MOD << "<null>" << CODE_MOD << "ABSTRACT INSTRUCTION!";
|
||||||
|
}
|
||||||
|
|
||||||
|
ostream& Latan::operator<<(ostream& out, const Instruction& ins)
|
||||||
|
{
|
||||||
|
ins.Print(out);
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
Push::Push(const double& init_cst)
|
||||||
|
: type(Constant), cst(init_cst), vname("")
|
||||||
|
{}
|
||||||
|
|
||||||
|
Push::Push(const string& init_vname)
|
||||||
|
: type(Variable), cst(0.0), vname(init_vname)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void Push::operator()(std::stack<double> &dstack, VarTable &vtable)
|
||||||
|
{
|
||||||
|
if (type == Constant)
|
||||||
|
{
|
||||||
|
dstack.push(cst);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dstack.push(vtable[vname]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Push::Print(std::ostream &out) const
|
||||||
|
{
|
||||||
|
out << CODE_MOD << "push";
|
||||||
|
if (type == Constant)
|
||||||
|
{
|
||||||
|
out << CODE_MOD << cst;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
out << CODE_MOD << vname;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Pop::Pop(const string& init_vname)
|
||||||
|
: vname(init_vname)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void Pop::operator()(std::stack<double> &dstack, VarTable &vtable)
|
||||||
|
{
|
||||||
|
vtable[vname] = dstack.top();
|
||||||
|
dstack.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Pop::Print(std::ostream &out) const
|
||||||
|
{
|
||||||
|
out << CODE_MOD << "pop" << CODE_MOD << vname;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define DEF_OP(name,narg,exp,code_name)\
|
||||||
|
void name::operator()(stack<double>& dstack, VarTable& vtable __dumb)\
|
||||||
|
{\
|
||||||
|
double x[narg];\
|
||||||
|
for (int i=0;i<narg;++i)\
|
||||||
|
{\
|
||||||
|
x[narg-1-i] = dstack.top();\
|
||||||
|
dstack.pop();\
|
||||||
|
}\
|
||||||
|
dstack.push(exp);\
|
||||||
|
}\
|
||||||
|
void name::Print(std::ostream &out) const\
|
||||||
|
{\
|
||||||
|
out << CODE_MOD << code_name;\
|
||||||
|
}
|
||||||
|
|
||||||
|
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")
|
||||||
|
|
||||||
|
VirtualProgram::VirtualProgram(void)
|
||||||
|
: vector<Instruction*>(0)
|
||||||
|
{}
|
||||||
|
|
||||||
|
ostream& Latan::operator<<(ostream& out,const VirtualProgram& prog)
|
||||||
|
{
|
||||||
|
for (unsigned int i=0;i<prog.size();++i)
|
||||||
|
{
|
||||||
|
out << *(prog[i]) << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
* MathCompiler implementation *
|
||||||
|
******************************************************************************/
|
||||||
|
// constructors ////////////////////////////////////////////////////////////////
|
||||||
|
MathCompiler::MathCompiler(void)
|
||||||
|
: code(NULL), code_name("<no_code>"), state(NULL), root(NULL), out(), status(0)
|
||||||
|
{}
|
||||||
|
|
||||||
|
MathCompiler::MathCompiler(const std::string& code_str)
|
||||||
|
{
|
||||||
|
Init(code_str);
|
||||||
|
}
|
||||||
|
|
||||||
|
// destructor //////////////////////////////////////////////////////////////////
|
||||||
|
MathCompiler::~MathCompiler(void)
|
||||||
|
{
|
||||||
|
Reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
// public methods //////////////////////////////////////////////////////////////
|
||||||
|
void MathCompiler::Init(const std::string &code_str)
|
||||||
|
{
|
||||||
|
if (status)
|
||||||
|
{
|
||||||
|
Reset();
|
||||||
|
}
|
||||||
|
code = new stringstream(code_str);
|
||||||
|
code_name = "<string>";
|
||||||
|
state = new MathParserState(code,&code_name,&root);
|
||||||
|
status |= Initialised;
|
||||||
|
}
|
||||||
|
|
||||||
|
const VirtualProgram& MathCompiler::operator()(void)
|
||||||
|
{
|
||||||
|
if (!(status & Parsed))
|
||||||
|
{
|
||||||
|
Parse();
|
||||||
|
}
|
||||||
|
if (!(status & Compiled))
|
||||||
|
{
|
||||||
|
Compile(*root);
|
||||||
|
}
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
// private methods /////////////////////////////////////////////////////////////
|
||||||
|
void MathCompiler::Parse(void)
|
||||||
|
{
|
||||||
|
_Math_parse(state);
|
||||||
|
status |= Parsed;
|
||||||
|
status -= status & Compiled;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define IFOP(name,narg) if ((N.String() == name)&&(N.NArg() == narg))
|
||||||
|
#define ELIFOP(name,narg) else IFOP(name,narg)
|
||||||
|
#define ELSE else
|
||||||
|
void MathCompiler::Compile(const MathNode& N)
|
||||||
|
{
|
||||||
|
switch (N.Type())
|
||||||
|
{
|
||||||
|
case NodeType::Constant:
|
||||||
|
out.push_back(new Push(ato<double>(N.String())));
|
||||||
|
break;
|
||||||
|
case NodeType::Variable:
|
||||||
|
out.push_back(new Push(N.String()));
|
||||||
|
break;
|
||||||
|
case NodeType::Operator:
|
||||||
|
for (unsigned int i=0;i<N.NArg();++i)
|
||||||
|
{
|
||||||
|
Compile(N[i]);
|
||||||
|
}
|
||||||
|
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.String()+"')");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LATAN_ERROR(Compilation, \
|
||||||
|
"unknown node type (node '"+N.String()+"')");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
status |= Compiled;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MathCompiler::Reset(void)
|
||||||
|
{
|
||||||
|
VirtualProgram::iterator i;
|
||||||
|
|
||||||
|
delete code;
|
||||||
|
code_name = "<no_code>";
|
||||||
|
delete state;
|
||||||
|
delete root;
|
||||||
|
for (i=out.begin();i!=out.end();++i)
|
||||||
|
{
|
||||||
|
delete *i;
|
||||||
|
}
|
||||||
|
out.clear();
|
||||||
|
status = 0;
|
||||||
|
}
|
||||||
|
|
173
latan/MathCompiler.hpp
Normal file
173
latan/MathCompiler.hpp
Normal file
@ -0,0 +1,173 @@
|
|||||||
|
#ifndef LATAN_MATHCOMPILER_HPP_
|
||||||
|
#define LATAN_MATHCOMPILER_HPP_
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <map>
|
||||||
|
#include <queue>
|
||||||
|
#include <string>
|
||||||
|
#include <stack>
|
||||||
|
#include <latan/Global.hpp>
|
||||||
|
#include <latan/ParserState.hpp>
|
||||||
|
|
||||||
|
#define MAXIDLENGTH 256
|
||||||
|
|
||||||
|
LATAN_BEGIN_CPPDECL
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
* Parser classes *
|
||||||
|
******************************************************************************/
|
||||||
|
namespace NodeType
|
||||||
|
{
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
Constant = 0,\
|
||||||
|
Operator = 1,\
|
||||||
|
Variable = 2
|
||||||
|
} Type;
|
||||||
|
}
|
||||||
|
|
||||||
|
class MathNode
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// constructor
|
||||||
|
MathNode(const std::string& init_str, NodeType::Type init_type);
|
||||||
|
MathNode(const std::string& init_str, NodeType::Type init_type,\
|
||||||
|
const unsigned int narg, ...);
|
||||||
|
// destructor
|
||||||
|
virtual ~MathNode();
|
||||||
|
// access
|
||||||
|
const std::string& String(void) const;
|
||||||
|
NodeType::Type Type(void) const;
|
||||||
|
unsigned int NArg(void) const;
|
||||||
|
// operators
|
||||||
|
const MathNode& operator[](const unsigned int i) const;
|
||||||
|
private:
|
||||||
|
// private members
|
||||||
|
std::string str;
|
||||||
|
NodeType::Type type;
|
||||||
|
std::vector<MathNode*> arg;
|
||||||
|
};
|
||||||
|
|
||||||
|
class MathParserState: public ParserState<MathNode*>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// constructor
|
||||||
|
explicit MathParserState(std::istream* pt_stream, std::string* name,\
|
||||||
|
MathNode** pt_data);
|
||||||
|
// destructor
|
||||||
|
virtual ~MathParserState(void);
|
||||||
|
private:
|
||||||
|
// allocation/deallocation functions defined in IOASCIILexer.lpp
|
||||||
|
void init_scanner(void);
|
||||||
|
void destroy_scanner(void);
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
* Virtual machine classes *
|
||||||
|
******************************************************************************/
|
||||||
|
typedef std::map<std::string,double> VarTable;
|
||||||
|
|
||||||
|
// Abstract base
|
||||||
|
class Instruction
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~Instruction() {};
|
||||||
|
// instruction execution
|
||||||
|
virtual void operator()(std::stack<double>& dstack, VarTable& vtable) = 0;
|
||||||
|
friend std::ostream& operator<<(std::ostream& out, const Instruction& ins);
|
||||||
|
private:
|
||||||
|
virtual void Print(std::ostream& out) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
// push and pop
|
||||||
|
class Push: public Instruction
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//constructors
|
||||||
|
explicit Push(const double& init_cst);
|
||||||
|
explicit Push(const std::string& init_vname);
|
||||||
|
// instruction execution
|
||||||
|
virtual void operator()(std::stack<double>& dstack, VarTable& vtable);
|
||||||
|
private:
|
||||||
|
typedef enum {Constant = 0, Variable = 1} ArgType;
|
||||||
|
ArgType type;
|
||||||
|
double cst;
|
||||||
|
std::string vname;
|
||||||
|
virtual void Print(std::ostream& out) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Pop: public Instruction
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//constructor
|
||||||
|
explicit Pop(const std::string& init_vname);
|
||||||
|
// instruction execution
|
||||||
|
virtual void operator()(std::stack<double>& dstack, VarTable& vtable);
|
||||||
|
private:
|
||||||
|
std::string vname;
|
||||||
|
virtual void Print(std::ostream& out) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Float operations
|
||||||
|
#define DECL_OP(name)\
|
||||||
|
class name: public Instruction\
|
||||||
|
{\
|
||||||
|
public:\
|
||||||
|
virtual void operator()(std::stack<double>& dstack, VarTable& vtable);\
|
||||||
|
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);
|
||||||
|
|
||||||
|
class VirtualProgram: public std::vector<Instruction*>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
VirtualProgram(void);
|
||||||
|
friend std::ostream& operator<<(std::ostream& out, \
|
||||||
|
const VirtualProgram& prog);
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
* Compiler class *
|
||||||
|
******************************************************************************/
|
||||||
|
class MathCompiler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// constructors
|
||||||
|
MathCompiler(void);
|
||||||
|
MathCompiler(const std::string& code_str);
|
||||||
|
// destructor
|
||||||
|
~MathCompiler(void);
|
||||||
|
// initialization
|
||||||
|
void Init(const std::string& code_str);
|
||||||
|
const VirtualProgram& operator()(void);
|
||||||
|
private:
|
||||||
|
// status flags
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
Initialised = 1 << 0,
|
||||||
|
Parsed = 1 << 1,
|
||||||
|
Compiled = 1 << 2
|
||||||
|
};
|
||||||
|
// private members
|
||||||
|
std::istream* code;
|
||||||
|
std::string code_name;
|
||||||
|
MathParserState* state;
|
||||||
|
MathNode* root;
|
||||||
|
VirtualProgram out;
|
||||||
|
unsigned int status;
|
||||||
|
// private methods
|
||||||
|
void Parse(void);
|
||||||
|
void Compile(const MathNode& N);
|
||||||
|
void Reset(void);
|
||||||
|
};
|
||||||
|
|
||||||
|
LATAN_END_CPPDECL
|
||||||
|
|
||||||
|
#endif
|
75
latan/MathLexer.lpp
Normal file
75
latan/MathLexer.lpp
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
%option reentrant
|
||||||
|
%option prefix="_Math_"
|
||||||
|
%option bison-bridge
|
||||||
|
%option bison-locations
|
||||||
|
%option noyywrap
|
||||||
|
%option yylineno
|
||||||
|
|
||||||
|
%{
|
||||||
|
#include <iostream>
|
||||||
|
#include <latan/MathCompiler.hpp>
|
||||||
|
#include <latan/MathParser.hpp>
|
||||||
|
#pragma GCC diagnostic ignored "-Wsign-compare"
|
||||||
|
#pragma GCC diagnostic ignored "-Wunused-function"
|
||||||
|
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace Latan;
|
||||||
|
|
||||||
|
#define YY_EXTRA_TYPE MathParserState*
|
||||||
|
#define YY_USER_ACTION \
|
||||||
|
yylloc->first_line = yylloc->last_line = yylineno;\
|
||||||
|
yylloc->first_column = yylloc->last_column + 1;\
|
||||||
|
yylloc->last_column = yylloc->first_column + yyleng - 1;
|
||||||
|
|
||||||
|
#define YY_INPUT(buf,result,max_size) \
|
||||||
|
{ \
|
||||||
|
(*yyextra->stream).read(buf,max_size);\
|
||||||
|
result = (*yyextra->stream).gcount();\
|
||||||
|
}
|
||||||
|
|
||||||
|
#define YY_DEBUG 0
|
||||||
|
#if (YY_DEBUG == 1)
|
||||||
|
#define RET(var) cout << (var) << "(" << yytext << ")" << endl; return (var)
|
||||||
|
#define RETTOK(tok) cout << #tok << "(" << yytext << ")" << endl; return tok
|
||||||
|
#else
|
||||||
|
#define RET(var) return (var)
|
||||||
|
#define RETTOK(tok) return tok
|
||||||
|
#endif
|
||||||
|
%}
|
||||||
|
|
||||||
|
DIGIT [0-9]
|
||||||
|
ALPHA [a-zA-Z_]
|
||||||
|
FLOAT (({DIGIT}+(\.{DIGIT}*)?)|({DIGIT}*\.{DIGIT}+))([eE][+-]?{DIGIT}+)?
|
||||||
|
OP [+\-*/^]
|
||||||
|
PAR [()]
|
||||||
|
BLANK [ \t]
|
||||||
|
|
||||||
|
%%
|
||||||
|
|
||||||
|
{FLOAT} {
|
||||||
|
strncpy(yylval->val_str,yytext,MAXIDLENGTH);
|
||||||
|
RETTOK(FLOAT);
|
||||||
|
}
|
||||||
|
{OP} {RET(*yytext);}
|
||||||
|
{PAR} {RET(*yytext);}
|
||||||
|
{ALPHA}({ALPHA}|{DIGIT})* {
|
||||||
|
strncpy(yylval->val_str,yytext,MAXIDLENGTH);
|
||||||
|
RETTOK(ID);
|
||||||
|
}
|
||||||
|
<*>\n {yylloc->last_column = 0;}
|
||||||
|
<*>{BLANK}
|
||||||
|
<*>. {yylval->val_char = yytext[0]; RETTOK(ERR);}
|
||||||
|
|
||||||
|
%%
|
||||||
|
|
||||||
|
void MathParserState::init_scanner()
|
||||||
|
{
|
||||||
|
yylex_init(&scanner);
|
||||||
|
yyset_extra(this, scanner);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MathParserState::destroy_scanner()
|
||||||
|
{
|
||||||
|
yylex_destroy(scanner);
|
||||||
|
}
|
72
latan/MathParser.ypp
Normal file
72
latan/MathParser.ypp
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
%{
|
||||||
|
#include <iostream>
|
||||||
|
#include <sstream>
|
||||||
|
#include <cstring>
|
||||||
|
#include <latan/Global.hpp>
|
||||||
|
#include <latan/MathCompiler.hpp>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace Latan;
|
||||||
|
%}
|
||||||
|
|
||||||
|
%pure-parser
|
||||||
|
%name-prefix="_Math_"
|
||||||
|
%locations
|
||||||
|
%defines
|
||||||
|
%error-verbose
|
||||||
|
%parse-param { Latan::MathParserState* state }
|
||||||
|
%initial-action {yylloc.last_column = 0;}
|
||||||
|
%lex-param { void* scanner }
|
||||||
|
|
||||||
|
%union
|
||||||
|
{
|
||||||
|
double val_double;
|
||||||
|
char val_char;
|
||||||
|
char val_str[MAXIDLENGTH];
|
||||||
|
Latan::MathNode* val_nodept;
|
||||||
|
}
|
||||||
|
|
||||||
|
%token <val_char> ERR
|
||||||
|
%token <val_str> FLOAT
|
||||||
|
%token <val_str> ID
|
||||||
|
|
||||||
|
%left '+' '-'
|
||||||
|
%left '*' '/'
|
||||||
|
%left '^'
|
||||||
|
%nonassoc UMINUS
|
||||||
|
|
||||||
|
%type <val_nodept> expr
|
||||||
|
|
||||||
|
%{
|
||||||
|
int _Math_lex(YYSTYPE* lvalp, YYLTYPE* llocp, void* scanner);
|
||||||
|
|
||||||
|
void _Math_error(YYLTYPE* locp, MathParserState* state, const char* err)
|
||||||
|
{
|
||||||
|
stringstream buf;
|
||||||
|
|
||||||
|
buf << *state->stream_name << ":" << locp->first_line << ":"\
|
||||||
|
<< locp->first_column << ": " << err;
|
||||||
|
LATAN_ERROR(Parsing,buf.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
#define scanner state->scanner
|
||||||
|
%}
|
||||||
|
|
||||||
|
%%
|
||||||
|
|
||||||
|
program:
|
||||||
|
/* empty string */
|
||||||
|
| expr {*state->data = $1;}
|
||||||
|
;
|
||||||
|
|
||||||
|
expr:
|
||||||
|
FLOAT {$$ = new MathNode($FLOAT,NodeType::Constant);}
|
||||||
|
| ID {$$ = new MathNode($ID,NodeType::Variable);}
|
||||||
|
| '-' expr %prec UMINUS {$$ = new MathNode("-",NodeType::Operator,1,$2);}
|
||||||
|
| expr '+' expr {$$ = new MathNode("+",NodeType::Operator,2,$1,$3);}
|
||||||
|
| expr '-' expr {$$ = new MathNode("-",NodeType::Operator,2,$1,$3);}
|
||||||
|
| expr '*' expr {$$ = new MathNode("*",NodeType::Operator,2,$1,$3);}
|
||||||
|
| expr '/' expr {$$ = new MathNode("/",NodeType::Operator,2,$1,$3);}
|
||||||
|
| expr '^' expr {$$ = new MathNode("^",NodeType::Operator,2,$1,$3);}
|
||||||
|
| '(' expr ')' {$$ = $2;}
|
||||||
|
;
|
39
latan/ParserState.hpp
Normal file
39
latan/ParserState.hpp
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
#ifndef LATAN_SAMPLE_HPP_
|
||||||
|
#define LATAN_SAMPLE_HPP_
|
||||||
|
|
||||||
|
#include <latan/Global.hpp>
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
LATAN_BEGIN_CPPDECL
|
||||||
|
|
||||||
|
template <typename DataObj>
|
||||||
|
class ParserState
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// constructor
|
||||||
|
explicit ParserState(std::istream* pt_stream, std::string* pt_name,\
|
||||||
|
DataObj* pt_data);
|
||||||
|
// destructor
|
||||||
|
virtual ~ParserState(void);
|
||||||
|
// public members
|
||||||
|
DataObj* data;
|
||||||
|
void* scanner;
|
||||||
|
std::istream* stream;
|
||||||
|
std::string* stream_name;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename DataObj>
|
||||||
|
ParserState<DataObj>::ParserState(std::istream* pt_stream,\
|
||||||
|
std::string* pt_name, \
|
||||||
|
DataObj* pt_data)
|
||||||
|
: data(pt_data), scanner(NULL), stream(pt_stream), stream_name(pt_name)
|
||||||
|
{}
|
||||||
|
|
||||||
|
template <typename DataObj>
|
||||||
|
ParserState<DataObj>::~ParserState(void)
|
||||||
|
{}
|
||||||
|
|
||||||
|
LATAN_END_CPPDECL
|
||||||
|
|
||||||
|
#endif
|
@ -3,6 +3,9 @@
|
|||||||
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <sstream>
|
||||||
|
#include <cstdarg>
|
||||||
#include "../config.h"
|
#include "../config.h"
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user