/* * MathInterpreter.hpp, part of LatAnalyze 3 * * Copyright (C) 2013 - 2016 Antonin Portelli * * LatAnalyze 3 is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * LatAnalyze 3 is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with LatAnalyze 3. If not, see . */ #ifndef Latan_MathInterpreter_hpp_ #define Latan_MathInterpreter_hpp_ #include #include #include #define MAXIDLENGTH 256 BEGIN_LATAN_NAMESPACE /****************************************************************************** * Class for runtime context * ******************************************************************************/ class RunContext { public: typedef std::map AddressTable; public: // constructor RunContext(void) = default; // destructor ~RunContext(void) = default; // access unsigned int addFunction(const std::string &name, DoubleFunction *init = nullptr); unsigned int addVariable(const std::string &name, const double init = 0.); DoubleFunction * getFunction(const std::string &name) const; DoubleFunction * getFunction(const unsigned int address) const; unsigned int getFunctionAddress(const std::string &name) const; const AddressTable & getFunctionTable(void) const; unsigned int getInsIndex(void) const; double getVariable(const std::string &name) const; double getVariable(const unsigned int address) const; unsigned int getVariableAddress(const std::string &name) const; const AddressTable & getVariableTable(void) const; void incrementInsIndex(const unsigned int inc = 1); void setFunction(const std::string &name, DoubleFunction *f); void setFunction(const unsigned int address, DoubleFunction *f); void setInsIndex(const unsigned index); void setVariable(const std::string &name, const double value); void setVariable(const unsigned int address, const double value); std::stack & stack(void); // reset void reset(void); private: unsigned int insIndex_; std::stack dStack_; std::vector vMem_; std::vector fMem_; AddressTable vTable_, fTable_; }; /****************************************************************************** * Instruction classes * ******************************************************************************/ // Abstract base class Instruction { public: // destructor virtual ~Instruction(void) = default; // 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; }; std::ostream & operator<<(std::ostream &out, const Instruction &ins); // Instruction container typedef std::vector> Program; // Push class Push: public Instruction { private: enum class ArgType { Constant = 0, Variable = 1 }; public: //constructors explicit Push(const double val); explicit Push(const unsigned int address, const std::string &name); // instruction execution virtual void operator()(RunContext &context) const; private: virtual void print(std::ostream& out) const; private: ArgType type_; double val_; unsigned int address_; std::string name_; }; // Pop class Pop: public Instruction { public: //constructor explicit Pop(const unsigned int address, const std::string &name); // instruction execution virtual void operator()(RunContext &context) const; private: virtual void print(std::ostream& out) const; private: unsigned int address_; std::string name_; }; // Store class Store: public Instruction { public: //constructor explicit Store(const unsigned int address, const std::string &name); // instruction execution virtual void operator()(RunContext &context) const; private: virtual void print(std::ostream& out) const; private: unsigned int address_; std::string name_; }; // Call function class Call: public Instruction { public: //constructor explicit Call(const unsigned int address, const std::string &name); // instruction execution virtual void operator()(RunContext &context) const; private: virtual void print(std::ostream& out) const; private: unsigned int address_; 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); /****************************************************************************** * Expression node classes * ******************************************************************************/ class ExprNode { public: // constructors explicit ExprNode(const std::string &name); // destructor virtual ~ExprNode() = default; // access const std::string& getName(void) const; Index getNArg(void) const; const ExprNode * getParent(void) const; Index getLevel(void) const; void setName(const std::string &name); void pushArg(ExprNode *node); // operator const ExprNode &operator[](const Index i) const; // compile virtual void compile(Program &program, RunContext &context) const = 0; private: std::string name_; std::vector> arg_; const ExprNode * parent_; }; std::ostream &operator<<(std::ostream &out, const ExprNode &n); #define DECL_NODE(base, name) \ class name: public base\ {\ public:\ using base::base;\ virtual void compile(Program &program, RunContext &context) const;\ } DECL_NODE(ExprNode, VarNode); DECL_NODE(ExprNode, CstNode); DECL_NODE(ExprNode, SemicolonNode); DECL_NODE(ExprNode, AssignNode); DECL_NODE(ExprNode, MathOpNode); DECL_NODE(ExprNode, FuncNode); class KeywordNode: public ExprNode { public: using ExprNode::ExprNode; virtual void compile(Program &program, RunContext &context) const = 0; }; DECL_NODE(KeywordNode, ReturnNode); /****************************************************************************** * Interpreter class * ******************************************************************************/ class MathInterpreter { public: // parser state class MathParserState: public ParserState> { public: // constructor explicit MathParserState(std::istream *stream, std::string *name, std::unique_ptr *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 }; }; public: // constructors MathInterpreter(void) = default; MathInterpreter(const std::string &code); // destructor ~MathInterpreter(void) = default; // access const Instruction * operator[](const Index i) const; const ExprNode * getAST(void) const; // initialization void setCode(const std::string &code); // interpreter void compile(RunContext &context); // 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 ExprNode &node); // execution void execute(RunContext &context) const; private: std::unique_ptr code_{nullptr}; std::string codeName_{""}; std::unique_ptr state_{nullptr}; std::unique_ptr root_{nullptr}; Program program_; unsigned int status_{Status::none}; }; std::ostream & operator<<(std::ostream &out, const MathInterpreter &program); END_LATAN_NAMESPACE #endif // Latan_MathInterpreter_hpp_