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