mirror of
https://github.com/aportelli/LatAnalyze.git
synced 2025-04-11 03:20:46 +01:00
math compiler support multi-expression code
This commit is contained in:
parent
119c2bf31d
commit
fa5ca7273c
@ -5,7 +5,7 @@ using namespace std;
|
|||||||
using namespace Latan;
|
using namespace Latan;
|
||||||
|
|
||||||
// Math Bison/Flex parser declaration
|
// Math Bison/Flex parser declaration
|
||||||
int _math_parse(MathParserState* state);
|
int _math_parse(MathCompiler::MathParserState* state);
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* MathNode implementation *
|
* MathNode implementation *
|
||||||
@ -14,6 +14,7 @@ int _math_parse(MathParserState* state);
|
|||||||
MathNode::MathNode(const string &name, const unsigned int type)
|
MathNode::MathNode(const string &name, const unsigned int type)
|
||||||
: name_(name)
|
: name_(name)
|
||||||
, type_(type)
|
, type_(type)
|
||||||
|
, parent_(NULL)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
MathNode::MathNode(const std::string &name, const unsigned int type,\
|
MathNode::MathNode(const std::string &name, const unsigned int type,\
|
||||||
@ -21,6 +22,7 @@ MathNode::MathNode(const std::string &name, const unsigned int type,\
|
|||||||
: name_(name)
|
: name_(name)
|
||||||
, type_(type)
|
, type_(type)
|
||||||
, arg_(nArg)
|
, arg_(nArg)
|
||||||
|
, parent_(NULL)
|
||||||
{
|
{
|
||||||
va_list va;
|
va_list va;
|
||||||
|
|
||||||
@ -28,6 +30,7 @@ MathNode::MathNode(const std::string &name, const unsigned int type,\
|
|||||||
for (unsigned int i = 0; i < nArg; ++i)
|
for (unsigned int i = 0; i < nArg; ++i)
|
||||||
{
|
{
|
||||||
arg_[i] = va_arg(va, MathNode*);
|
arg_[i] = va_arg(va, MathNode*);
|
||||||
|
arg_[i]->parent_ = this;
|
||||||
}
|
}
|
||||||
va_end(va);
|
va_end(va);
|
||||||
}
|
}
|
||||||
@ -35,7 +38,7 @@ MathNode::MathNode(const std::string &name, const unsigned int type,\
|
|||||||
// destructor //////////////////////////////////////////////////////////////////
|
// destructor //////////////////////////////////////////////////////////////////
|
||||||
MathNode::~MathNode(void)
|
MathNode::~MathNode(void)
|
||||||
{
|
{
|
||||||
vector<MathNode*>::iterator i;
|
vector<MathNode *>::iterator i;
|
||||||
|
|
||||||
for (i = arg_.begin(); i != arg_.end(); ++i)
|
for (i = arg_.begin(); i != arg_.end(); ++i)
|
||||||
{
|
{
|
||||||
@ -65,21 +68,10 @@ const MathNode &MathNode::operator[](const unsigned int i) const
|
|||||||
return *arg_[i];
|
return *arg_[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************
|
// test ////////////////////////////////////////////////////////////////////////
|
||||||
* MathParserState implementation *
|
bool MathNode::isRoot(void) const
|
||||||
******************************************************************************/
|
|
||||||
// constructor /////////////////////////////////////////////////////////////////
|
|
||||||
MathParserState::MathParserState(std::istream *stream, std::string *name,
|
|
||||||
MathNode **data)
|
|
||||||
: ParserState<MathNode *>(stream, name, data)
|
|
||||||
{
|
{
|
||||||
initScanner();
|
return (parent_ == NULL);
|
||||||
}
|
|
||||||
|
|
||||||
// destructor //////////////////////////////////////////////////////////////////
|
|
||||||
MathParserState::~MathParserState(void)
|
|
||||||
{
|
|
||||||
destroyScanner();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
@ -146,9 +138,13 @@ Pop::Pop(const string &name)
|
|||||||
: name_(name)
|
: name_(name)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
|
||||||
void Pop::operator()(std::stack<double> &dStack, VarTable &vTable)
|
void Pop::operator()(std::stack<double> &dStack, VarTable &vTable)
|
||||||
{
|
{
|
||||||
vTable[name_] = dStack.top();
|
if (!name_.empty())
|
||||||
|
{
|
||||||
|
vTable[name_] = dStack.top();
|
||||||
|
}
|
||||||
dStack.pop();
|
dStack.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -157,6 +153,24 @@ void Pop::print(std::ostream &out) const
|
|||||||
out << CODE_MOD << "pop" << CODE_MOD << name_;
|
out << CODE_MOD << "pop" << CODE_MOD << name_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Store::Store(const string &name)
|
||||||
|
: name_(name)
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
void Store::operator()(std::stack<double> &dStack, VarTable &vTable)
|
||||||
|
{
|
||||||
|
if (!name_.empty())
|
||||||
|
{
|
||||||
|
vTable[name_] = dStack.top();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Store::print(std::ostream &out) const
|
||||||
|
{
|
||||||
|
out << CODE_MOD << "store" << CODE_MOD << name_;
|
||||||
|
}
|
||||||
|
|
||||||
#define DEF_OP(name, nArg, exp, insName)\
|
#define DEF_OP(name, nArg, exp, insName)\
|
||||||
void name::operator()(stack<double> &dStack, VarTable &vTable __dumb)\
|
void name::operator()(stack<double> &dStack, VarTable &vTable __dumb)\
|
||||||
{\
|
{\
|
||||||
@ -174,8 +188,8 @@ void name::print(std::ostream &out) const\
|
|||||||
}
|
}
|
||||||
|
|
||||||
DEF_OP(Neg, 1, -x[0], "neg")
|
DEF_OP(Neg, 1, -x[0], "neg")
|
||||||
DEF_OP(Add, 2, x[0]+x[1], "add")
|
DEF_OP(Add, 2, x[0] + x[1], "add")
|
||||||
DEF_OP(Sub, 2, x[0]-x[1], "sub")
|
DEF_OP(Sub, 2, x[0] - x[1], "sub")
|
||||||
DEF_OP(Mul, 2, x[0]*x[1], "mul")
|
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")
|
||||||
@ -197,12 +211,25 @@ ostream &Latan::operator<<(ostream &out, const VirtualProgram &prog)
|
|||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* MathCompiler implementation *
|
* MathCompiler implementation *
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
// MathParserState constructor /////////////////////////////////////////////////
|
||||||
|
MathCompiler::MathParserState::MathParserState(istream *stream, string *name,
|
||||||
|
vector<MathNode *> *data)
|
||||||
|
: ParserState<vector<MathNode *> >(stream, name, data)
|
||||||
|
{
|
||||||
|
initScanner();
|
||||||
|
}
|
||||||
|
|
||||||
|
// MathParserState destructor //////////////////////////////////////////////////
|
||||||
|
MathCompiler::MathParserState::~MathParserState(void)
|
||||||
|
{
|
||||||
|
destroyScanner();
|
||||||
|
}
|
||||||
|
|
||||||
// constructors ////////////////////////////////////////////////////////////////
|
// constructors ////////////////////////////////////////////////////////////////
|
||||||
MathCompiler::MathCompiler(void)
|
MathCompiler::MathCompiler(void)
|
||||||
: code_(NULL)
|
: code_(NULL)
|
||||||
, codeName_("<no_code>")
|
, codeName_("<no_code>")
|
||||||
, state_(NULL)
|
, state_(NULL)
|
||||||
, root_(NULL)
|
|
||||||
, out_()
|
, out_()
|
||||||
, status_(Status::none)
|
, status_(Status::none)
|
||||||
{}
|
{}
|
||||||
@ -227,8 +254,8 @@ void MathCompiler::init(const std::string &code)
|
|||||||
}
|
}
|
||||||
code_ = new stringstream(code);
|
code_ = new stringstream(code);
|
||||||
codeName_ = "<string>";
|
codeName_ = "<string>";
|
||||||
state_ = new MathParserState(code_, &codeName_, &root_);
|
state_ = new MathParserState(code_, &codeName_, &expr_);
|
||||||
status_ |= Status::initialised;
|
status_ = Status::initialised;
|
||||||
}
|
}
|
||||||
|
|
||||||
const VirtualProgram& MathCompiler::operator()(void)
|
const VirtualProgram& MathCompiler::operator()(void)
|
||||||
@ -236,10 +263,13 @@ const VirtualProgram& MathCompiler::operator()(void)
|
|||||||
if (!(status_ & Status::parsed))
|
if (!(status_ & Status::parsed))
|
||||||
{
|
{
|
||||||
parse();
|
parse();
|
||||||
|
status_ |= Status::parsed;
|
||||||
|
status_ -= status_ & Status::compiled;
|
||||||
}
|
}
|
||||||
if (!(status_ & Status::compiled))
|
if (!(status_ & Status::compiled))
|
||||||
{
|
{
|
||||||
compile(*root_);
|
compile(expr_);
|
||||||
|
status_ |= Status::compiled;
|
||||||
}
|
}
|
||||||
|
|
||||||
return out_;
|
return out_;
|
||||||
@ -249,54 +279,97 @@ const VirtualProgram& MathCompiler::operator()(void)
|
|||||||
void MathCompiler::parse(void)
|
void MathCompiler::parse(void)
|
||||||
{
|
{
|
||||||
_math_parse(state_);
|
_math_parse(state_);
|
||||||
status_ |= Status::parsed;
|
|
||||||
status_ -= status_ & Status::compiled;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define IFOP(name, nArg) if ((n.getName() == (name))&&(n.getNArg() == nArg))
|
void MathCompiler::compile(const vector<MathNode *> &expr)
|
||||||
#define ELIFOP(name, nArg) else IFOP(name, nArg)
|
{
|
||||||
|
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 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())
|
switch (n.getType())
|
||||||
{
|
{
|
||||||
case MathNode::Type::Constant:
|
case MathNode::Type::cst:
|
||||||
out_.push_back(new Push(strTo<double>(n.getName())));
|
out_.push_back(new Push(strTo<double>(n.getName())));
|
||||||
break;
|
break;
|
||||||
case MathNode::Type::Variable:
|
case MathNode::Type::var:
|
||||||
out_.push_back(new Push(n.getName()));
|
out_.push_back(new Push(n.getName()));
|
||||||
break;
|
break;
|
||||||
case MathNode::Type::Operator:
|
case MathNode::Type::op:
|
||||||
|
if (n.getName() == "=")
|
||||||
|
{
|
||||||
|
compile(n[1]);
|
||||||
|
if (n.isRoot())
|
||||||
|
{
|
||||||
|
out_.push_back(new Pop(n[0].getName()));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
out_.push_back(new Store(n[0].getName()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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 (node '"
|
||||||
|
+ n.getName() + "')");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MathNode::Type::keyw:
|
||||||
for (unsigned int i = 0; i < n.getNArg(); ++i)
|
for (unsigned int i = 0; i < n.getNArg(); ++i)
|
||||||
{
|
{
|
||||||
compile(n[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.getName() + "')");
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
LATAN_ERROR(Compilation,
|
LATAN_ERROR(Compilation,
|
||||||
"unknown node type (node '" + n.getName() + "')");
|
"unknown node type (node '" + n.getName() + "')");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
status_ |= Status::compiled;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MathCompiler::reset(void)
|
void MathCompiler::reset(void)
|
||||||
{
|
{
|
||||||
VirtualProgram::iterator i;
|
|
||||||
|
|
||||||
delete code_;
|
delete code_;
|
||||||
codeName_ = "<no_code>";
|
codeName_ = "<no_code>";
|
||||||
delete state_;
|
delete state_;
|
||||||
delete root_;
|
for (vector<MathNode *>::iterator i = expr_.begin(); i != expr_.end(); ++i)
|
||||||
for (i = out_.begin(); i != out_.end(); ++i)
|
{
|
||||||
|
delete *i;
|
||||||
|
}
|
||||||
|
expr_.clear();
|
||||||
|
for (VirtualProgram::iterator i = out_.begin(); i != out_.end(); ++i)
|
||||||
{
|
{
|
||||||
delete *i;
|
delete *i;
|
||||||
}
|
}
|
||||||
|
@ -24,9 +24,10 @@ public:
|
|||||||
public:
|
public:
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
Constant = 0,
|
cst = 0,
|
||||||
Operator = 1,
|
op = 1,
|
||||||
Variable = 2
|
var = 2,
|
||||||
|
keyw = 3
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
public:
|
public:
|
||||||
@ -40,27 +41,15 @@ public:
|
|||||||
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;
|
||||||
// operators
|
// operator
|
||||||
const MathNode &operator[](const unsigned int i) const;
|
const MathNode &operator[](const unsigned int i) const;
|
||||||
|
// test
|
||||||
|
bool isRoot(void) const;
|
||||||
private:
|
private:
|
||||||
// private members
|
std::string name_;
|
||||||
std::string name_;
|
unsigned int type_;
|
||||||
unsigned int type_;
|
std::vector<MathNode *> arg_;
|
||||||
std::vector<MathNode*> arg_;
|
const MathNode * parent_;
|
||||||
};
|
|
||||||
|
|
||||||
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);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
@ -80,7 +69,7 @@ private:
|
|||||||
virtual void print(std::ostream &out) const = 0;
|
virtual void print(std::ostream &out) const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
// push and pop
|
// push, pop and store
|
||||||
class Push: public Instruction
|
class Push: public Instruction
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
@ -120,6 +109,19 @@ private:
|
|||||||
std::string name_;
|
std::string name_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class Store: public Instruction
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//constructor
|
||||||
|
explicit Store(const std::string &name);
|
||||||
|
// instruction execution
|
||||||
|
virtual void operator()(std::stack<double> &dStack, VarTable &vTable);
|
||||||
|
private:
|
||||||
|
virtual void print(std::ostream& out) const;
|
||||||
|
private:
|
||||||
|
std::string name_;
|
||||||
|
};
|
||||||
|
|
||||||
// Float operations
|
// Float operations
|
||||||
#define DECL_OP(name)\
|
#define DECL_OP(name)\
|
||||||
class name: public Instruction\
|
class name: public Instruction\
|
||||||
@ -150,7 +152,23 @@ public:
|
|||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
class MathCompiler
|
class MathCompiler
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
// parser state
|
||||||
|
class MathParserState: public ParserState<std::vector<MathNode *> >
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// constructor
|
||||||
|
explicit MathParserState(std::istream *stream, std::string *name,
|
||||||
|
std::vector<MathNode *> *data);
|
||||||
|
// destructor
|
||||||
|
virtual ~MathParserState(void);
|
||||||
|
private:
|
||||||
|
// allocation/deallocation functions defined in MathLexer.lpp
|
||||||
|
virtual void initScanner(void);
|
||||||
|
virtual void destroyScanner(void);
|
||||||
|
};
|
||||||
private:
|
private:
|
||||||
|
// status flags
|
||||||
class Status
|
class Status
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -173,15 +191,16 @@ public:
|
|||||||
const VirtualProgram &operator()(void);
|
const VirtualProgram &operator()(void);
|
||||||
private:
|
private:
|
||||||
void parse(void);
|
void parse(void);
|
||||||
void compile(const MathNode& node);
|
void compile(const std::vector<MathNode *> &expr);
|
||||||
|
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_;
|
||||||
MathNode *root_;
|
std::vector<MathNode *> expr_;
|
||||||
VirtualProgram out_;
|
VirtualProgram out_;
|
||||||
unsigned int status_;
|
unsigned int status_;
|
||||||
};
|
};
|
||||||
|
|
||||||
LATAN_END_CPPDECL
|
LATAN_END_CPPDECL
|
||||||
|
@ -16,15 +16,15 @@
|
|||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace Latan;
|
using namespace Latan;
|
||||||
|
|
||||||
#define YY_EXTRA_TYPE MathParserState*
|
#define YY_EXTRA_TYPE MathCompiler::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;\
|
||||||
yylloc->last_column = yylloc->first_column + yyleng - 1;
|
yylloc->last_column = yylloc->first_column + yyleng - 1;
|
||||||
|
|
||||||
#define YY_INPUT(buf,result,max_size) \
|
#define YY_INPUT(buf, result, max_size) \
|
||||||
{ \
|
{ \
|
||||||
(*yyextra->stream).read(buf,max_size);\
|
(*yyextra->stream).read(buf, max_size);\
|
||||||
result = (*yyextra->stream).gcount();\
|
result = (*yyextra->stream).gcount();\
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -41,7 +41,9 @@
|
|||||||
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}+)?
|
||||||
OP [+\-*/^]
|
KEYWORD return
|
||||||
|
END ;
|
||||||
|
OP [+\-*/^=]
|
||||||
PAR [()]
|
PAR [()]
|
||||||
BLANK [ \t]
|
BLANK [ \t]
|
||||||
|
|
||||||
@ -52,24 +54,26 @@ BLANK [ \t]
|
|||||||
RETTOK(FLOAT);
|
RETTOK(FLOAT);
|
||||||
}
|
}
|
||||||
{OP} {RET(*yytext);}
|
{OP} {RET(*yytext);}
|
||||||
|
{KEYWORD} {RET(*yytext);}
|
||||||
{PAR} {RET(*yytext);}
|
{PAR} {RET(*yytext);}
|
||||||
{ALPHA}({ALPHA}|{DIGIT})* {
|
{ALPHA}({ALPHA}|{DIGIT})* {
|
||||||
strncpy(yylval->val_str,yytext,MAXIDLENGTH);
|
strncpy(yylval->val_str,yytext,MAXIDLENGTH);
|
||||||
RETTOK(ID);
|
RETTOK(ID);
|
||||||
}
|
}
|
||||||
|
{END} {RETTOK(END);}
|
||||||
<*>\n {yylloc->last_column = 0;}
|
<*>\n {yylloc->last_column = 0;}
|
||||||
<*>{BLANK}
|
<*>{BLANK}
|
||||||
<*>. {yylval->val_char = yytext[0]; RETTOK(ERR);}
|
<*>. {yylval->val_char = yytext[0]; RETTOK(ERR);}
|
||||||
|
|
||||||
%%
|
%%
|
||||||
|
|
||||||
void MathParserState::initScanner()
|
void MathCompiler::MathParserState::initScanner()
|
||||||
{
|
{
|
||||||
yylex_init(&scanner);
|
yylex_init(&scanner);
|
||||||
yyset_extra(this, scanner);
|
yyset_extra(this, scanner);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MathParserState::destroyScanner()
|
void MathCompiler::MathParserState::destroyScanner()
|
||||||
{
|
{
|
||||||
yylex_destroy(scanner);
|
yylex_destroy(scanner);
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
%locations
|
%locations
|
||||||
%defines
|
%defines
|
||||||
%error-verbose
|
%error-verbose
|
||||||
%parse-param { Latan::MathParserState* state }
|
%parse-param { Latan::MathCompiler::MathParserState *state }
|
||||||
%initial-action {yylloc.last_column = 0;}
|
%initial-action {yylloc.last_column = 0;}
|
||||||
%lex-param { void* scanner }
|
%lex-param { void* scanner }
|
||||||
|
|
||||||
@ -23,30 +23,34 @@
|
|||||||
double val_double;
|
double val_double;
|
||||||
char val_char;
|
char val_char;
|
||||||
char val_str[MAXIDLENGTH];
|
char val_str[MAXIDLENGTH];
|
||||||
Latan::MathNode* val_nodept;
|
Latan::MathNode *val_node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
%token END
|
||||||
%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
|
||||||
|
|
||||||
|
%left '='
|
||||||
%left '+' '-'
|
%left '+' '-'
|
||||||
%left '*' '/'
|
%left '*' '/'
|
||||||
%left '^'
|
%left '^'
|
||||||
%nonassoc UMINUS
|
%nonassoc UMINUS
|
||||||
|
|
||||||
%type <val_nodept> expr
|
%type <val_node> expr
|
||||||
|
|
||||||
%{
|
%{
|
||||||
int _math_lex(YYSTYPE* lvalp, YYLTYPE* llocp, void* scanner);
|
int _math_lex(YYSTYPE *lvalp, YYLTYPE *llocp, void *scanner);
|
||||||
|
|
||||||
void _math_error(YYLTYPE* locp, MathParserState* state, const char* err)
|
void _math_error(YYLTYPE *locp, MathCompiler::MathParserState *state,
|
||||||
|
const char *err)
|
||||||
{
|
{
|
||||||
stringstream buf;
|
stringstream buf;
|
||||||
|
|
||||||
buf << *state->streamName << ":" << locp->first_line << ":"\
|
buf << *(state->streamName) << ":" << locp->first_line << ":"\
|
||||||
<< locp->first_column << ": " << err;
|
<< locp->first_column << ": " << err;
|
||||||
LATAN_ERROR(Parsing,buf.str());
|
LATAN_ERROR(Parsing, buf.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
#define scanner state->scanner
|
#define scanner state->scanner
|
||||||
@ -56,25 +60,30 @@
|
|||||||
|
|
||||||
program:
|
program:
|
||||||
/* empty string */
|
/* empty string */
|
||||||
| expr {*state->data = $1;}
|
| program expr END {state->data->push_back($2);}
|
||||||
;
|
;
|
||||||
|
|
||||||
expr:
|
expr:
|
||||||
FLOAT
|
FLOAT
|
||||||
{$$ = new MathNode($FLOAT, MathNode::Type::Constant);}
|
{$$ = new MathNode($FLOAT, MathNode::Type::cst);}
|
||||||
| ID
|
| ID
|
||||||
{$$ = new MathNode($ID,MathNode::Type::Variable);}
|
{$$ = new MathNode($ID,MathNode::Type::var);}
|
||||||
|
| 'r' expr
|
||||||
|
{$$ = new MathNode("return", MathNode::Type::keyw, 1, $2);}
|
||||||
| '-' expr %prec UMINUS
|
| '-' expr %prec UMINUS
|
||||||
{$$ = new MathNode("-", MathNode::Type::Operator, 1,$2);}
|
{$$ = new MathNode("-", MathNode::Type::op, 1, $2);}
|
||||||
|
| expr '=' expr
|
||||||
|
{$$ = new MathNode("=", MathNode::Type::op, 2, $1, $3);}
|
||||||
| expr '+' expr
|
| expr '+' expr
|
||||||
{$$ = new MathNode("+", MathNode::Type::Operator, 2, $1, $3);}
|
{$$ = new MathNode("+", MathNode::Type::op, 2, $1, $3);}
|
||||||
| expr '-' expr
|
| expr '-' expr
|
||||||
{$$ = new MathNode("-", MathNode::Type::Operator, 2, $1, $3);}
|
{$$ = new MathNode("-", MathNode::Type::op, 2, $1, $3);}
|
||||||
| expr '*' expr
|
| expr '*' expr
|
||||||
{$$ = new MathNode("*", MathNode::Type::Operator, 2, $1, $3);}
|
{$$ = new MathNode("*", MathNode::Type::op, 2, $1, $3);}
|
||||||
| expr '/' expr
|
| expr '/' expr
|
||||||
{$$ = new MathNode("/", MathNode::Type::Operator, 2, $1, $3);}
|
{$$ = new MathNode("/", MathNode::Type::op, 2, $1, $3);}
|
||||||
| expr '^' expr
|
| expr '^' expr
|
||||||
{$$ = new MathNode("^", MathNode::Type::Operator, 2, $1, $3);}
|
{$$ = new MathNode("^", MathNode::Type::op, 2, $1, $3);}
|
||||||
| '(' expr ')' {$$ = $2;}
|
| '(' expr ')'
|
||||||
|
{$$ = $2;}
|
||||||
;
|
;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user