Skip to content

Instantly share code, notes, and snippets.

@inxanedev
Created February 6, 2022 09:54
Show Gist options
  • Save inxanedev/711871b805aed0c16d639452f8d6e1bf to your computer and use it in GitHub Desktop.
Save inxanedev/711871b805aed0c16d639452f8d6e1bf to your computer and use it in GitHub Desktop.
Brainfuck intepreter in C++
#include <vector>
#include <iostream>
#include <string>
#include <fstream>
#include <unordered_map>
class Interpreter {
public:
using SourceType = std::vector<char>;
template <typename T>
class Memory {
public:
Memory() {
memory.push_back(0);
}
size_t left() {
if (index != 0) index--;
return index;
}
size_t right() {
if (index + 1 >= memory.size()) {
memory.push_back(0);
}
return ++index;
}
T increment() {
return ++memory[index];
}
T decrement() {
return --memory[index];
}
T get() {
return memory[index];
}
T set(T value) {
return (memory[index] = value);
}
private:
std::vector<T> memory;
size_t index = 0;
};
public:
static SourceType read_source(const std::string& filename) {
SourceType source;
std::ifstream file(filename);
char c;
while (file.get(c)) {
source.push_back(c);
}
return source;
}
public:
Interpreter() = delete;
Interpreter(const std::string& filename)
: source(Interpreter::read_source(filename)) {}
Interpreter(SourceType&& source)
: source(std::move(source)) {}
Interpreter(const SourceType& source)
: source(source) {}
public:
void execute() {
Memory<uint32_t> memory;
std::unordered_map<size_t, size_t> loops;
size_t index = 0;
while (index < source.size()) {
char c = source[index];
if (c == '>') memory.right();
else if (c == '<') memory.left();
else if (c == '+') memory.increment();
else if (c == '-') memory.decrement();
else if (c == ',') {
char input;
std::cin >> input;
memory.set(static_cast<uint32_t>(input));
}
else if (c == '.')
std::cout << static_cast<char>(memory.get());
else if (c == '[') {
if (memory.get() == 0)
index = get_matching_brace(index);
else
loops[get_matching_brace(index)] = index;
}
else if (c == ']') {
if (memory.get() != 0)
index = loops[index];
}
index++;
}
}
size_t get_matching_brace(size_t first) {
size_t count = first;
uint32_t nest_counter = 0;
while (count < source.size()) {
char c = source[++count];
if (c == '[') nest_counter++;
else if (c == ']') {
if (nest_counter == 0) {
return count;
}
else nest_counter--;
}
}
std::cerr << "cant find matching brace\n";
std::exit(-1);
}
private:
const SourceType source;
};
int main(int argc, char* argv[]) {
if (argc < 2) {
std::cout << "Usage: " << argv[0] << " filename.bf\n";
return -1;
}
Interpreter interpreter(argv[1]);
interpreter.execute();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment