Skip to content

Commit 762b131

Browse files
authored
Add files via upload
1 parent e471631 commit 762b131

File tree

11 files changed

+365
-0
lines changed

11 files changed

+365
-0
lines changed

CMakeLists.txt

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
cmake_minimum_required(VERSION 3.30)
2+
project(brainfuck C)
3+
4+
set(CMAKE_C_STANDARD 11)
5+
6+
include_directories(.)
7+
8+
add_executable(brainfuck
9+
src/common.h
10+
src/error.c
11+
src/error.h
12+
src/interpreter.c
13+
src/interpreter.h
14+
src/main.c
15+
src/memory.c
16+
src/memory.h
17+
src/program.c
18+
src/program.h
19+
)

src/common.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#ifndef COMMON_H
2+
#define COMMON_H
3+
4+
#define MEMORY_SIZE 30000
5+
#define MAX_PROGRAM_SIZE 65536
6+
7+
typedef struct position_t {
8+
int line;
9+
int column;
10+
} Position;
11+
12+
#endif

src/error.c

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#include "error.h"
2+
3+
#include <stdio.h>
4+
5+
void error_syntax(const char* message, const Position *pos) {
6+
if (pos == NULL) {
7+
fprintf(stderr, "Syntax Error: %s\n", message);
8+
return;
9+
}
10+
fprintf(stderr, "Syntax Error: %s at line %d, column %d\n",
11+
message, pos->line, pos->column);
12+
}
13+
14+
void error_runtime(const char* message, const Position *pos) {
15+
if (pos == NULL) {
16+
fprintf(stderr, "Runtime Error: %s\n", message);
17+
return;
18+
}
19+
fprintf(stderr, "Runtime Error: %s at line %d, column %d\n",
20+
message, pos->line, pos->column);
21+
}

src/error.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#ifndef ERROR_H
2+
#define ERROR_H
3+
4+
#include "common.h"
5+
6+
void error_syntax(const char* message, const Position *pos);
7+
void error_runtime(const char* message, const Position *pos);
8+
9+
#endif

src/interpreter.c

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
#include "interpreter.h"
2+
#include "error.h"
3+
4+
#include <stdbool.h>
5+
#include <stdio.h>
6+
#include <stdlib.h>
7+
8+
Interpreter* interpreter_create(void) {
9+
Interpreter* interpreter = malloc(sizeof(Interpreter));
10+
if (!interpreter) return NULL;
11+
12+
interpreter->memory = memory_create(MEMORY_SIZE);
13+
interpreter->program = program_create();
14+
15+
if (!interpreter->memory || !interpreter->program) {
16+
interpreter_destroy(interpreter);
17+
return NULL;
18+
}
19+
20+
return interpreter;
21+
}
22+
23+
void interpreter_destroy(Interpreter* interpreter) {
24+
if (interpreter) {
25+
memory_destroy(interpreter->memory);
26+
program_destroy(interpreter->program);
27+
free(interpreter);
28+
}
29+
}
30+
31+
bool interpreter_execute(const Interpreter* interpreter) {
32+
Program* prog = interpreter->program;
33+
Memory* mem = interpreter->memory;
34+
int bracket_count;
35+
36+
// this loop be cleaned up by using computed gotos
37+
while (prog->pc < prog->size) {
38+
const Token current = prog->instructions[prog->pc];
39+
40+
switch (current.instruction) {
41+
case '>':
42+
if (!memory_bounds_check(mem, mem->pointer + 1)) {
43+
error_runtime("Memory pointer out of bounds", &current.pos);
44+
return false;
45+
}
46+
mem->pointer++;
47+
break;
48+
49+
case '<':
50+
if (!memory_bounds_check(mem, mem->pointer - 1)) {
51+
error_runtime("Memory pointer out of bounds", &current.pos);
52+
return false;
53+
}
54+
mem->pointer--;
55+
break;
56+
57+
case '+':
58+
mem->cells[mem->pointer]++;
59+
break;
60+
61+
case '-':
62+
mem->cells[mem->pointer]--;
63+
break;
64+
65+
case '.':
66+
putchar(mem->cells[mem->pointer]);
67+
break;
68+
69+
case ',':
70+
mem->cells[mem->pointer] = getchar();
71+
break;
72+
73+
case '[':
74+
if (mem->cells[mem->pointer] == 0) {
75+
bracket_count = 1;
76+
while (bracket_count > 0) {
77+
prog->pc++;
78+
if (prog->instructions[prog->pc].instruction == '[') bracket_count++;
79+
if (prog->instructions[prog->pc].instruction == ']') bracket_count--;
80+
}
81+
}
82+
break;
83+
84+
case ']':
85+
if (mem->cells[mem->pointer] != 0) {
86+
bracket_count = 1;
87+
while (bracket_count > 0) {
88+
prog->pc--;
89+
if (prog->instructions[prog->pc].instruction == '[') bracket_count--;
90+
if (prog->instructions[prog->pc].instruction == ']') bracket_count++;
91+
}
92+
}
93+
break;
94+
default: break;
95+
}
96+
prog->pc++;
97+
}
98+
return true;
99+
}

src/interpreter.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#ifndef INTERPRETER_H
2+
#define INTERPRETER_H
3+
4+
#include "memory.h"
5+
#include "program.h"
6+
7+
#include <stdbool.h>
8+
9+
typedef struct interpreter_t {
10+
Memory* memory;
11+
Program* program;
12+
} Interpreter;
13+
14+
Interpreter* interpreter_create(void);
15+
void interpreter_destroy(Interpreter* interpreter);
16+
bool interpreter_execute(const Interpreter* interpreter);
17+
18+
#endif

src/main.c

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#include <stdio.h>
2+
3+
#include "interpreter.h"
4+
5+
int main(int argc, char* argv[]) {
6+
if (argc != 2) {
7+
fprintf(stderr, "Usage: %s <filename.bf>\n", argv[0]);
8+
return 1;
9+
}
10+
11+
Interpreter* interpreter = interpreter_create();
12+
if (!interpreter) {
13+
fprintf(stderr, "Failed to initialize interpreter\n");
14+
return 1;
15+
}
16+
17+
if (!program_load(interpreter->program, argv[1])) {
18+
interpreter_destroy(interpreter);
19+
return 1;
20+
}
21+
22+
bool success = interpreter_execute(interpreter);
23+
interpreter_destroy(interpreter);
24+
25+
return success ? 0 : 1;
26+
}

src/memory.c

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#include "memory.h"
2+
3+
#include <stdbool.h>
4+
#include <stdlib.h>
5+
6+
Memory* memory_create(const size_t size) {
7+
Memory* mem = malloc(sizeof(Memory));
8+
if (!mem) return NULL;
9+
10+
mem->cells = calloc(size, sizeof(char));
11+
if (!mem->cells) {
12+
free(mem);
13+
return NULL;
14+
}
15+
16+
mem->size = size;
17+
mem->pointer = 0;
18+
return mem;
19+
}
20+
21+
void memory_destroy(Memory* mem) {
22+
if (mem) {
23+
free(mem->cells);
24+
free(mem);
25+
}
26+
}
27+
28+
bool memory_bounds_check(const Memory* mem, const int pointer) {
29+
return pointer >= 0 && pointer < mem->size;
30+
}

src/memory.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#ifndef MEMORY_H
2+
#define MEMORY_H
3+
4+
#include <stdbool.h>
5+
#include <stddef.h>
6+
7+
typedef struct memory_t {
8+
char* cells;
9+
size_t size;
10+
int pointer;
11+
} Memory;
12+
13+
Memory* memory_create(size_t size);
14+
void memory_destroy(Memory* mem);
15+
bool memory_bounds_check(const Memory* mem, int pointer);
16+
17+
#endif

src/program.c

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
#include "program.h"
2+
3+
#include "error.h"
4+
5+
#include <stdbool.h>
6+
#include <stdio.h>
7+
#include <stdlib.h>
8+
#include <string.h>
9+
10+
static bool has_bf_extension(const char* filename) {
11+
const char* dot = strrchr(filename, '.');
12+
return dot && strcmp(dot, ".bf") == 0;
13+
}
14+
15+
Program* program_create(void) {
16+
Program* prog = malloc(sizeof(Program));
17+
if (!prog) return NULL;
18+
19+
prog->instructions = malloc(MAX_PROGRAM_SIZE * sizeof(Token));
20+
if (!prog->instructions) {
21+
free(prog);
22+
return NULL;
23+
}
24+
25+
prog->size = 0;
26+
prog->pc = 0;
27+
return prog;
28+
}
29+
30+
void program_destroy(Program* prog) {
31+
if (prog) {
32+
free(prog->instructions);
33+
free(prog);
34+
}
35+
}
36+
37+
bool program_load(Program* prog, const char* filename) {
38+
FILE* file = fopen(filename, "r");
39+
if (!file) {
40+
error_runtime("Cannot open file", NULL);
41+
return false;
42+
}
43+
44+
if (!has_bf_extension(filename)) {
45+
error_runtime("File must have .bf extension", NULL);
46+
return false;
47+
}
48+
49+
int c;
50+
int line = 1, column = 0;
51+
int bracket_balance = 0;
52+
53+
while ((c = fgetc(file)) != EOF && prog->size < MAX_PROGRAM_SIZE) {
54+
column++;
55+
56+
if (c == '\n') {
57+
line++;
58+
column = 0;
59+
continue;
60+
}
61+
62+
if (strchr("><+-.,[]", c)) {
63+
const Token token = {
64+
.instruction = c,
65+
.pos = (Position){line, column}
66+
};
67+
68+
if (c == '[') bracket_balance++;
69+
if (c == ']') {
70+
bracket_balance--;
71+
if (bracket_balance < 0) {
72+
error_syntax("Unmatched ']'", &token.pos);
73+
fclose(file);
74+
return false;
75+
}
76+
}
77+
78+
prog->instructions[prog->size++] = token;
79+
}
80+
}
81+
82+
if (bracket_balance > 0) {
83+
error_syntax("Unmatched '['", &(Position){line, column});
84+
fclose(file);
85+
return false;
86+
}
87+
88+
fclose(file);
89+
return true;
90+
}

src/program.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#ifndef PROGRAM_H
2+
#define PROGRAM_H
3+
4+
#include "common.h"
5+
6+
#include <stdbool.h>
7+
#include <stddef.h>
8+
9+
typedef struct token_t {
10+
char instruction;
11+
Position pos;
12+
} Token;
13+
14+
typedef struct program_t {
15+
Token* instructions;
16+
size_t size;
17+
int pc;
18+
} Program;
19+
20+
Program* program_create(void);
21+
void program_destroy(Program* prog);
22+
bool program_load(Program* prog, const char* filename);
23+
24+
#endif

0 commit comments

Comments
 (0)