88 lines
2.2 KiB
C++
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] << " [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<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;
|
|
}
|
|
}
|
|
}
|