Last active
August 29, 2015 14:27
-
-
Save taiypeo/434ddbf27fa44875d6c6 to your computer and use it in GitHub Desktop.
A Brainfuck interpreter written in C
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <string.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <limits.h> | |
#define STACK_MAX 100 | |
#define TAPE_MAX 30000 | |
#define ECHO_MESSAGES 1 | |
enum MESSAGE | |
{ | |
TOO_BIG, TOO_SMALL, OUT_OF_BOUNDS, STACK_OVERFLOW, TOO_MANY_LOOPS_CLOSED, NOT_ENOUGH_LOOPS_CLOSED, UNKNOWN_SYMBOL | |
}; | |
typedef enum MESSAGE MESSAGE; | |
void interpret(unsigned char* program); | |
void message(MESSAGE message, unsigned int symbol); | |
int main() | |
{ | |
unsigned char *program = malloc(0), *temp; | |
char c; | |
unsigned int i; | |
for(i = 0;;i++) | |
{ | |
c = getchar(); | |
if(c == '\n') | |
break; | |
program[i] = c; | |
temp = realloc(program, (i+1)*sizeof(unsigned char*)); | |
program = temp; | |
} | |
interpret(program); | |
free(program); | |
return 0; | |
} | |
void interpret(unsigned char* program) | |
{ | |
unsigned char tape[TAPE_MAX] = {0}, stack[STACK_MAX]; | |
unsigned char* ptr = tape; | |
int stackTop = -1; | |
unsigned int i; | |
for(i = 0; i < strlen(program); i++) | |
{ | |
switch(program[i]) | |
{ | |
case '+': | |
if(*ptr < UCHAR_MAX) | |
++*ptr; | |
else | |
{ | |
message(TOO_BIG, i+1); | |
return; | |
} | |
break; | |
case '-': | |
if(*ptr > 0) | |
--*ptr; | |
else | |
{ | |
message(TOO_SMALL, i+1); | |
return; | |
} | |
break; | |
case '>': | |
if(ptr-tape < TAPE_MAX-1) | |
++ptr; | |
else | |
{ | |
message(OUT_OF_BOUNDS, i+1); | |
return; | |
} | |
break; | |
case '<': | |
if(ptr > tape) | |
--ptr; | |
else | |
{ | |
message(OUT_OF_BOUNDS, i+1); | |
return; | |
} | |
break; | |
case '.': | |
putchar(*ptr); | |
putchar('\n'); | |
break; | |
case ',': | |
*ptr = getchar(); | |
break; | |
case '[': | |
if(stackTop < STACK_MAX-1) | |
stack[++stackTop] = i; | |
else | |
{ | |
message(STACK_OVERFLOW, i+1); | |
return; | |
} | |
break; | |
case ']': | |
if(stackTop > -1) | |
if(*ptr) | |
i = stack[stackTop]; | |
else | |
stack[stackTop--] = 0; | |
else | |
{ | |
message(TOO_MANY_LOOPS_CLOSED, i+1); | |
return; | |
} | |
break; | |
default: | |
message(UNKNOWN_SYMBOL, i+1); | |
} | |
} | |
if(stackTop != -1) | |
message(NOT_ENOUGH_LOOPS_CLOSED, i); | |
} | |
void message(MESSAGE message, unsigned int symbol) | |
{ | |
if(ECHO_MESSAGES) | |
switch(message) | |
{ | |
case TOO_BIG: | |
printf("%s%d%s%d\n","ERROR: Cells cannot contain values above ", UCHAR_MAX, ". SYMBOL #", symbol); | |
break; | |
case TOO_SMALL: | |
printf("%s%d\n","ERROR: Cells cannot contain values below zero. SYMBOL #", symbol); | |
break; | |
case OUT_OF_BOUNDS: | |
printf("%s%d\n","ERROR: Out of bounds. SYMBOL #", symbol); | |
break; | |
case STACK_OVERFLOW: | |
printf("%s%d\n","ERROR: Stack overflow. SYMBOL #", symbol); | |
break; | |
case TOO_MANY_LOOPS_CLOSED: | |
printf("%s%d\n","ERROR: Too many closing brackets. SYMBOL #", symbol); | |
break; | |
case NOT_ENOUGH_LOOPS_CLOSED: | |
printf("%s%d\n","ERROR: Not all loops are closed. SYMBOL #", symbol); | |
break; | |
case UNKNOWN_SYMBOL: | |
printf("%s%d\n", "WARNING: Unknown symbol. SYMBOL #", symbol); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment