Files
scripts/cpp/brainfuck/brainfuck.cpp
2019-05-25 19:06:58 +03:00

88 lines
2.2 KiB
C++

#include <cstdint>
#include <string>
#include <array>
#include <stack>
#include <fstream>
#include <iostream>
#include <filesystem>
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<typename value_type, std::size_t size>
struct bf_context_t {
std::array<value_type, size> cells;
std::stack<std::size_t> scope;
std::uintptr_t ptr;
};
int main(int argc, char* argv[]) {
if (argc < 2) {
std::cout << "Usage: " << argv[0] << 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<std::uint8_t, 30'000>{};
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;
}
}
}