Last active
May 7, 2023 22:08
-
-
Save Friedjof/f9e034598edafac04faf1bc5da3d6bd0 to your computer and use it in GitHub Desktop.
This is an interpreter for Brainfuck written in C.
This file contains hidden or 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 <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