Skip to content

Instantly share code, notes, and snippets.

@ysakasin
Last active Jan 22, 2018
Embed
What would you like to do?
// Copyright (c) 2018 SAKATA Sinji. Released under the MIT license.
#include <fstream>
#include <iostream>
#include <iterator>
#include <string>
#include <vector>
using namespace std;
const int DataSize = 30000;
enum OP_CODE {
OP_ADD_PTR = 0,
OP_ADD_DATA,
OP_READ,
OP_OUT,
OP_JUMP,
OP_JUMP_BK,
};
const string code_s[] = {
"addptr", "adddata", "read", "out", "jump", "jumpbk",
};
struct Operation {
OP_CODE op;
int value;
};
using Program = vector<Operation>;
Program parse(const string &code) {
int cp = 0;
int pp = 0;
vector<int> bracket_pp;
Program program;
program.push_back({OP_ADD_DATA, 0});
while (cp < code.length()) {
int jump_to;
switch (code[cp]) {
case '>':
if (program.back().op != OP_ADD_PTR) {
program.push_back({OP_ADD_PTR, 0});
}
program.back().value++;
break;
case '<':
if (program.back().op != OP_ADD_PTR) {
program.push_back({OP_ADD_PTR, 0});
}
program.back().value--;
break;
case '+':
if (program.back().op != OP_ADD_DATA) {
program.push_back({OP_ADD_DATA, 0});
}
program.back().value++;
break;
case '-':
if (program.back().op != OP_ADD_DATA) {
program.push_back({OP_ADD_DATA, 0});
}
program.back().value--;
break;
case '.':
program.push_back({OP_OUT, 1});
break;
case ',':
program.push_back({OP_READ, 1});
break;
case '[':
bracket_pp.push_back(program.size());
program.push_back({OP_JUMP, 0});
break;
case ']':
jump_to = bracket_pp.back();
bracket_pp.pop_back();
program[jump_to].value = program.size();
program.push_back({OP_JUMP_BK, jump_to});
break;
default:
break; // ignore
}
cp++;
}
return program;
}
void print_op(const Operation &o) {
cout << code_s[o.op] << " " << o.value << endl;
}
void print_program(const Program &program) {
int line = 0;
for (const auto &o : program) {
cout << line << ":";
print_op(o);
line++;
}
}
void eval(const Program &program) {
int pp = 0;
int ptr = 0;
uint8_t data[DataSize] = {};
while (pp < program.size()) {
OP_CODE op = program[pp].op;
int value = program[pp].value;
// print_op(program[pp]);
switch (op) {
case OP_ADD_DATA:
data[ptr] += value;
break;
case OP_ADD_PTR:
ptr += value;
break;
case OP_READ:
cin >> data[ptr];
break;
case OP_OUT:
cout << data[ptr];
break;
case OP_JUMP:
if (data[ptr] == 0)
pp = value;
break;
case OP_JUMP_BK:
if (data[ptr] != 0)
pp = value;
break;
}
pp++;
}
}
void eval(const string &code) {
int cp = 0;
int ptr = 0;
uint8_t data[DataSize] = {};
while (cp < code.length()) {
switch (code[cp]) {
case '>':
ptr++;
break;
case '<':
ptr--;
break;
case '+':
data[ptr]++;
break;
case '-':
data[ptr]--;
break;
case '.':
putchar(data[ptr]);
break;
case ',':
cin >> data[ptr];
break;
case '[':
if (data[ptr] == 0) {
int bracket_cnt = 0;
while (code[++cp] != ']' || bracket_cnt != 0) {
if (code[cp] == '[')
bracket_cnt++;
else if (code[cp] == ']')
bracket_cnt--;
}
}
break;
case ']':
if (data[ptr] != 0) {
int bracket_cnt = 0;
while (code[--cp] != '[' || bracket_cnt != 0) {
if (code[cp] == ']')
bracket_cnt++;
else if (code[cp] == '[')
bracket_cnt--;
}
}
break;
default:; // ignore
}
cp++;
}
}
int main(int argc, char *argv[]) {
if (argc != 2) {
cerr << "require source code" << endl;
return -1;
}
string src(argv[1]);
ifstream ifs(src);
if (ifs.fail()) {
std::cerr << src << ": Not found." << std::endl;
return -1;
}
istreambuf_iterator<char> it(ifs);
istreambuf_iterator<char> last;
string code(it, last);
Program program = parse(code);
// print_program(program);
eval(program);
// eval(code);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment