-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathbf_interpreter.cpp
102 lines (93 loc) · 2.55 KB
/
bf_interpreter.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
// Copyright 2014 Brian Quinlan
// See "LICENSE" file for details.
#include <cstdint>
#include <stack>
#include "bf_interpreter.h"
using std::stack;
BrainfuckInterpreter::BrainfuckInterpreter() {}
bool BrainfuckInterpreter::init(string::const_iterator start,
string::const_iterator end) {
start_ = start;
end_ = end;
// Build the mapping from the position of the start of a block (i.e. "]") to
// the character *after* the end of the block.
stack<string::const_iterator> block_starts;
for (string::const_iterator it = start; it != end; ++it) {
if (*it == '[') {
block_starts.push(it);
} else if (*it == ']') {
if (block_starts.size() != 0) {
const string::const_iterator &loop_start = block_starts.top();
loop_start_to_after_end_[loop_start] = it+1;
block_starts.pop();
}
}
}
if (block_starts.size() != 0) {
fprintf(
stderr,
"Unable to find loop end in block starting with: %s\n",
string(block_starts.top(), end).c_str());
return false;
}
return true;
}
void* BrainfuckInterpreter::run(BrainfuckReader reader,
void* reader_arg,
BrainfuckWriter writer,
void* writer_arg,
void* memory) {
uint8_t* byte_memory = reinterpret_cast<uint8_t *>(memory);
// When processing a "[", push the position of that command onto a stack so
// that we can quickly return to the start of the block when then "]" is
// interpreted.
stack<string::const_iterator> return_stack;
for (string::const_iterator it = start_; it != end_;) {
switch (*it) {
case '<':
--byte_memory;
++it;
break;
case '>':
++byte_memory;
++it;
break;
case '-':
*byte_memory -= 1;
++it;
break;
case '+':
*byte_memory += 1;
++it;
break;
case ',':
*byte_memory = reader(reader_arg);
++it;
break;
case '.':
writer(writer_arg, *byte_memory);
++it;
break;
case '[':
if (*byte_memory) {
return_stack.push(it);
++it;
} else {
it = loop_start_to_after_end_[it];
}
break;
case ']':
if (return_stack.size() != 0) {
it = return_stack.top();
return_stack.pop();
} else {
++it;
}
break;
default:
++it;
break;
}
}
return byte_memory;
}