mirror of
https://github.com/aportelli/LatAnalyze.git
synced 2025-04-11 03:20:46 +01:00
math compiler fixes and improvements, now working
This commit is contained in:
parent
36bc0bc9b0
commit
50d21ae904
2
.gitignore
vendored
2
.gitignore
vendored
@ -3,7 +3,7 @@
|
|||||||
*.a
|
*.a
|
||||||
*.so
|
*.so
|
||||||
*.dylib
|
*.dylib
|
||||||
examples/ex_test
|
examples/exMathCompiler
|
||||||
sandbox/*
|
sandbox/*
|
||||||
|
|
||||||
# Apple stuffs
|
# Apple stuffs
|
||||||
|
@ -15,10 +15,10 @@ endif
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
noinst_PROGRAMS = \
|
noinst_PROGRAMS = \
|
||||||
ex_test
|
exMathCompiler
|
||||||
|
|
||||||
ex_test_SOURCES = ex_test.cpp
|
exMathCompiler_SOURCES = exMathCompiler.cpp
|
||||||
ex_test_CFLAGS = -g -O2
|
exMathCompiler_CFLAGS = -g -O2
|
||||||
ex_test_LDFLAGS = -L../latan/.libs -llatan
|
exMathCompiler_LDFLAGS = -L../latan/.libs -llatan
|
||||||
|
|
||||||
ACLOCAL_AMFLAGS = -I .buildutils/m4
|
ACLOCAL_AMFLAGS = -I .buildutils/m4
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <latan/Function.hpp>
|
#include <latan/Math.hpp>
|
||||||
#include <latan/MathCompiler.hpp>
|
#include <latan/MathCompiler.hpp>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
@ -7,22 +7,31 @@ using namespace Latan;
|
|||||||
|
|
||||||
int main(int argc, char* argv[])
|
int main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
MathCompiler C(argv[1]);
|
string source;
|
||||||
|
|
||||||
|
if (argc != 2)
|
||||||
|
{
|
||||||
|
cerr << "usage: " << argv[0] << " <program>" << endl;
|
||||||
|
}
|
||||||
|
source = argv[1];
|
||||||
|
|
||||||
|
MathCompiler C(source);
|
||||||
VarTable vtable;
|
VarTable vtable;
|
||||||
FunctionTable ftable;
|
FunctionTable ftable;
|
||||||
stack<double> dstack;
|
stack<double> dstack;
|
||||||
const VirtualProgram& P = C();
|
const VirtualProgram& P = C();
|
||||||
|
|
||||||
ftable["exp"] = &StdMath::exp;
|
cout << "-- Source code:" << endl << source << endl << endl;
|
||||||
ftable["atan2"] = &StdMath::atan2;
|
cout << "-- Abstract Syntax Tree:" << endl << *C.getAST() << endl;
|
||||||
cout << P << endl;
|
cout << "-- Program:" << endl << P << endl;
|
||||||
|
StdMath::addStdMathFunc(ftable);
|
||||||
for (unsigned int i=0;i<P.size();++i)
|
for (unsigned int i=0;i<P.size();++i)
|
||||||
{
|
{
|
||||||
(*(P[i]))(dstack,vtable,ftable);
|
(*(P[i]))(dstack, vtable, ftable);
|
||||||
}
|
}
|
||||||
if (!dstack.empty())
|
if (!dstack.empty())
|
||||||
{
|
{
|
||||||
cout << "result= " << dstack.top() << endl;
|
cout << "-- Result: " << dstack.top() << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
@ -62,6 +62,23 @@ unsigned int MathNode::getNArg(void) const
|
|||||||
return static_cast<unsigned int>(arg_.size());
|
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)
|
void MathNode::setName(const std::string &name)
|
||||||
{
|
{
|
||||||
name_ = name;
|
name_ = name;
|
||||||
@ -72,16 +89,38 @@ void MathNode::pushArg(MathNode *node)
|
|||||||
arg_.push_back(node);
|
arg_.push_back(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
// operator ////////////////////////////////////////////////////////////////////
|
// operators ///////////////////////////////////////////////////////////////////
|
||||||
const MathNode &MathNode::operator[](const unsigned int i) const
|
const MathNode &MathNode::operator[](const unsigned int i) const
|
||||||
{
|
{
|
||||||
return *arg_[i];
|
return *arg_[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
// test ////////////////////////////////////////////////////////////////////////
|
ostream &Latan::operator<<(ostream &out, const MathNode &n)
|
||||||
bool MathNode::isRoot(void) const
|
|
||||||
{
|
{
|
||||||
return (parent_ == NULL);
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
@ -228,10 +267,6 @@ DEF_OP(Mul, 2, x[0]*x[1], "mul")
|
|||||||
DEF_OP(Div, 2, x[0]/x[1], "div")
|
DEF_OP(Div, 2, x[0]/x[1], "div")
|
||||||
DEF_OP(Pow, 2, pow(x[0],x[1]), "pow")
|
DEF_OP(Pow, 2, pow(x[0],x[1]), "pow")
|
||||||
|
|
||||||
VirtualProgram::VirtualProgram(void)
|
|
||||||
: vector<Instruction *>(0)
|
|
||||||
{}
|
|
||||||
|
|
||||||
ostream &Latan::operator<<(ostream &out, const VirtualProgram &prog)
|
ostream &Latan::operator<<(ostream &out, const VirtualProgram &prog)
|
||||||
{
|
{
|
||||||
for (unsigned int i = 0; i < prog.size(); ++i)
|
for (unsigned int i = 0; i < prog.size(); ++i)
|
||||||
@ -247,8 +282,8 @@ ostream &Latan::operator<<(ostream &out, const VirtualProgram &prog)
|
|||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
// MathParserState constructor /////////////////////////////////////////////////
|
// MathParserState constructor /////////////////////////////////////////////////
|
||||||
MathCompiler::MathParserState::MathParserState(istream *stream, string *name,
|
MathCompiler::MathParserState::MathParserState(istream *stream, string *name,
|
||||||
vector<MathNode *> *data)
|
MathNode **data)
|
||||||
: ParserState<vector<MathNode *> >(stream, name, data)
|
: ParserState<MathNode *>(stream, name, data)
|
||||||
{
|
{
|
||||||
initScanner();
|
initScanner();
|
||||||
}
|
}
|
||||||
@ -264,11 +299,16 @@ MathCompiler::MathCompiler(void)
|
|||||||
: code_(NULL)
|
: code_(NULL)
|
||||||
, codeName_("<no_code>")
|
, codeName_("<no_code>")
|
||||||
, state_(NULL)
|
, state_(NULL)
|
||||||
|
, root_(NULL)
|
||||||
|
, gotReturn_(false)
|
||||||
, out_()
|
, out_()
|
||||||
, status_(Status::none)
|
, status_(Status::none)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
MathCompiler::MathCompiler(const std::string &code)
|
MathCompiler::MathCompiler(const std::string &code)
|
||||||
|
: root_(NULL)
|
||||||
|
, gotReturn_(false)
|
||||||
|
, out_()
|
||||||
{
|
{
|
||||||
init(code);
|
init(code);
|
||||||
}
|
}
|
||||||
@ -279,6 +319,19 @@ MathCompiler::~MathCompiler(void)
|
|||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// access //////////////////////////////////////////////////////////////////////
|
||||||
|
const MathNode * MathCompiler::getAST(void) const
|
||||||
|
{
|
||||||
|
if (root_)
|
||||||
|
{
|
||||||
|
return root_;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// public methods //////////////////////////////////////////////////////////////
|
// public methods //////////////////////////////////////////////////////////////
|
||||||
void MathCompiler::init(const std::string &code)
|
void MathCompiler::init(const std::string &code)
|
||||||
{
|
{
|
||||||
@ -288,7 +341,7 @@ void MathCompiler::init(const std::string &code)
|
|||||||
}
|
}
|
||||||
code_ = new stringstream(code);
|
code_ = new stringstream(code);
|
||||||
codeName_ = "<string>";
|
codeName_ = "<string>";
|
||||||
state_ = new MathParserState(code_, &codeName_, &expr_);
|
state_ = new MathParserState(code_, &codeName_, &root_);
|
||||||
status_ = Status::initialised;
|
status_ = Status::initialised;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -302,7 +355,16 @@ const VirtualProgram& MathCompiler::operator()(void)
|
|||||||
}
|
}
|
||||||
if (!(status_ & Status::compiled))
|
if (!(status_ & Status::compiled))
|
||||||
{
|
{
|
||||||
compile(expr_);
|
if (root_)
|
||||||
|
{
|
||||||
|
gotReturn_ = false;
|
||||||
|
compile(*root_);
|
||||||
|
if (!gotReturn_)
|
||||||
|
{
|
||||||
|
LATAN_ERROR(Syntax, "expected 'return' in program '" +
|
||||||
|
codeName_ + "'");
|
||||||
|
}
|
||||||
|
}
|
||||||
status_ |= Status::compiled;
|
status_ |= Status::compiled;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -315,95 +377,114 @@ void MathCompiler::parse(void)
|
|||||||
_math_parse(state_);
|
_math_parse(state_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MathCompiler::compile(const vector<MathNode *> &expr)
|
|
||||||
{
|
|
||||||
string lastNode;
|
|
||||||
|
|
||||||
for (unsigned int i = 0; i < expr.size(); ++i)
|
|
||||||
{
|
|
||||||
lastNode = expr[i]->getName();
|
|
||||||
if ((lastNode == "=")||(lastNode == "return"))
|
|
||||||
{
|
|
||||||
compile(*expr[i]);
|
|
||||||
if (lastNode == "return")
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lastNode != "return")
|
|
||||||
{
|
|
||||||
LATAN_ERROR(Syntax, "expected 'return' in program '" + codeName_ + "'");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#define IFNODE(name, nArg) if ((n.getName() == (name))&&(n.getNArg() == nArg))
|
#define IFNODE(name, nArg) if ((n.getName() == (name))&&(n.getNArg() == nArg))
|
||||||
#define ELIFNODE(name, nArg) else IFNODE(name, nArg)
|
#define ELIFNODE(name, nArg) else IFNODE(name, nArg)
|
||||||
#define ELSE else
|
#define ELSE else
|
||||||
void MathCompiler::compile(const MathNode& n)
|
void MathCompiler::compile(const MathNode& n)
|
||||||
{
|
{
|
||||||
switch (n.getType())
|
if (!gotReturn_)
|
||||||
{
|
{
|
||||||
case MathNode::Type::cst:
|
switch (n.getType())
|
||||||
out_.push_back(new Push(strTo<double>(n.getName())));
|
{
|
||||||
break;
|
case MathNode::Type::cst:
|
||||||
case MathNode::Type::var:
|
out_.push_back(new Push(strTo<double>(n.getName())));
|
||||||
out_.push_back(new Push(n.getName()));
|
break;
|
||||||
break;
|
case MathNode::Type::var:
|
||||||
case MathNode::Type::op:
|
out_.push_back(new Push(n.getName()));
|
||||||
if (n.getName() == "=")
|
break;
|
||||||
{
|
case MathNode::Type::op:
|
||||||
if (n[0].getType() == MathNode::Type::var)
|
// semicolon
|
||||||
|
if (n.getName() == ";")
|
||||||
{
|
{
|
||||||
compile(n[1]);
|
// compile relevant statements
|
||||||
if (n.isRoot())
|
for (unsigned int i = 0; i < n.getNArg(); ++i)
|
||||||
{
|
{
|
||||||
out_.push_back(new Pop(n[0].getName()));
|
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)
|
||||||
|
{
|
||||||
|
compile(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
|
||||||
|
compile(n[1]);
|
||||||
|
// pop instruction if at the end of a statement
|
||||||
|
if (hasSemicolonParent)
|
||||||
|
{
|
||||||
|
out_.push_back(new Pop(n[0].getName()));
|
||||||
|
}
|
||||||
|
// store instruction else
|
||||||
|
else
|
||||||
|
{
|
||||||
|
out_.push_back(new Store(n[0].getName()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
out_.push_back(new Store(n[0].getName()));
|
LATAN_ERROR(Compilation, "invalid LHS for '='");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// arithmetic operators
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (unsigned int i = 0; i < n.getNArg(); ++i)
|
||||||
|
{
|
||||||
|
compile(n[i]);
|
||||||
|
}
|
||||||
|
IFNODE("-", 1) out_.push_back(new Neg);
|
||||||
|
ELIFNODE("+", 2) out_.push_back(new Add);
|
||||||
|
ELIFNODE("-", 2) out_.push_back(new Sub);
|
||||||
|
ELIFNODE("*", 2) out_.push_back(new Mul);
|
||||||
|
ELIFNODE("/", 2) out_.push_back(new Div);
|
||||||
|
ELIFNODE("^", 2) out_.push_back(new Pow);
|
||||||
|
ELSE LATAN_ERROR(Compilation, "unknown operator '"
|
||||||
|
+ n.getName() + "'");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MathNode::Type::keyw:
|
||||||
|
if (n.getName() == "return")
|
||||||
|
{
|
||||||
|
compile(n[0]);
|
||||||
|
gotReturn_ = true;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LATAN_ERROR(Compilation, "invalid LHS for '='");
|
LATAN_ERROR(Compilation, "unknown keyword '" + n.getName()
|
||||||
|
+ "'");
|
||||||
}
|
}
|
||||||
}
|
break;
|
||||||
else
|
case MathNode::Type::func:
|
||||||
{
|
|
||||||
for (unsigned int i = 0; i < n.getNArg(); ++i)
|
for (unsigned int i = 0; i < n.getNArg(); ++i)
|
||||||
{
|
{
|
||||||
compile(n[i]);
|
compile(n[i]);
|
||||||
}
|
}
|
||||||
IFNODE("-", 1) out_.push_back(new Neg);
|
out_.push_back(new Call(n.getName()));
|
||||||
ELIFNODE("+", 2) out_.push_back(new Add);
|
break;
|
||||||
ELIFNODE("-", 2) out_.push_back(new Sub);
|
default:
|
||||||
ELIFNODE("*", 2) out_.push_back(new Mul);
|
LATAN_ERROR(Compilation,
|
||||||
ELIFNODE("/", 2) out_.push_back(new Div);
|
"unknown node type (node named '" + n.getName()
|
||||||
ELIFNODE("^", 2) out_.push_back(new Pow);
|
+ "')");
|
||||||
ELSE LATAN_ERROR(Compilation, "unknown operator (node '"
|
break;
|
||||||
+ n.getName() + "')");
|
}
|
||||||
}
|
|
||||||
break;
|
|
||||||
case MathNode::Type::keyw:
|
|
||||||
for (unsigned int i = 0; i < n.getNArg(); ++i)
|
|
||||||
{
|
|
||||||
compile(n[i]);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case MathNode::Type::func:
|
|
||||||
for (unsigned int i = 0; i < n.getNArg(); ++i)
|
|
||||||
{
|
|
||||||
compile(n[i]);
|
|
||||||
}
|
|
||||||
out_.push_back(new Call(n.getName()));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
LATAN_ERROR(Compilation,
|
|
||||||
"unknown node type (node '" + n.getName() + "')");
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -412,11 +493,7 @@ void MathCompiler::reset(void)
|
|||||||
delete code_;
|
delete code_;
|
||||||
codeName_ = "<no_code>";
|
codeName_ = "<no_code>";
|
||||||
delete state_;
|
delete state_;
|
||||||
for (vector<MathNode *>::iterator i = expr_.begin(); i != expr_.end(); ++i)
|
delete root_;
|
||||||
{
|
|
||||||
delete *i;
|
|
||||||
}
|
|
||||||
expr_.clear();
|
|
||||||
for (VirtualProgram::iterator i = out_.begin(); i != out_.end(); ++i)
|
for (VirtualProgram::iterator i = out_.begin(); i != out_.end(); ++i)
|
||||||
{
|
{
|
||||||
delete *i;
|
delete *i;
|
||||||
|
@ -25,11 +25,12 @@ public:
|
|||||||
public:
|
public:
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
cst = 0,
|
undef = -1,
|
||||||
op = 1,
|
cst = 0,
|
||||||
var = 2,
|
op = 1,
|
||||||
keyw = 3,
|
var = 2,
|
||||||
func = 4
|
keyw = 3,
|
||||||
|
func = 4
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
public:
|
public:
|
||||||
@ -40,15 +41,18 @@ public:
|
|||||||
// destructor
|
// destructor
|
||||||
virtual ~MathNode();
|
virtual ~MathNode();
|
||||||
// access
|
// access
|
||||||
const std::string& getName(void) const;
|
const std::string& getName(void) const;
|
||||||
unsigned int getType(void) const;
|
unsigned int getType(void) const;
|
||||||
unsigned int getNArg(void) const;
|
unsigned int getNArg(void) const;
|
||||||
|
const MathNode * getParent(void) const;
|
||||||
|
unsigned int getLevel(void) const;
|
||||||
void setName(const std::string &name);
|
void setName(const std::string &name);
|
||||||
void pushArg(MathNode *node);
|
void pushArg(MathNode *node);
|
||||||
// operator
|
// operator
|
||||||
const MathNode &operator[](const unsigned int i) const;
|
const MathNode &operator[](const unsigned int i) const;
|
||||||
// test
|
private:
|
||||||
bool isRoot(void) const;
|
// IO
|
||||||
|
std::ostream &print(std::ostream &out) const;
|
||||||
private:
|
private:
|
||||||
std::string name_;
|
std::string name_;
|
||||||
unsigned int type_;
|
unsigned int type_;
|
||||||
@ -56,6 +60,8 @@ private:
|
|||||||
const MathNode * parent_;
|
const MathNode * parent_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
std::ostream &operator<<(std::ostream &out, const MathNode &n);
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* Virtual machine code classes *
|
* Virtual machine code classes *
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
@ -166,13 +172,10 @@ DECL_OP(Mul);
|
|||||||
DECL_OP(Div);
|
DECL_OP(Div);
|
||||||
DECL_OP(Pow);
|
DECL_OP(Pow);
|
||||||
|
|
||||||
class VirtualProgram: public std::vector<Instruction *>
|
// Virtual program type
|
||||||
{
|
typedef std::vector<Instruction *> VirtualProgram;
|
||||||
public:
|
|
||||||
VirtualProgram(void);
|
std::ostream &operator<<(std::ostream &out, const VirtualProgram &program);
|
||||||
friend std::ostream &operator<<(std::ostream &out,
|
|
||||||
const VirtualProgram &program);
|
|
||||||
};
|
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* Compiler class *
|
* Compiler class *
|
||||||
@ -181,12 +184,12 @@ class MathCompiler
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// parser state
|
// parser state
|
||||||
class MathParserState: public ParserState<std::vector<MathNode *> >
|
class MathParserState: public ParserState<MathNode *>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// constructor
|
// constructor
|
||||||
explicit MathParserState(std::istream *stream, std::string *name,
|
explicit MathParserState(std::istream *stream, std::string *name,
|
||||||
std::vector<MathNode *> *data);
|
MathNode **data);
|
||||||
// destructor
|
// destructor
|
||||||
virtual ~MathParserState(void);
|
virtual ~MathParserState(void);
|
||||||
private:
|
private:
|
||||||
@ -213,21 +216,24 @@ public:
|
|||||||
MathCompiler(const std::string &code);
|
MathCompiler(const std::string &code);
|
||||||
// destructor
|
// destructor
|
||||||
~MathCompiler(void);
|
~MathCompiler(void);
|
||||||
|
// access
|
||||||
|
const MathNode * getAST(void) const;
|
||||||
// initialization
|
// initialization
|
||||||
void init(const std::string &code);
|
void init(const std::string &code);
|
||||||
|
// compilation
|
||||||
const VirtualProgram &operator()(void);
|
const VirtualProgram &operator()(void);
|
||||||
private:
|
private:
|
||||||
void parse(void);
|
void parse(void);
|
||||||
void compile(const std::vector<MathNode *> &expr);
|
|
||||||
void compile(const MathNode &node);
|
void compile(const MathNode &node);
|
||||||
void reset(void);
|
void reset(void);
|
||||||
private:
|
private:
|
||||||
std::istream *code_;
|
std::istream *code_;
|
||||||
std::string codeName_;
|
std::string codeName_;
|
||||||
MathParserState *state_;
|
MathParserState *state_;
|
||||||
std::vector<MathNode *> expr_;
|
MathNode *root_;
|
||||||
VirtualProgram out_;
|
bool gotReturn_;
|
||||||
unsigned int status_;
|
VirtualProgram out_;
|
||||||
|
unsigned int status_;
|
||||||
};
|
};
|
||||||
|
|
||||||
LATAN_END_CPPDECL
|
LATAN_END_CPPDECL
|
||||||
|
@ -41,10 +41,7 @@
|
|||||||
DIGIT [0-9]
|
DIGIT [0-9]
|
||||||
ALPHA [a-zA-Z_]
|
ALPHA [a-zA-Z_]
|
||||||
FLOAT (({DIGIT}+(\.{DIGIT}*)?)|({DIGIT}*\.{DIGIT}+))([eE][+-]?{DIGIT}+)?
|
FLOAT (({DIGIT}+(\.{DIGIT}*)?)|({DIGIT}*\.{DIGIT}+))([eE][+-]?{DIGIT}+)?
|
||||||
KEYWORD return
|
SPECIAL [;,()+\-*/^={}]
|
||||||
PUNC [;,()]
|
|
||||||
OP [+\-*/^=]
|
|
||||||
PAR []
|
|
||||||
BLANK [ \t]
|
BLANK [ \t]
|
||||||
|
|
||||||
%%
|
%%
|
||||||
@ -53,9 +50,8 @@ BLANK [ \t]
|
|||||||
strncpy(yylval->val_str,yytext,MAXIDLENGTH);
|
strncpy(yylval->val_str,yytext,MAXIDLENGTH);
|
||||||
RETTOK(FLOAT);
|
RETTOK(FLOAT);
|
||||||
}
|
}
|
||||||
{OP} {RET(*yytext);}
|
{SPECIAL} {RET(*yytext);}
|
||||||
{KEYWORD} {RET(*yytext);}
|
return {RETTOK(RETURN);}
|
||||||
{PUNC} {RET(*yytext);}
|
|
||||||
{ALPHA}({ALPHA}|{DIGIT})* {
|
{ALPHA}({ALPHA}|{DIGIT})* {
|
||||||
strncpy(yylval->val_str,yytext,MAXIDLENGTH);
|
strncpy(yylval->val_str,yytext,MAXIDLENGTH);
|
||||||
RETTOK(ID);
|
RETTOK(ID);
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
%token <val_char> ERR
|
%token <val_char> ERR
|
||||||
%token <val_str> FLOAT
|
%token <val_str> FLOAT
|
||||||
%token <val_str> ID
|
%token <val_str> ID
|
||||||
%token <val_str> KEYWORD
|
%token RETURN
|
||||||
|
|
||||||
%left '='
|
%left '='
|
||||||
%left '+' '-'
|
%left '+' '-'
|
||||||
@ -37,8 +37,7 @@
|
|||||||
%left '^'
|
%left '^'
|
||||||
%nonassoc UMINUS
|
%nonassoc UMINUS
|
||||||
|
|
||||||
%type <val_node> expr
|
%type <val_node> stmt stmt_list expr func_args
|
||||||
%type <val_node> funcargs
|
|
||||||
|
|
||||||
%{
|
%{
|
||||||
int _math_lex(YYSTYPE *lvalp, YYLTYPE *llocp, void *scanner);
|
int _math_lex(YYSTYPE *lvalp, YYLTYPE *llocp, void *scanner);
|
||||||
@ -60,21 +59,37 @@
|
|||||||
|
|
||||||
program:
|
program:
|
||||||
/* empty string */
|
/* empty string */
|
||||||
| program expr ';' {state->data->push_back($2);}
|
| stmt_list {*(state->data) = $1;}
|
||||||
|
;
|
||||||
|
|
||||||
|
stmt:
|
||||||
|
';'
|
||||||
|
{$$ = new MathNode(";", MathNode::Type::op, 0);}
|
||||||
|
| expr ';'
|
||||||
|
{$$ = $1;}
|
||||||
|
| ID '=' expr ';'
|
||||||
|
{
|
||||||
|
$$ = new MathNode("=", MathNode::Type::op, 2, \
|
||||||
|
new MathNode($ID,MathNode::Type::var), $3);
|
||||||
|
}
|
||||||
|
| RETURN expr ';'
|
||||||
|
{$$ = new MathNode("return", MathNode::Type::keyw, 1, $2);}
|
||||||
|
| '{' stmt_list '}'
|
||||||
|
{$$ = $2;}
|
||||||
|
;
|
||||||
|
|
||||||
|
stmt_list:
|
||||||
|
stmt
|
||||||
|
{$$ = $1;}
|
||||||
|
| stmt_list stmt
|
||||||
|
{$$ = new MathNode(";", MathNode::Type::op, 2, $1, $2);}
|
||||||
;
|
;
|
||||||
|
|
||||||
expr:
|
expr:
|
||||||
FLOAT
|
FLOAT
|
||||||
{$$ = new MathNode($FLOAT, MathNode::Type::cst);}
|
{$$ = new MathNode($FLOAT, MathNode::Type::cst);}
|
||||||
| ID
|
| ID
|
||||||
{$$ = new MathNode($ID,MathNode::Type::var);}
|
{$$ = new MathNode($ID, MathNode::Type::var);}
|
||||||
| ID '=' expr
|
|
||||||
{
|
|
||||||
$$ = new MathNode("=", MathNode::Type::op, 2, \
|
|
||||||
new MathNode($ID,MathNode::Type::var), $3);
|
|
||||||
}
|
|
||||||
| 'r' expr
|
|
||||||
{$$ = new MathNode("return", MathNode::Type::keyw, 1, $2);}
|
|
||||||
| '-' expr %prec UMINUS
|
| '-' expr %prec UMINUS
|
||||||
{$$ = new MathNode("-", MathNode::Type::op, 1, $2);}
|
{$$ = new MathNode("-", MathNode::Type::op, 1, $2);}
|
||||||
| expr '+' expr
|
| expr '+' expr
|
||||||
@ -89,16 +104,16 @@ expr:
|
|||||||
{$$ = new MathNode("^", MathNode::Type::op, 2, $1, $3);}
|
{$$ = new MathNode("^", MathNode::Type::op, 2, $1, $3);}
|
||||||
| '(' expr ')'
|
| '(' expr ')'
|
||||||
{$$ = $2;}
|
{$$ = $2;}
|
||||||
| ID '(' funcargs ')'
|
| ID '(' func_args ')'
|
||||||
{$$ = $3; $$->setName($ID);}
|
{$$ = $3; $$->setName($ID);}
|
||||||
;
|
;
|
||||||
|
|
||||||
funcargs:
|
func_args:
|
||||||
/* empty string */
|
/* empty string */
|
||||||
{$$ = new MathNode("", MathNode::Type::func);}
|
{$$ = new MathNode("", MathNode::Type::func);}
|
||||||
| expr
|
| expr
|
||||||
{$$ = new MathNode("", MathNode::Type::func, 1, $1);}
|
{$$ = new MathNode("", MathNode::Type::func, 1, $1);}
|
||||||
| funcargs ',' expr
|
| func_args ',' expr
|
||||||
{$$ = $1; $$->pushArg($3);}
|
{$$ = $1; $$->pushArg($3);}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user