diff --git a/Hash.cpp b/Hash.cpp deleted file mode 100644 index 7957b6e..0000000 --- a/Hash.cpp +++ /dev/null @@ -1,18 +0,0 @@ -#include "Hash.hpp" - -Hash::Hash() { - return; -} - -Hash::Hash(Hash const &hash) { - *this = hash; -} - -Hash &Hash::operator=(Hash const &hash) { - (void)hash; - return *this; -} - -Hash::~Hash() { - return; -} diff --git a/Hash.hpp b/Hash.hpp deleted file mode 100644 index c5b3bf7..0000000 --- a/Hash.hpp +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef HASH_HPP -# define HASH_HPP - - -class Hash { - - public: - - ~Hash(); - - private: - std::string _regex; - bool _isNeedParameter; - void () - void (Human::*arrayOfPointer[3])(std::string const &target) = {&Human::meleeAttack, &Human::rangedAttack, &Human::intimidatingShout}; - Hash(); - Hash(Hash const &src); - Hash &operator=(Hash const &rhs); -}; - -#endif diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..c151ba9 --- /dev/null +++ b/Makefile @@ -0,0 +1,27 @@ +NAME = abstractVm +FLAGS = -std=c++14 -Wall -Wextra -Werror +INCLUDE = includes/ +SRCSPATH = srcs/ +SRCS = Operand.cpp OperandFactory.cpp Stack.cpp StackManager.cpp eOperandType.cpp main.cpp +OBJ= $(SRC:.cpp=.o) +CC = clang++ + +SRC = $(addprefix $(SRCSPATH), $(SRCS)) + +%.o: %.cpp + $(CC) -I $(INCLUDE) -c $(FLAGS) $< -o $@ + +all: $(NAME) + +$(NAME): $(OBJ) + $(CC) $(FLAGS) -I $(INCLUDE) -o $(NAME) $(OBJ) + +clean: + rm -f $(OBJ) + +fclean: + rm -f $(NAME) $(OBJ) + +re: fclean all + +.PHONY: all clean fclean re \ No newline at end of file diff --git a/Operand.cpp b/Operand.cpp deleted file mode 100644 index 1157fa3..0000000 --- a/Operand.cpp +++ /dev/null @@ -1,90 +0,0 @@ -# include "Operand.hpp" - -template Operand::Operand(eOperandType type, T value) : _type(type), _value(value), _sValue(std::to_string(value)) { - return; -} - -template Operand::~Operand() { - return; -} - -template int Operand::getPrecision(void) const { - return this->_type;//a voir si je dois cast -} - -template eOperandType Operand::getType(void) const { - return this->_type; -} - - -template eOperandType Operand::getPriorityType(eOperandType const & firstType, eOperandType const & secondType) const { - if (firstType < secondType) - return firstType; - return secondType; -} - -template IOperand const * Operand::operator+(IOperand const & rhs) const { - eOperandType type = getPriorityType(this->getType() , rhs.getType()); - OperandFactory operandFactory; - - return operandFactory.createOperand(type, std::to_string(this->_value + std::stod(rhs.toString()))); -} - -template IOperand const * Operand::operator-(IOperand const & rhs) const { - OperandFactory operandFactory; - eOperandType type = getPriorityType(this->getType() , rhs.getType()); - return operandFactory.createOperand(type, std::to_string(this->_value - std::stod(rhs.toString()))); -} - -template IOperand const * Operand::operator*(IOperand const & rhs) const { - OperandFactory operandFactory; - eOperandType type = getPriorityType(this->getType() , rhs.getType()); - return operandFactory.createOperand(type, std::to_string(this->_value * std::stod(rhs.toString()))); -} - -template IOperand const * Operand::operator/(IOperand const & rhs) const { - OperandFactory operandFactory; - eOperandType type = getPriorityType(this->getType() , rhs.getType()); - if (std::stod(rhs.toString()) == 0) { - throw new ArithmeticException(); - } - return operandFactory.createOperand(type, std::to_string(this->_value / std::stod(rhs.toString()))); -} - -template IOperand const * Operand::operator%(IOperand const & rhs) const { - OperandFactory operandFactory; - eOperandType type = getPriorityType(this->_type, rhs.getType()); - if (std::stod(rhs.toString()) == 0) { - throw new ArithmeticException(); - } - return operandFactory.createOperand(type, std::to_string(std::fmod(this->_value, std::stod(rhs.toString())))); -} - -template std::string const & Operand::toString(void) const { - - return this->_sValue; -} - - -template Operand::Operand() : _type(Int32), _value(0) { - return; -} - -template Operand::Operand(Operand const &operand) { - *this = operand; - return; -} - -template Operand & Operand::operator=(Operand const &operand) { - if (this == &operand) - return (*this); - this->_value = operand._value; - this->_sValue = std::to_string(this->_value); - return *this; -} - -template class Operand; -template class Operand; -template class Operand; -template class Operand; -template class Operand; \ No newline at end of file diff --git a/OperandFactory.cpp b/OperandFactory.cpp deleted file mode 100644 index bff65d6..0000000 --- a/OperandFactory.cpp +++ /dev/null @@ -1,120 +0,0 @@ -#include "OperandFactory.hpp" - -OperandFactory::OperandFactory() { - return; -} - -OperandFactory::~OperandFactory() { - return; -} - -OperandFactory::OperandFactory(OperandFactory const &operandFactory) { - *this = operandFactory; - return; -} - -OperandFactory & OperandFactory::operator=(OperandFactory const &operandFactory) { - (void)operandFactory; - return *this; -} - -IOperand const * OperandFactory::createOperand(eOperandType type, std::string const & value) const { - IOperand const * (OperandFactory::*arrayOfPointer[5])(std::string const &value) const = { &OperandFactory::createInt8, - &OperandFactory::createInt16, - &OperandFactory::createInt32, - &OperandFactory::createFloat, - &OperandFactory::createDouble }; - return (this->*arrayOfPointer[type])(value);//CAST MAYBE -} - -IOperand const * OperandFactory::createInt8(std::string const & value) const { - int intValue = 0; - char const *error = "the value must be an int8 value"; - try { - intValue = std::stoi(value); - } catch(const std::out_of_range& e) { - - throw new OverflowException(error); - } - if (intValue < INT8_MIN || intValue > INT8_MAX) - throw new OverflowException(error); - eOperandType type = Int8; - return new Operand(type, static_cast(intValue)); -} - -IOperand const * OperandFactory::createInt16(std::string const & value) const { - int intValue = 0; - char const *error = "the value must be an int16 value"; - try { - intValue = std::stoi(value); - } catch(const std::out_of_range& e) { - throw new OverflowException(error); - } - if (intValue < INT16_MIN || intValue > INT16_MAX) - throw new OverflowException(error); - eOperandType type = Int16; - return new Operand(type, static_cast(intValue)); -} - -IOperand const * OperandFactory::createInt32(std::string const & value) const { - int intValue = 0; - char const *error = "the value must be an int32 value"; - try { - intValue = std::stoi(value); - } catch(const std::out_of_range& e) { - throw new OverflowException(error); - } - eOperandType type = Int32; - return new Operand(type, intValue); -} - -IOperand const * OperandFactory::createFloat(std::string const & value) const { - float floatValue = 0; - char const *error = "the value must be a float value"; - try { - floatValue = std::stof(value); - } catch(const std::out_of_range& e) { - throw new OverflowException(error); - } - eOperandType type = Float; - return new Operand(type, floatValue); -} - -IOperand const * OperandFactory::createDouble(std::string const & value) const { - double doubleValue = 0; - char const *error = "the value must be a double value"; - try { - doubleValue = std::stod(value); - } catch(const std::out_of_range& e) { - throw new OverflowException(error); - } - eOperandType type = Double; - return new Operand(type, doubleValue); -} - - -OperandFactory::OverflowException::OverflowException(char const *error) : _error(error) { - return; -} - -OperandFactory::OverflowException::~OverflowException(void) throw() { - return; -} - -OperandFactory::OverflowException::OverflowException(OverflowException const &overflowException) { - *this = overflowException; - return; -} - -OperandFactory::OverflowException & OperandFactory::OverflowException::operator=(OverflowException const &overflowException) { - (void)overflowException; - return *this; -} - -OperandFactory::OverflowException::OverflowException(void) { - return; -} - -const char *OperandFactory::OverflowException::what() const throw() { - return this->_error; -} diff --git a/Stack.cpp b/Stack.cpp deleted file mode 100644 index 5f80019..0000000 --- a/Stack.cpp +++ /dev/null @@ -1,150 +0,0 @@ -#include "Stack.hpp" - -Stack::Stack() { - return; -} - -Stack::Stack(Stack const &stack) { - *this = stack; -} - -Stack &Stack::operator=(Stack const &stack) { - this->c = stack.c; - return *this; -} - -Stack::~Stack() { - return; -} - -Stack::iterator Stack::begin() { - return this->c.begin(); -} - -Stack::iterator Stack::end() { - return this->c.end(); -} - -IOperand const & Stack::at(size_type pos) { - return *(this->c.at(pos)); -} - -void Stack::pop() { - if (this->empty() == true) - throw new StackSizeException(); - this->pop(); -} - -void Stack::dump() { - for (Stack::iterator iterator = this->begin(); iterator != this->end(); iterator++) { - std::cout << (*iterator)->toString() << std::endl; - } -} - -void Stack::assert(IOperand const & iOperand) { - if (this->empty() == true) - throw new StackSizeException(); - if (this->at(0).getType() != iOperand.getType() || this->at(0).toString() != iOperand.toString()) - throw new StackAssertException(true); -} - -void Stack::print() { - if (this->empty() == true) - throw new StackSizeException(); - if (this->at(0).getType() != Int8) - throw new StackAssertException(true); - std::cout << this->at(0).toString() << std::endl; -} - -void Stack::add() { - if (this->size() < 2) - throw new StackSizeException(); - IOperand const * iOperand = this->at(0) + this->at(1); - this->insert(iOperand); -} - -void Stack::sub() { - if (this->size() < 2) - throw new StackSizeException(); - IOperand const * iOperand = this->at(0) - this->at(1); - this->insert(iOperand); -} - -void Stack::mul() { - if (this->size() < 2) - throw new StackSizeException(); - IOperand const * iOperand = this->at(0) * this->at(1); - this->insert(iOperand); -} - -void Stack::div() { - if (this->size() < 2) - throw new StackSizeException(); - IOperand const * iOperand = this->at(0) / this->at(1); - this->insert(iOperand); -} - -void Stack::mod() { - if (this->size() < 2) - throw new StackSizeException(); - IOperand const * iOperand = this->at(0) % this->at(1); - this->insert(iOperand); -} - -void Stack::insert(IOperand const * iOperand) { - this->pop(); - this->pop(); - this->push(iOperand); -} - - -Stack::StackSizeException::StackSizeException() { - return; -} - -Stack::StackSizeException::~StackSizeException() throw() { - return; -} - -const char *Stack::StackSizeException::what() const throw() { - return "The number of element in the stack is too small for this action"; -} - -Stack::StackSizeException & Stack::StackSizeException::operator=(StackSizeException const &stackSizeException) { - (void)stackSizeException; - return *this; -} - -Stack::StackSizeException::StackSizeException(StackSizeException const &stackSizeException) { - *this = stackSizeException; - return; -} - - -Stack::StackAssertException::StackAssertException() { - return; -} - -Stack::StackAssertException::StackAssertException(bool isAssertInstruction) : _isAssertInstruction(isAssertInstruction){ - return; -} - -Stack::StackAssertException::~StackAssertException() throw() { - return; -} - -const char *Stack::StackAssertException::what() const throw() { - if (this->_isAssertInstruction == true) - return "The assert is false"; - return "The first element on the stack is not an int8 value"; -} - -Stack::StackAssertException & Stack::StackAssertException::operator=(StackAssertException const &stackAssertException) { - (void)stackAssertException; - return *this; -} - -Stack::StackAssertException::StackAssertException(StackAssertException const &stackAssertException) { - *this = stackAssertException; - return; -} diff --git a/a.out b/a.out deleted file mode 100755 index 599ae01..0000000 Binary files a/a.out and /dev/null differ diff --git a/IOperand.hpp b/includes/IOperand.hpp similarity index 91% rename from IOperand.hpp rename to includes/IOperand.hpp index c85889b..778c3fd 100644 --- a/IOperand.hpp +++ b/includes/IOperand.hpp @@ -2,14 +2,7 @@ # define IOPERAND_HPP # include - -enum eOperandType { - Int8, - Int16, - Int32, - Float, - Double -}; +# include "eOperandType.hpp" class IOperand { public: diff --git a/Operand.hpp b/includes/Operand.hpp similarity index 69% rename from Operand.hpp rename to includes/Operand.hpp index a611ca0..f1f105e 100644 --- a/Operand.hpp +++ b/includes/Operand.hpp @@ -2,6 +2,10 @@ # define OPERAND_TPP # include +# include +# include +# include +# include # include "IOperand.hpp" # include "OperandFactory.hpp" @@ -10,11 +14,11 @@ class Operand : public IOperand { public: Operand(); Operand(eOperandType type, T value); - Operand(Operand const &operand); virtual ~Operand(); int getPrecision(void) const; eOperandType getType(void) const; eOperandType getPriorityType(eOperandType const & firstType, eOperandType const & secondType) const; + IOperand const * resultOperand(IOperand const & rhs, std::string const & value) const; IOperand const * operator+(IOperand const & rhs) const; IOperand const * operator-(IOperand const & rhs) const; IOperand const * operator*(IOperand const & rhs) const; @@ -24,34 +28,22 @@ class Operand : public IOperand { class ArithmeticException : public std::exception { public: - virtual ~ArithmeticException(void) throw() { - return; - } - - ArithmeticException(void) { - return; - } - virtual const char *what() const throw() { - return "division or modulo by zero not allowed."; - } + virtual ~ArithmeticException(void) throw(); + ArithmeticException(void); + virtual const char *what() const throw(); + ArithmeticException(ArithmeticException const &arithmeticException); private: - ArithmeticException(ArithmeticException const &arithmeticException) { - *this = arithmeticException; - return; - } - - Operand::ArithmeticException & operator=(ArithmeticException const &arithmeticException) { - (void)arithmeticException; - return *this; - } + Operand::ArithmeticException & operator=(ArithmeticException const &arithmeticException); }; private: + Operand(Operand const &operand); Operand & operator=(Operand const &operand); - eOperandType _type; - T _value; - std::string _sValue; + static std::string const convertValueToString(T value); + eOperandType const _type; + T const _value; + std::string const _sValue; }; #endif diff --git a/OperandFactory.hpp b/includes/OperandFactory.hpp similarity index 69% rename from OperandFactory.hpp rename to includes/OperandFactory.hpp index 56435ce..a016c5d 100644 --- a/OperandFactory.hpp +++ b/includes/OperandFactory.hpp @@ -3,6 +3,8 @@ # include # include +# include +# include # include "IOperand.hpp" # include "Operand.hpp" @@ -12,15 +14,14 @@ class OperandFactory { virtual ~OperandFactory(); IOperand const * createOperand(eOperandType type, std::string const & value) const; - class OverflowException : public std::exception { + class OverflowException : public std::runtime_error { public: OverflowException(char const *error); virtual ~OverflowException() throw(); - virtual const char *what() const throw(); + OverflowException(OverflowException const &OverflowException); private: OverflowException(void); OperandFactory::OverflowException & operator=(OverflowException const &OverflowException); - OverflowException(OverflowException const &OverflowException); char const *_error; }; @@ -30,9 +31,15 @@ class OperandFactory { IOperand const * createInt8(std::string const & value) const; IOperand const * createInt16(std::string const & value) const; IOperand const * createInt32(std::string const & value) const; + IOperand const * createInt64(std::string const & value) const; IOperand const * createFloat(std::string const & value) const; IOperand const * createDouble(std::string const & value) const; + static double convertValue(eOperandType type, std::string const & value); + static std::map initMapMin(); + static std::map initMapMax(); + static std::map _mapMin; + static std::map _mapMax; }; - + #endif \ No newline at end of file diff --git a/Stack.hpp b/includes/Stack.hpp similarity index 88% rename from Stack.hpp rename to includes/Stack.hpp index 7db00fb..d8d742b 100644 --- a/Stack.hpp +++ b/includes/Stack.hpp @@ -3,6 +3,7 @@ # include # include +# include # include "IOperand.hpp" class Stack : public std::stack { @@ -11,15 +12,30 @@ class Stack : public std::stack { Stack(); ~Stack(); + void assert(IOperand const & iOperand); + void pop(); + void dump(); + void vdump(); + void add(); + void sub(); + void mul(); + void div(); + void mod(); + void max(); + void min(); + void drop(); + void print(); + void exit(); + void insert(IOperand const *); class StackSizeException : public std::exception { public: StackSizeException(void); virtual ~StackSizeException(void) throw(); virtual const char *what() const throw(); + StackSizeException(StackSizeException const &stackSizeException); private: Stack::StackSizeException & operator=(StackSizeException const &stackSizeException); - StackSizeException(StackSizeException const &stackSizeException); }; @@ -28,32 +44,20 @@ class Stack : public std::stack { StackAssertException(bool isAssertInstruction); virtual ~StackAssertException(void) throw(); virtual const char *what() const throw(); + StackAssertException(StackAssertException const &stackAssertException); private: Stack::StackAssertException & operator=(StackAssertException const &stackAssertException); StackAssertException(void); - StackAssertException(StackAssertException const &stackAssertException); bool _isAssertInstruction; }; private: - typedef std::stack::container_type::iterator iterator; + typedef std::stack::container_type::reverse_iterator iterator; Stack(Stack const &stack); Stack &operator=(Stack const &stack); iterator begin(); iterator end(); IOperand const & at(size_type pos); - void assert(IOperand const & iOperand); - void pop(); - void dump(); - void add(); - void sub(); - void mul(); - void div(); - void mod(); - void print(); - void insert(IOperand const *); }; -//REVOIR LE PRINT - #endif diff --git a/includes/StackManager.hpp b/includes/StackManager.hpp new file mode 100644 index 0000000..ab9c598 --- /dev/null +++ b/includes/StackManager.hpp @@ -0,0 +1,40 @@ +#ifndef STACK_MANAGER_HPP +# define STACK_MANAGER_HPP + +# include +# include +# include +# include +# include +# include +# include "OperandFactory.hpp" +# include "IOperand.hpp" +# include "Stack.hpp" + +class StackManager { + + public: + StackManager(); + ~StackManager(); + void push(std::string type, std::string value); + void assert(std::string type, std::string value); + void runInstruction(std::string instruction); + private: + StackManager(StackManager const &stackManager); + StackManager &operator=(StackManager const &stackManager); + IOperand const * getIOperand(std::string type, std::string value); + OperandFactory _operandFactory; + Stack _stack; + typedef std::map mapStack; + typedef std::map mapStackManager; + typedef std::map mapEOperandType; + static int lineIterator; + static mapStack initMapStack(); + static mapStackManager initMapStackManager(); + static mapEOperandType initMapEOperandType(); + static mapStack _mapOfPointerToStackMember; + static mapStackManager _mapOfPointerToStackManagerMember; + static mapEOperandType _mapEOperandType; +}; + +#endif \ No newline at end of file diff --git a/includes/eOperandType.hpp b/includes/eOperandType.hpp new file mode 100644 index 0000000..bcc437f --- /dev/null +++ b/includes/eOperandType.hpp @@ -0,0 +1,17 @@ +#ifndef EOPERAND_TYPE_HPP +# define EOPERAND_TYPE_HPP + +#include + +enum eOperandType { + Int8, + Int16, + Int32, + Int64, + Float, + Double +}; + +std::ostream & operator<<(std::ostream & os, eOperandType type); + +#endif \ No newline at end of file diff --git a/main.cpp b/main.cpp deleted file mode 100644 index 5e59c7a..0000000 --- a/main.cpp +++ /dev/null @@ -1,105 +0,0 @@ -#include -#include -#include -#include -#include -#include "OperandFactory.hpp" -// Rajoute un type -// Rajoute un operateur (pow) -// afficher toutes les erreurs - -std::vector getLinesFromStdin() { - std::vector lines = NULL; - std::string line = NULL; - while (line != ";;") { - std::getline(std::cin, line); - if (std::cin.bad() || std::cin.eof() || std::cin.fail()) - return NULL; - if (line != ";;") - lines.push_back(line); - } - return lines; -} - -std::vector getLinesFromFile(char *fileName) { - std::vector lines = NULL; - std::string line = NULL; - std::ifstream file(fileName); - - if (file) { - while (std::getline(file, line)) { - lines.push_back(line); - } - file.close(); - } - return lines; -} - - -// createOperant(string) { -// getType() -// create -// } - -// Push(string) { -// createOperant() -// stack.insert -// } - -// Assert() { -// createOperant() -// stackAssert() -// } - -int main(int ac, char **av) { - OperandFactory* operandFactory = new OperandFactory(); - std::vector lines; - std::vector hashList; - push_back(); - push_back(); - push_back(); - push_back(); - push_back(); - push_back(); - push_back(); - push_back(); - push_back(); - push_back(); - push_back(); - push_back(); - push_back(); - push_back(); - switch (ac) { - case 1: - lines = getLinesFromStdin(); - break; - case 2: - lines = getLinesFromFile(av[1]); - break; - default: - std::cout << "usage: ./abstract [file]" << std::endl; - return EXIT_FAILURE; - } - if (lines == NULL) { - //Do something ... - return EXIT_FAILURE; - } - for (std::vector::iterator it = lines.begin(); it != lines.end(); it++) { //*it for the string - - } - return EXIT_FAILURE; - // return EXIT_SUCCESS; -} - - - - // std::string regexs { '/^push int8\([-]?[\d]+\)(?:;(.*))?$/', - // '/^push int16\([-]?[\d]+\)(?:;(.*))?$/', - // '/^push int32\([-]?[\d]+\)(?:;(.*))?$/', - // '/^push float\([-]?[\d]+\.[\d]+\)(?:;(.*))?$/', - // '/^push double\([-]?[\d]+\.[\d]+\)(?:;(.*))?$/', - // '/^pop(?:;(.*))?$/', '/^dump(?:;(.*))?$/', - // '/^add(?:;(.*))?$/', '/^sub(?:;(.*))?$/', - // '/^mul(?:;(.*))?$/', '/^div(?:;(.*))?$/', - // '/^mod(?:;(.*))?$/', '/^print(?:;(.*))?$/', - // '/^exit(?:;(.*))?$/', '/^;;$/'} \ No newline at end of file diff --git a/srcs/Operand.cpp b/srcs/Operand.cpp new file mode 100644 index 0000000..83654ea --- /dev/null +++ b/srcs/Operand.cpp @@ -0,0 +1,114 @@ +# include "Operand.hpp" + +template Operand::Operand(eOperandType type, T value) : _type(type), _value(value), _sValue(convertValueToString(value)) { + return; +} + +template Operand::~Operand() { + return; +} + +template std::string const Operand::convertValueToString(T value) { + std::ostringstream out; + if (std::is_same::value) { + out << std::setprecision(std::numeric_limits::max_digits10) << static_cast(value); + } + else { + out << std::setprecision(std::numeric_limits::max_digits10) << value; + } + return out.str(); +} + +template int Operand::getPrecision(void) const { + return static_cast(this->_type); +} + +template eOperandType Operand::getType(void) const { + return this->_type; +} + + +template eOperandType Operand::getPriorityType(eOperandType const & firstType, eOperandType const & secondType) const { + if (firstType < secondType) + return secondType; + return firstType; +} +template IOperand const * Operand::resultOperand(IOperand const & rhs, std::string const & value) const { + OperandFactory operandFactory; + return operandFactory.createOperand(getPriorityType(this->getType() , rhs.getType()), value); +} + +template IOperand const * Operand::operator+(IOperand const & rhs) const { + return this->resultOperand(rhs, std::to_string(this->_value + std::stod(rhs.toString()))); +} + +template IOperand const * Operand::operator-(IOperand const & rhs) const { + return this->resultOperand(rhs, std::to_string(this->_value - std::stod(rhs.toString()))); +} + +template IOperand const * Operand::operator*(IOperand const & rhs) const { + return this->resultOperand(rhs, std::to_string(this->_value * std::stod(rhs.toString()))); +} + +template IOperand const * Operand::operator/(IOperand const & rhs) const { + if (std::stod(rhs.toString()) == 0) { + throw ArithmeticException(); + } + return this->resultOperand(rhs, std::to_string(this->_value / std::stod(rhs.toString()))); +} + +template IOperand const * Operand::operator%(IOperand const & rhs) const { + if (std::stod(rhs.toString()) == 0) { + throw ArithmeticException(); + } + return this->resultOperand(rhs, std::to_string(std::fmod(this->_value, std::stod(rhs.toString())))); +} + +template std::string const & Operand::toString(void) const { + return this->_sValue; +} + + +template Operand::Operand() : _type(Int32), _value(0) { + return; +} + +template Operand::Operand(Operand const &operand) : _type(operand._type), _value(operand._value), _sValue(operand._sValue) { + *this = operand; + return; +} + +template Operand & Operand::operator=(Operand const &operand) { + if (this == &operand) + return (*this); + return *this; +} + +template Operand::ArithmeticException::~ArithmeticException(void) throw() { + +} + +template Operand::ArithmeticException::ArithmeticException(void) { + +} + +template const char *Operand::ArithmeticException::what() const throw() { + return "ArithmeticException: division or modulo by zero not allowed."; +} + +template Operand::ArithmeticException::ArithmeticException(ArithmeticException const &arithmeticException) { + *this = arithmeticException; + return; +} + +template typename Operand::ArithmeticException & Operand::ArithmeticException::operator=(ArithmeticException const &arithmeticException) { + (void)arithmeticException; + return *this; +} + +template class Operand; +template class Operand; +template class Operand; +template class Operand; +template class Operand; +template class Operand; \ No newline at end of file diff --git a/srcs/OperandFactory.cpp b/srcs/OperandFactory.cpp new file mode 100644 index 0000000..73c608f --- /dev/null +++ b/srcs/OperandFactory.cpp @@ -0,0 +1,123 @@ +#include "OperandFactory.hpp" +#include +#include +#include +#include +OperandFactory::OperandFactory() { + return; +} + +OperandFactory::~OperandFactory() { + return; +} + +OperandFactory::OperandFactory(OperandFactory const &operandFactory) { + *this = operandFactory; + return; +} + +OperandFactory & OperandFactory::operator=(OperandFactory const &operandFactory) { + (void)operandFactory; + return *this; +} + +IOperand const * OperandFactory::createOperand(eOperandType type, std::string const & value) const { + IOperand const * (OperandFactory::*arrayOfPointer[6])(std::string const &value) const = { &OperandFactory::createInt8, + &OperandFactory::createInt16, + &OperandFactory::createInt32, + &OperandFactory::createInt64, + &OperandFactory::createFloat, + &OperandFactory::createDouble }; + return (this->*arrayOfPointer[static_cast(type)])(value); +} + +double OperandFactory::convertValue(eOperandType type, std::string const & value) { + double doubleValue; + std::ostringstream stream; + stream << "OverflowException: the value must be an " << type << " value"; + std::string str = stream.str(); + char const *error = str.c_str(); + try { + doubleValue = std::stod(value); + } catch(const std::out_of_range& e) { + throw OverflowException(error); + } + if (doubleValue < OperandFactory::_mapMin[type] || doubleValue > OperandFactory::_mapMax[type]) { + throw OverflowException(error); + } + return doubleValue; +} + +IOperand const * OperandFactory::createInt8(std::string const & value) const { + return new Operand(Int8, static_cast(this->convertValue(Int8, value))); +} + +IOperand const * OperandFactory::createInt16(std::string const & value) const { + return new Operand(Int16, static_cast(this->convertValue(Int16, value))); +} + +IOperand const * OperandFactory::createInt32(std::string const & value) const { + return new Operand(Int32, static_cast(this->convertValue(Int32, value))); +} + +IOperand const * OperandFactory::createInt64(std::string const & value) const { + return new Operand(Int64, static_cast(this->convertValue(Int64, value))); +} + +IOperand const * OperandFactory::createFloat(std::string const & value) const { + return new Operand(Float, static_cast(this->convertValue(Float, value))); +} + +IOperand const * OperandFactory::createDouble(std::string const & value) const { + return new Operand(Double, this->convertValue(Double, value)); +} + + +OperandFactory::OverflowException::OverflowException(char const *error) : runtime_error(error), _error(error) { + return; +} + +OperandFactory::OverflowException::~OverflowException(void) throw() { + return; +} + +OperandFactory::OverflowException::OverflowException(OverflowException const &overflowException) : runtime_error(overflowException._error) { + *this = overflowException; + return; +} + +OperandFactory::OverflowException & OperandFactory::OverflowException::operator=(OverflowException const &overflowException) { + (void)overflowException; + return *this; +} + +OperandFactory::OverflowException::OverflowException(void) : runtime_error("OverflowException : the value isn't good") { + return; +} + +std::map OperandFactory::initMapMin() { + std::map mapMin = { + {Int8, static_cast(std::numeric_limits::lowest())}, + {Int16, static_cast(std::numeric_limits::lowest())}, + {Int32, static_cast(std::numeric_limits::lowest())}, + {Int64, static_cast(std::numeric_limits::lowest())}, + {Float, static_cast(std::numeric_limits::lowest())}, + {Double, static_cast(std::numeric_limits::lowest())} + }; + return mapMin; +} + +std::map OperandFactory::initMapMax() { + std::map mapMax = { + {Int8, static_cast(std::numeric_limits::max())}, + {Int16, static_cast(std::numeric_limits::max())}, + {Int32, static_cast(std::numeric_limits::max())}, + {Int64, static_cast(std::numeric_limits::max())}, + {Float, static_cast(std::numeric_limits::max())}, + {Double, static_cast(std::numeric_limits::max())} + }; + return mapMax; +} + +std::map OperandFactory::_mapMin = initMapMin(); +std::map OperandFactory::_mapMax = initMapMax(); diff --git a/srcs/Stack.cpp b/srcs/Stack.cpp new file mode 100644 index 0000000..c8e828e --- /dev/null +++ b/srcs/Stack.cpp @@ -0,0 +1,200 @@ +#include "Stack.hpp" + +Stack::Stack() { + return; +} + +Stack::Stack(Stack const &stack) { + *this = stack; +} + +Stack &Stack::operator=(Stack const &stack) { + this->c = stack.c; + return *this; +} + +Stack::~Stack() { + return; +} + +Stack::iterator Stack::begin() { + return this->c.rbegin(); +} + +Stack::iterator Stack::end() { + return this->c.rend(); +} + +IOperand const & Stack::at(size_type pos) { + return *(this->c.at(this->size() - (pos + 1))); +} + +void Stack::pop() { + if (this->empty() == true) + throw StackSizeException(); + std::stack::pop(); +} + +void Stack::dump() { + for (Stack::iterator iterator = this->begin(); iterator != this->end(); iterator++) { + std::cout << (*iterator)->toString() << std::endl; + } +} + +void Stack::vdump() { + for (Stack::iterator iterator = this->begin(); iterator != this->end(); iterator++) { + std::cout << "type: " << (*iterator)->getType() << "\tvalue: " << (*iterator)->toString() << std::endl; + } +} + +void Stack::assert(IOperand const & iOperand) { + if (this->empty() == true) + throw StackSizeException(); + if (this->at(0).getType() != iOperand.getType() || this->at(0).toString() != iOperand.toString()) { + throw StackAssertException(true); + } +} + +void Stack::print() { + if (this->empty() == true) + throw StackSizeException(); + if (this->at(0).getType() != Int8) + throw StackAssertException(false); + std::cout << static_cast(std::stoi(this->at(0).toString())) << std::endl; +} + +void Stack::add() { + if (this->size() < 2) + throw StackSizeException(); + IOperand const * iOperand = this->at(1) + this->at(0); + this->insert(iOperand); +} + +void Stack::sub() { + if (this->size() < 2) + throw StackSizeException(); + IOperand const * iOperand = this->at(1) - this->at(0); + this->insert(iOperand); +} + +void Stack::mul() { + if (this->size() < 2) + throw StackSizeException(); + IOperand const * iOperand = this->at(1) * this->at(0); + this->insert(iOperand); +} + +void Stack::div() { + if (this->size() < 2) + throw StackSizeException(); + IOperand const * iOperand = this->at(1) / this->at(0); + this->insert(iOperand); +} + +void Stack::mod() { + if (this->size() < 2) + throw StackSizeException(); + IOperand const * iOperand = this->at(1) % this->at(0); + this->insert(iOperand); +} + +void Stack::max() { + Stack::iterator finalIterator; + double value; + if (this->empty() == true) { + throw StackSizeException(); + } + finalIterator = this->begin(); + value = std::stod(this->at(0).toString()); + for (Stack::iterator iterator = this->begin() + 1; iterator != this->end(); iterator++) { + if (std::stod((*iterator)->toString()) > value) { + value = std::stod((*iterator)->toString()); + finalIterator = iterator; + } + } + std::cout << (*finalIterator)->toString() << std::endl; +} + +void Stack::min() { + Stack::iterator finalIterator; + double value; + if (this->empty() == true) { + throw StackSizeException(); + } + finalIterator = this->begin(); + value = std::stod(this->at(0).toString()); + for (Stack::iterator iterator = this->begin() + 1; iterator != this->end(); iterator++) { + if (std::stod((*iterator)->toString()) < value) { + value = std::stod((*iterator)->toString()); + finalIterator = iterator; + } + } + std::cout << (*finalIterator)->toString() << std::endl; +} + +void Stack::drop() { + while (this->empty() == false) { + std::stack::pop(); + } +} + +void Stack::insert(IOperand const * iOperand) { + this->pop(); + this->pop(); + std::stack::push(iOperand); +} + +void Stack::exit() { + std::exit(EXIT_SUCCESS); +} + +Stack::StackSizeException::StackSizeException() { + return; +} + +Stack::StackSizeException::~StackSizeException() throw() { + return; +} + +const char *Stack::StackSizeException::what() const throw() { + return "StackSizeException: the number of element in the stack is too small for this action"; +} + +Stack::StackSizeException & Stack::StackSizeException::operator=(StackSizeException const &stackSizeException) { + (void)stackSizeException; + return *this; +} + +Stack::StackSizeException::StackSizeException(StackSizeException const &stackSizeException) { + *this = stackSizeException; + return; +} + + +Stack::StackAssertException::StackAssertException() { + return; +} + +Stack::StackAssertException::StackAssertException(bool isAssertInstruction) : _isAssertInstruction(isAssertInstruction){ + return; +} + +Stack::StackAssertException::~StackAssertException() throw() { + return; +} + +const char *Stack::StackAssertException::what() const throw() { + if (this->_isAssertInstruction == true) + return "StackAssertException: The assert is false"; + return "StackAssertException: The first element on the stack is not an int8 value"; +} + +Stack::StackAssertException & Stack::StackAssertException::operator=(StackAssertException const &stackAssertException) { + (void)stackAssertException; + return *this; +} + +Stack::StackAssertException::StackAssertException(StackAssertException const &stackAssertException) { + *this = stackAssertException; + return; +} diff --git a/srcs/StackManager.cpp b/srcs/StackManager.cpp new file mode 100644 index 0000000..2d41711 --- /dev/null +++ b/srcs/StackManager.cpp @@ -0,0 +1,111 @@ +#include "StackManager.hpp" + +StackManager::StackManager() { + return; +} + +StackManager::StackManager(StackManager const &stackManager) { + *this = stackManager; +} + +StackManager &StackManager::operator=(StackManager const &stackManager) { + (void)stackManager; + return *this; +} + +StackManager::~StackManager() { + return; +} + +IOperand const * StackManager::getIOperand(std::string type, std::string value) { + return this->_operandFactory.createOperand(this->_mapEOperandType[type], value); +} + +void StackManager::push(std::string type, std::string value) { + IOperand const * iOperand = this->getIOperand(type, value); + this->_stack.push(iOperand); +} + +void StackManager::assert(std::string type, std::string value) { + IOperand const * iOperand = this->getIOperand(type, value); + this->_stack.assert(*iOperand); +} + +void StackManager::runInstruction(std::string instruction) { + std::cmatch match; + StackManager::lineIterator += 1; + for(auto mapStackManager : this->_mapOfPointerToStackManagerMember) { + if (std::regex_search(instruction.c_str(), match, std::regex(mapStackManager.first))) { + try { + (this->*mapStackManager.second)(match[1], match[2]); + } + catch (std::exception const & e) { + std::cerr << "\e[1;1m" << "line:" << StackManager::lineIterator << ": " + << "\e[1;91m" << "error: " << "\e[0;0m" << "\e[1;1m" << e.what() << " : " << std::endl << "\e[0;0m" << "\e[1;32m" << "> " + << "\e[0;0m" << instruction << std::endl; + } + return; + } + } + for (auto mapStack : this->_mapOfPointerToStackMember) { + if (std::regex_match(instruction, std::regex(mapStack.first))) { + try { + (this->_stack.*(mapStack.second))(); + } + catch (std::exception const & e) { + std::cerr << "\e[1;1m" << "line:" << StackManager::lineIterator << ": " + << "\e[1;91m" << "error: " << "\e[0;0m" << "\e[1;1m" << e.what() << " : " << std::endl << "\e[0;0m" << "\e[1;32m" << "> " + << "\e[0;0m" << instruction << std::endl; + } + return; + } + } + if (!std::regex_match(instruction, std::regex("^(?:;.*)$"))) { + std::cerr << "\e[1;1m" << "line:" << StackManager::lineIterator << ": " + << "\e[1;91m" << "error: " << "\e[0;0m" << "\e[1;1m" << "invalid instruction :" << std::endl + << "\e[0;0m" << "\e[1;32m" << "> " << "\e[0;0m" << instruction << std::endl; + } +} + +StackManager::mapStack StackManager::initMapStack() { + StackManager::mapStack mapOfPointerToStackMember; + mapOfPointerToStackMember["^pop\\s*(?:;.*)?$"] = &Stack::pop; + mapOfPointerToStackMember["^dump\\s*(?:;.*)?$"] = &Stack::dump; + mapOfPointerToStackMember["^vdump\\s*(?:;.*)?$"] = &Stack::vdump; + mapOfPointerToStackMember["^add\\s*(?:;.*)?$"] = &Stack::add; + mapOfPointerToStackMember["^sub\\s*(?:;.*)?$"] = &Stack::sub; + mapOfPointerToStackMember["^mul\\s*(?:;.*)?$"] = &Stack::mul; + mapOfPointerToStackMember["^div\\s*(?:;.*)?$"] = &Stack::div; + mapOfPointerToStackMember["^mod\\s*(?:;.*)?$"] = &Stack::mod; + mapOfPointerToStackMember["^max\\s*(?:;.*)?$"] = &Stack::max; + mapOfPointerToStackMember["^min\\s*(?:;.*)?$"] = &Stack::min; + mapOfPointerToStackMember["^drop\\s*(?:;.*)?$"] = &Stack::drop; + mapOfPointerToStackMember["^print\\s*(?:;.*)?$"] = &Stack::print; + mapOfPointerToStackMember["^exit\\s*(?:;.*)?$"] = &Stack::exit; + return mapOfPointerToStackMember; +} + +StackManager::mapStackManager StackManager::initMapStackManager() { + StackManager::mapStackManager mapOfPointerToStackManagerMember; + mapOfPointerToStackManagerMember["^push (int(?:8|16|32|64))\\(([-]?[\\d]+)\\)\\s*(?:;.*)?$"] = &StackManager::push; + mapOfPointerToStackManagerMember["^push (float|double)\\(([-]?[\\d]+\\.[\\d]+)\\)\\s*(?:;.*)?$"] = &StackManager::push; + mapOfPointerToStackManagerMember["^assert (int(?:8|16|32|64))\\(([-]?[\\d]+)\\)\\s*(?:;.*)?$"] = &StackManager::assert; + mapOfPointerToStackManagerMember["^assert (float|double)\\(([-]?[\\d]+\\.[\\d]+)\\)\\s*(?:;.*)?$"] = &StackManager::assert; + return mapOfPointerToStackManagerMember; +} + +StackManager::mapEOperandType StackManager::initMapEOperandType() { + StackManager::mapEOperandType mapEOperandType; + mapEOperandType["int8"] = Int8; + mapEOperandType["int16"] = Int16; + mapEOperandType["int32"] = Int32; + mapEOperandType["int64"] = Int64; + mapEOperandType["float"] = Float; + mapEOperandType["double"] = Double; + return mapEOperandType; +} + +int StackManager::lineIterator = 0; +StackManager::mapStack StackManager::_mapOfPointerToStackMember = initMapStack(); +StackManager::mapStackManager StackManager::_mapOfPointerToStackManagerMember = initMapStackManager(); +StackManager::mapEOperandType StackManager::_mapEOperandType = initMapEOperandType(); \ No newline at end of file diff --git a/srcs/eOperandType.cpp b/srcs/eOperandType.cpp new file mode 100644 index 0000000..61fa31a --- /dev/null +++ b/srcs/eOperandType.cpp @@ -0,0 +1,29 @@ +#include "eOperandType.hpp" + +std::ostream & operator<<(std::ostream & os, eOperandType type) { + switch(type) + { + case Int8: + os << "Int8"; + break; + case Int16: + os << "Int16"; + break; + case Int32: + os << "Int32"; + break; + case Int64: + os << "Int64"; + break; + case Float: + os << "Float"; + break; + case Double: + os << "Double"; + break; + default: + os << "type undifined"; + break; + } + return os; +} \ No newline at end of file diff --git a/srcs/main.cpp b/srcs/main.cpp new file mode 100644 index 0000000..f38e4a8 --- /dev/null +++ b/srcs/main.cpp @@ -0,0 +1,61 @@ +#include +#include +#include +#include +#include "StackManager.hpp" + +std::vector getLinesFromStdin() { + std::vector lines; + std::string line; + while (line != ";;") { + std::getline(std::cin, line); + if (std::cin.bad() || std::cin.eof() || std::cin.fail()) + return lines; + if (line != ";;") + lines.push_back(line); + } + return lines; +} + +std::vector getLinesFromFile(char *fileName) { + std::vector lines; + std::string line; + std::ifstream file(fileName); + + if (file) { + while (std::getline(file, line)) { + lines.push_back(line); + } + file.close(); + } + return lines; +} + +int main(int ac, char **av) { + StackManager *stackManager = new StackManager(); + std::vector lines; + switch (ac) { + case 1: + lines = getLinesFromStdin(); + break; + case 2: + lines = getLinesFromFile(av[1]); + break; + default: + std::cerr << "Usage: ./abstract [file]." << std::endl; + delete stackManager; + return EXIT_FAILURE; + } + if (lines.empty()) { + std::cerr << "\e[1;91m" << "error: " << "\e[0;0m" << "\e[1;1m" << " problem while reading the file or the input from terminal." << "\e[0;0m" << std::endl; + return EXIT_FAILURE; + } + for (auto line : lines) { + if (!line.empty()) { + stackManager->runInstruction(line); + } + } + std::cerr << "\e[1;91m" << "error: " << "\e[0;0m" << "\e[1;1m" << "No exit instruction found." << "\e[0;0m" << std::endl; + delete stackManager; + return EXIT_FAILURE; +} \ No newline at end of file