Add brainfuck.cpp
This commit is contained in:
2
cpp/brainfuck/Makefile
Normal file
2
cpp/brainfuck/Makefile
Normal file
@@ -0,0 +1,2 @@
|
||||
all:
|
||||
g++ -std=c++17 -O2 brainfuck.cpp -lstdc++fs -o brainfuck
|
||||
87
cpp/brainfuck/brainfuck.cpp
Normal file
87
cpp/brainfuck/brainfuck.cpp
Normal file
@@ -0,0 +1,87 @@
|
||||
#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;
|
||||
}
|
||||
}
|
||||
}
|
||||
1
cpp/brainfuck/cat.bf
Normal file
1
cpp/brainfuck/cat.bf
Normal file
@@ -0,0 +1 @@
|
||||
,[.[-],]
|
||||
1
cpp/brainfuck/helloworld.bf
Normal file
1
cpp/brainfuck/helloworld.bf
Normal file
@@ -0,0 +1 @@
|
||||
++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.
|
||||
Reference in New Issue
Block a user