blob: 28d4c18962225f1c315d176f0fb831ad91a273fa (
plain) (
blame)
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
103
104
105
106
107
108
109
110
111
112
113
114
|
#include "bf_interpreter.h"
#include <cmath>
#include <cstring>
#include <iostream>
#include <stack>
#ifndef MEMSIZE
#define MEMSIZE 30000
#endif
BFInterpreter::BFInterpreter(const char *program, std::istream &input, std::ostream &output) :
memory_blocks(nullptr), p(nullptr),
program(nullptr), input(input), output(output),
memory_size(MEMSIZE) {
this->program = new char[strlen(program) + 1];
strncpy(this->program, program, strlen(program) + 1);
pp = this->program;
memory_blocks = new uchar[memory_size];
for (int i = 0; i < memory_size; ++i) {
memory_blocks[i] = 0;
}
p = memory_blocks;
}
BFInterpreter::~BFInterpreter() {
delete [] memory_blocks;
delete [] program;
}
void BFInterpreter::addMemory() {
uchar *new_memory = new uchar[memory_size + ((size_t) log2(memory_size))];
for (int i = 0; i < memory_size; ++i) {
new_memory[i] = memory_blocks[i];
}
delete [] memory_blocks;
memory_blocks = new_memory;
memory_size += log2(memory_size);
}
void BFInterpreter::compile() {
while (*pp) {
switch (*pp) {
case '[':
++pp;
loop();
break;
case ']': // that will only happen if code is wrong
printf("Syntax error!\n");
return;
default:
proccessNonLoopCmd(*pp);
}
++pp;
}
output.put('\n');
}
void BFInterpreter::loop() {
std::stack<char*> loops;
loops.push(pp);
char *body = loops.top();
while (!loops.empty()) {
while (*body != ']' && *body != '[') {
proccessNonLoopCmd(*body);
++body;
}
if (*body == ']') {
if (!*p) { /* End of a loop */
loops.pop();
++body;
} else { /* Loop has not ended. Return to the beginning of the current loop */
body = loops.top();
}
} else { /* Start of a new loop */
loops.push(body + 1);
++body;
}
}
pp = --body;
return;
}
void BFInterpreter::proccessNonLoopCmd(char c) {
switch (c) {
case '+':
++*p;
break;
case '-':
--*p;
break;
case '.':
output.put(*p);
break;
case ',':
*p = input.get();
break;
case '<':
if (p == memory_blocks)
p = memory_blocks + (memory_size - 1);
else
--p;
break;
case '>':
if (p == memory_blocks + (memory_size - 1))
p = memory_blocks;
else
++p;
break;
}
}
|