2th/AuthorImplementation.c
Jump to navigation
Jump to search
// Easy implementation of a 2th interpreter. #include <stdio.h> #include <stdlib.h> #define NUM_CELLS 10000 int isDigit(char x) { return '0' <= x && x <= '9'; } // Function for finding bracket matches. // I know this is a slow approach to use a while loop to find the matching bracket... // (It is preferred to prepare a match table before hand) int matchJump(int i, const char *program, size_t programLength, int dir) { dir = (dir > 0)? 1 : -1; // direction to search in int level = -dir; int i0 = i; // saving original value of i for error message while (level != 0 && 0 < i && i < programLength) { i += dir; switch (program[i]) { case '[': level--; break; case ']': level++; break; } } if (level == 0) { return i; } else { printf("SYNTAX ERROR: unmatched opening bracket '[' at index %d", i0); return -1; } } // Interprets your 2th program string. void interpret2thProgram(const char *program, size_t programLength) { char tape[NUM_CELLS] = { 0 }; // data tape char r = 0; // the register size_t t = 0; // data pointer index size_t i = 0; // instruction pointer index size_t m = 0; // mode flag for if we are in register mode size_t n = 1; // multiplier for run-length encoding size_t resetN; // extra flag for whether to reset n to 1 (removes redundancy from the switch cases) while (i < programLength) { resetN = 1; switch(program[i]) { case '+': // Increment if (m) { r += n; } else { tape[t] += n; } i++; break; case '-': // Decrement if (m) { r -= n; } else { tape[t] -= n; } i++; break; case '<': // Move left t -= n; if (t < 0) { t = 0; } i++; break; case '>': // Move right t += n; if (t >= NUM_CELLS) { t = NUM_CELLS - 1; } i++; break; case '%': // enter cell mode m = 1; i++; break; case '^': // enter register mode m = 0; i++; break; case '[': // Jump past matching bracket if current cell/R is 0 (depending on mode) if ((m && r == 0) || (!m && tape[t] == 0)) { i = matchJump(i, program, programLength, 1); if (i < 0) exit(1); } i++; break; case ']': // Jump back to the matching bracket if current cell/R is not 0 (depending on mode) if ((m && r != 0) || (!m && tape[t] != 0)) { i = matchJump(i, program, programLength, -1); if (i < 0) exit(1); } i++; break; case '?': // Get a character of input if (m) { r = getchar(); } else { tape[t] = getchar(); } i++; break; case '.': // Set a character of output if (m) { putchar(r); } else { putchar(tape[t]); } i++; break; default: if (isDigit(program[i])) { // Read a number for the (run length encoding) multiplier, n n = 0; while (isDigit(program[i])) { n = (n * 10) + (program[i] - '0'); i++; } // This combines making sure that (n != 0) and that we do not reset n if it is valid: resetN = (n == 0); } else { // Ignore other characters i++; } break; } // this happens unless a number (digits) was read: if (resetN) { n = 1; } } } int main(int argc, char **argv) { if (argc != 2) { printf("%s: error: expected exactly 1 argument, the program string\n", argv[0]); exit(1); } interpret2thProgram(argv[1], strlen(argv[1])); }