Skip to content

Instantly share code, notes, and snippets.

@Friedjof
Last active May 7, 2023 22:08
Show Gist options
  • Save Friedjof/f9e034598edafac04faf1bc5da3d6bd0 to your computer and use it in GitHub Desktop.
Save Friedjof/f9e034598edafac04faf1bc5da3d6bd0 to your computer and use it in GitHub Desktop.
This is an interpreter for Brainfuck written in C.
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define PROGRAM_SIZE 8192
#define LOOP_DEPTH 256
// Interpreter state
struct BFState
{
// The array and the size of the array.
size_t array_len;
uint8_t *array;
// Pointer to the current position, points into array..array+array_len.
uint8_t *cur;
};
int brainfuck(struct BFState* state, const char* program) {
char *p = (char*)program;
char *loop_start[LOOP_DEPTH] = {0}; // Stack for loop start positions
int lp = 0; // Loop pointer
while (*p) {
switch (*p) {
case '>': // Move the data pointer to the right
++state->cur;
if (state->cur >= state->array + state->array_len) {
return -1; // Out of bounds
}
break;
case '<': // Move the data pointer to the left
--state->cur;
if (state->cur < state->array) {
return -1; // Out of bounds
}
break;
case '+': // Increment the value at the data pointer
++(*state->cur);
break;
case '-': // Decrement the value at the data pointer
--(*state->cur);
break;
case '.': // Output the value at the data pointer (ignored for testing purposes)
break;
case ',': // Input a value and store it at the data pointer (ignored for testing purposes)
break;
case '[': // Jump forward to the matching ] if the value at the data pointer is zero
if (*state->cur == 0) {
// Find the matching ]
int depth = 1;
while (depth > 0 && *++p) {
if (*p == '[') {
++depth;
} else if (*p == ']') {
--depth;
}
}
if (depth > 0) {
return -1; // Unterminated loop
}
} else {
// Push the current position onto the loop start stack
if (lp >= LOOP_DEPTH) {
return -1; // Loop depth too large
}
loop_start[lp++] = p;
}
break;
case ']': // Jump back to the matching [ if the value at the data pointer is nonzero
if (*state->cur != 0) {
// Pop the loop start position from the stack
if (lp <= 0) {
return -1; // Unmatched loop
}
p = loop_start[lp - 1];
} else {
--lp;
}
break;
default:
break;
}
if (++p - (char*)program > PROGRAM_SIZE) {
return -1; // Program too long
}
}
return 0;
}
int main(int argc, char *argv[])
{
const char *program = "++><[->[->+>+<<]>>[-<<+>>]<<<]";
// Initialize the BFState struct
struct BFState state;
state.array_len = 4;
state.array = calloc(state.array_len, sizeof(uint8_t));
memcpy(state.array, "\x00\x00\x00\x00", state.array_len);
state.cur = state.array;
// Call the brain_fuck function
int result = brainfuck(&state, program);
// Check for errors and print the data array
if (result == 0)
{
for (size_t i = 0; i < state.array_len; i++)
{
printf("%d ", state.array[i]);
}
printf("\n");
}
else
{
printf("Brainfuck error: %d\n", result);
}
// Free the memory used by the data array
free(state.array);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment