#include #include #include #include #include #include #include std::string get_file_contents(std::ifstream& file_stream) { std::string file_string; file_stream.seekg(0, std::ios::end); file_string.resize(file_stream.tellg()); file_stream.seekg(0, std::ios::beg); file_stream.read(&file_string[0], file_string.size()); return file_string; } std::string get_brainfuck_code(const std::string& file) { std::string code; for (auto c : file) { switch (c) { case '>': case '<': case '+': case '-': case '.': case ',': case '[': case ']': code.push_back(c); } } return code; } template struct bf_context_t { std::array cells; std::stack scope; std::uintptr_t ptr; }; int main(int argc, char* argv[]) { if (argc < 2) { std::cout << "Usage: " << argv[0] << " [BRAINFUCK FILE]" << std::endl; return 1; } const std::string file_path = argv[1]; if (!std::filesystem::exists(file_path)) { std::cout << "Could not find file." << std::endl; return 1; } std::ifstream file_stream(file_path); if (!file_stream) { std::cout << "Could not open file." << std::endl; return 1; } const std::string file_contents = get_file_contents(file_stream); const std::string bf_code = get_brainfuck_code(file_contents); // by default, std::cin skips whitespace std::cin >> std::noskipws; auto ctx = bf_context_t{}; for (auto ip = 0; ip < bf_code.length(); ++ip) { switch (bf_code[ip]) { case '>': ++ctx.ptr; break; case '<': --ctx.ptr; break; case '+': ++ctx.cells[ctx.ptr]; break; case '-': --ctx.cells[ctx.ptr]; break; case '.': std::cout << (char)ctx.cells[ctx.ptr]; break; case ',': std::cin >> ctx.cells[ctx.ptr]; break; case '[': ctx.scope.push(ip); break; case ']': if (ctx.cells[ctx.ptr]) ip = ctx.scope.top() - 1; ctx.scope.pop(); break; } } }