Как стать автором
Обновить

Brainfuck и почему это просто?

Время на прочтение3 мин
Количество просмотров15K

Недавно решил я попробовать написать какой-нибудь интерпретатор и сделать это на языке C, остановился на языке brainfuck, потому, что его интерпретатор довольно прост в написании.

Что такое brainfuck?

Brainfuck это язык программирования известный своим минимализмом

И правда, в нем всего 8 комманд это "+", "-", ">", "<", "[", "]", ".", ",".

Инструкция

Действие

"+"

Увеличивает значение в текущей ячейке на 1

"-"

Уменьшает значение текущей ячейки на 1

">"

Переход к следующей ячейке

"<"

Переход к предыдущей ячейке

"."

Вывод на экран содержания текущей ячейки

","

Ввод символа с клавиатуры в текущюю ячейку

"[" и "]"

Операторы goto

Написание самого интерпретатора

Чтобы интерпретатор работал надо подключить определённые библиотеки

  • stdio для printf, fopen

  • stdlib для exit

  • string для memset

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

Дальше надо инициализировать массив памяти и определить инструкции:

char stack[30000]; //массив памяти 
int indexx = 0; // индекс текущей ячейки
char * plus = "+";
char * minus = "-";
char * next = ">";
char * back = "<";
char * prt = ".";
char * inp = ",";
char * lp = "[";
char * llp = "]";
int rc = 0;
char * endl = "\n";
char * ex = "@";

Значек "@" будет использоваться как выход из программы

Следующий шаг это создать метод main и в его теле инициализировать массив

memset(stack, 0, 30000);

Далее проверку на кол-во аргументов командной строки

if (argc < 2) {
  bf_shell();
  exit(0);
} 

Выходит если аргумент 1, то запускается brainfuck shell - ещё одна фича моего интерпретатора

Код brainfuck shell:

int bf_shell()
{
  printf("Startimg BrainFuck Shell...\n");
	char command[4096];
	int i = 1;
	do {
		printf("BF> ");
		gets(command);
		for (int x = 0; x < sizeof(command); x++) {
			if (command[x] == *plus) {
				stack[indexx]++;
			} else if (command[x] == *minus) {
				stack[indexx]--;
			} else if (command[x] == *next) {
				indexx++;
			} else if (command[x] == *back) {
				indexx--;
			} else if (command[x] == *prt) {
				putchar(stack[indexx]);
			} else if (command[x] == *inp) {
				char t[2];
				gets(t);
				stack[indexx] = (int)t[0];
			}else if (command[x] == *endl) {
				i = 1;
			} else if (command[x] == *ex) {
				i = 0;
			} else if (command[x] == *lp) {
				if (!stack[indexx]) {
					rc++;
					while (rc) {
						i++;
						if (command[x] == *lp) {
							rc++;
						}
						if (command[x] == *llp) {
							rc--;
						}
					}
				} else continue;
			} else if (command[x] == *llp) {
				if (!stack[indexx]) {
					continue;
				} else {
					if (command[x] == *llp) {
						rc++;
						while (rc) {
							x--;
							if (command[x] == *lp) {
								rc--;
							}
							if(command[x] == *llp) {
								rc++;
							}
						}
						x--;
					}
				}
			} else {
				continue;
			}
		}
	} while (i);
	return 0;
} 

Дальше идёт тело метода main где интерпретатор интерпретирует символы из файла

FILE * file = fopen(argv[1], "r");
if (file == NULL) {
	printf("Cann't open file %s!\n", argv[1]);
	exit(1);
}
fseek(file, 0L, SEEK_END);
long size = ftell(file);
fseek(file, 0L, SEEK_SET);
char buf[size];
fread(buf, sizeof(buf), 1, file);

И сам цикл интерпретации

for (int i = 0; i < sizeof(buf); i++) {
		if (buf[i] == *plus){
			stack[indexx]++;
		} else if (buf[i] == *minus) {
			stack[indexx]--;
		} else if (buf[i] == *next) {
			indexx++;
		} else if (buf[i] == *back) {
			indexx--;
		} else if (buf[i] == *prt) {
			putchar(stack[indexx]);
		} else if (buf[i] == *inp) {
			char c;
			scanf("%c", &c);
			stack[indexx] = (int)c;
		} else if (buf[i] == *lp) {
			if (!stack[indexx]) {
				rc++;
				while (rc) {
					i++;
					if (buf[i] == *lp) {
						rc++;
					}
					if (buf[i] == *llp) {
						rc--;
					} 
				}
			} else continue;
		} else if (buf[i] == *llp) {
			if(!stack[indexx]) {
				continue;
			} else {
				if (buf[i] == *llp) {
					rc++;
					while (rc) {
						i--;
						if (buf[i] == *lp) {
							rc--;
						}
						if (buf[i] == *llp) {
							rc++;
						}
					}
					i--;
				}
			}
		} else if (buf[i] == *ex) {
			return 0;
		}
}

Исходник доступен на моем гитхабе

Учтите, что в исходниках все написано в теле метода main.

Теги:
Хабы:
Всего голосов 14: ↑2 и ↓12-9
Комментарии28

Публикации

Истории

Работа

Программист С
56 вакансий

Ближайшие события

27 августа – 7 октября
Премия digital-кейсов «Проксима»
МоскваОнлайн
28 сентября – 5 октября
О! Хакатон
Онлайн
3 – 18 октября
Kokoc Hackathon 2024
Онлайн
10 – 11 октября
HR IT & Team Lead конференция «Битва за IT-таланты»
МоскваОнлайн
25 октября
Конференция по росту продуктов EGC’24
МоскваОнлайн
7 – 8 ноября
Конференция byteoilgas_conf 2024
МоскваОнлайн