Skip to content

Instantly share code, notes, and snippets.

@taiypeo
Last active August 29, 2015 14:27
Show Gist options
  • Save taiypeo/434ddbf27fa44875d6c6 to your computer and use it in GitHub Desktop.
Save taiypeo/434ddbf27fa44875d6c6 to your computer and use it in GitHub Desktop.
A Brainfuck interpreter written in C
#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