BrainFuck и C++

Всем привет.

Сегодня разберем как программировать на самом лучшем эзотерическим языке программирования, а именно BrainFuck.

[spoiler]

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


BrainFuck дословно переводится как "еб**ь мозг" =) из за названия он не очень популярен, а так его можно было бы использвать в школах, дабы преподать людям основы основ.
BrainFuck придумал Урбаном Мюллером (нем) в 2003 году. Сейчас это самый популярный эзотерический язык программирования. BrainFuck предстовляет собой только 8 команд, и этого достаточно что бы написать любую программу как и на С++, это как раз минимальный набор для языка.


Об языке


Как говорилось ранее язык имеент всего лишь 8 комманд.

> ----------------перейти к следующей ячейке

< ----------------перейти к предыдущей ячейке

+ ----------------увеличить значение в текущей ячейке на 1

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

. ----------------напечатать значение из текущей ячейки

, ----------------ввести извне значение и сохранить в текущей ячейке

[ ----------------если значение текущей ячейки нуль, перейти вперёд по
тексту программы на ячейку, следующую за соответствующей
] (с учётом вложенности)

] ----------------если значение текущей ячейки не нуль, перейти назад по тексту
программы на символ [ (с учётом вложенности)


Пример программы


Программа печатающая Hello World!
/*http://esate.ru, isaer*/


++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++
.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.
------.--------.>+.>.
Разберем ее позже


Странное место статьи


Как вы уже заметили, что статья находится в разделе C++, не странно ли, нет, так как сдесь пойдет речь именно о С++, а именно написания интерпретатора к BrainFuck. Почему? Просто в BrainFuck всего лишь 8 комманд и пишется все это очень быстро.


Начнем


Нам потребуется только ввод-вывод и чтение исходника, для этого подойдут
iostream и fstream, так что подключаем их
/*http://esate.ru, isaer*/


#include <iostream>
#include <fstream>

using namespace std;

int main(int argc, char** argv)
{
}

Теперь загрузим наш исходник
/*http://esate.ru, isaer*/

ifstream file(argv[1]);

Эти мы создадим поток с файлом в качестве параметра (programm source.bf)

Теперь объявим пару переменных, это:
массив чаров на 30000 элементов (ячейки),
адресную переменную
и переменную в которой будет лежать текущая команда

и того:

/*http://esate.ru, isaer*/

  unsigned char a[30000];
  unsigned char *b = a;
  char c;


Еще надо обнулить массив ячеек

А теперь не будем замарачиваться какими то замудренными паттернами и тд а просто через switch перебираем наши комманды, читаем первую комманду и начинаем перебирать:
/*http://esate.ru, isaer*/


file >> c;
while(!(file.eof()))
{
   switch(c)
   {
    case '>': break;
    case '<': break;
    case '+': break;
    case '-': break;
    case '.': break;
    case ',': break;
    case '[': break;
    case ']': break;
    default:  break;
   }
   file >> c;
}


переменная b будет отвечать за выполнение комманд
переменная a хранит в себе ячейки значений
переменная c хранит в себе текущую комманду
переменная file содержит поток исходника

Теперь приступим к заполнению реакций на команду

> <
Этими командами мы перемещаемся в ячейках, реализуем их
/*http://esate.ru, isaer*/

b++;
и
/*http://esate.ru, isaer*/

b--;
все очень просто, b у нас держит адрес первого элемента массива, и если прибавить еденицу то он переместится к следующиму, а если отнять еденицу то переместся к предыдущей (я не делаю проверку на выход за массив, хотя вы можете реализовать)

+ -
Эти команды изменяют значение текущей ячейки, реализуется тоже очень просто
/*http://esate.ru, isaer*/

(*b)--;
и
/*http://esate.ru, isaer*/

(*b)++;
Сначало разименовываем а потом прибавляем к текущему значению еденицу. Скобочки нужны обязательно так как приоритет у инкрементов больше чем у разименовывания.

. ,
Вывод -
/*http://esate.ru, isaer*/

cout << *c;
Ввод -
/*http://esate.ru, isaer*/

cin >> *c;
тоже все просто, разименовываем и записываем в ячейку.

[ ]
ну и наконец то циклы, тоже ничего сложного не прелставляют, как они работают можно почитать выше

Итак, начало цикла -
/*http://esate.ru, isaer*/

int n = 1;
if((*b) == 0)
   while(n != 0)
   {
    file >> c;
    if(с == ']')
       n--;
    else if(с == '[')
   n++;
   }

тут мы смотрим, если значение равно 0 то пропускаем все что находится между []
n - уровень вложения

Конец цикла-
/*http://esate.ru, isaer*/

int n = 1;
if((*b) != 0)
   while(n != 0)
   {
    int k = file.tellg();
    file.seekg(k - 2);
    file >> c;
    if(c == ']')
   n++;
    else if(c == '[')
   n--;
   }

сдесь все тоже самое, нашли закрывающуюся скобку, перемещаямся на 2 позиции назад, читаем символ, если закрывающая скобка то прибавляем вложение если открывающаяся то убавляем

Вот и все, 8 комманд, теперь компилируем и смотрим выполнение примера

исходник: http://codepaste.ru/9027/


Попишем


Итак давайте для начала разберем исходник вот этот

/*http://esate.ru, isaer*/

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.
++++++++++++++++++++++++++++++++++++++++++++++.
------------------.
+++++++++++++++++++.
---------------.
-------------------------------------------------------.
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.
+++.
----------------------------------------------------------------------
-------------------------------------.


сдесь не применяются ячейки, про них может позже
стандартная ячейка стоит 0 и все изменения применяются к ней
вначале мы прибавляем 69 и выводим на экран, это получается большое E (69)
дальше прибавляем 46 и выводим получаем s(115), потом отнимаем от 115 18 и выводим получаем a(97) и так далее и получаем на выходе Esate.ru и новоя строчка (10)
таблицу можно посмотреть тут

В примере выше, где hello world там используются ячейки, можете поизучать.


Заключение


Есть еще такой язык pbrain там все тоже самое только добавлены 3 комманды - ( ) :
() - открытие закрытие функции : - вызов функции

Ну вот и все, жду ваших интересных программ на BrainFuck =)
0       3409        15.01.2012        5

0  
16.01.2012 00:00:00
Жесткий язык!=)
Наверное пока не решусь воспользоваться), сильно сложно, лучше буду вводить команды ассемблера Нex-ами)))) так хоть мозг цел будет=))))
Супер!!!
+1 к статьи, только плиз мат убери=)
это как раз минимальный набор бля(для) языка))
0  
19.01.2012 00:00:00
0  
18.12.2012 00:00:00
как я за вами скучал)
0  
18.12.2012 00:00:00
за кем/чем?=)
0  
18.12.2012 00:00:00
Коллектив вашего сайта) Ваши уроки, советы
^