Website Summary Files Commits Branches @commit @diff @stats
path: root / homework / 81568 / BF_Interpreter / bf_interpreter.cpp
diff options
context:
space:
mode:
1 files changed, 114 insertions, 0 deletions
-rw-r--r--homework/81568/BF_Interpreter/bf_interpreter.cpp114
diff --git a/homework/81568/BF_Interpreter/bf_interpreter.cpp b/homework/81568/BF_Interpreter/bf_interpreter.cpp
new file mode 100644
index 0000000..28d4c18
--- /dev/null
+++ b/homework/81568/BF_Interpreter/bf_interpreter.cpp
@@ -0,0 +1,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;
+ }
+}