/* * Parsodus - A language agnostic parser generator * Copyright © 2016-2017 Thomas Avé, Robin Jadoul, Kobe Wullaert * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #pragma once #ifndef INSTRUCTION_H #define INSTRUCTION_H #include #include #include #include namespace bf { using Data = std::array; class Instruction { public: virtual void execute(Data& d, std::size_t& data_ptr) const = 0; virtual void print() const = 0; }; class InstructionRight : public Instruction { public: void execute(Data&, std::size_t& data_ptr) const { data_ptr++; if (data_ptr >= 30000) { std::cerr << "Out of bounds" << std::endl; std::exit(1); } }; void print() const { std::cout << ">"; } }; class InstructionLeft : public Instruction { public: void execute(Data&, std::size_t& data_ptr) const { data_ptr--; if (data_ptr >= 30000) { //wraps around when below 0 std::cerr << "Out of bounds" << std::endl; std::exit(1); } }; void print() const { std::cout << "<"; } }; class InstructionInc : public Instruction { public: void execute(Data& d, std::size_t& ptr) const { d[ptr]++; } void print() const { std::cout << "+"; } }; class InstructionDec : public Instruction { public: void execute(Data& d, std::size_t& ptr) const { d[ptr]--; } void print() const { std::cout << "-"; } }; class InstructionOut : public Instruction { public: void execute(Data& d, std::size_t& ptr) const { std::cout << static_cast(d[ptr]); } void print() const { std::cout << "."; } }; class InstructionIn : public Instruction { public: void execute(Data& d, std::size_t& ptr) const { char c = -1; if (!std::cin.eof()) std::cin.get(c); d[ptr] = c; } void print() const { std::cout << ","; } }; class InstructionLoop : public Instruction { public: InstructionLoop(std::deque>&& body) : m_body(std::move(body)) {}; void execute(Data& d, std::size_t& ptr) const { while (d[ptr] != 0) { for (auto& b : m_body) b->execute(d, ptr); } } void print() const { std::cout << "["; for (auto& b : m_body) b->print(); std::cout << "]"; } private: std::deque> m_body; }; } #endif