mirror of
				https://github.com/aportelli/LatAnalyze.git
				synced 2025-10-28 13:59:32 +00:00 
			
		
		
		
	first working version of the math compiler
This commit is contained in:
		
							
								
								
									
										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 | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user