首页 > 代码库 > Brainfuck 编程语言

Brainfuck 编程语言

很偶然的机会认识到这个语言,当时在纸上对着它的 "hello world" 程序一个字符一个字符的解释了一遍,惊讶于它的设计思想。到网上查了下,记录下来。

以下是正文 :

-------------------------------- 

Brainfuck,是一种极小化的计算机语言,它是由Urban Müller在1993年创建的。由于fuck在英语中是脏话,这种语言有时被称为brainf*ck或brainf***,甚至被简称为BF。 

Müller的目标是创建一种简单的、可以用最小的编译器来实现的、符合图灵完全思想的编程语言。这种语言由八种运算符构成,为Amiga机器编写的编译器(第二版)只有240个字节大小。 

就象它的名字所暗示的,brainfuck程序很难读懂。尽管如此,brainfuck图灵机一样可以完成任何计算任务。虽然brainfuck的计算方式如此与众不同,但它确实能够正确运行。 

这种语言基于一个简单的机器模型,除了指令,这个机器还包括:一个以字节为单位、被初始化为零的数组、一个指向该数组的指针(初始时指向数组的第一个字节)、以及用于输入输出的两个字节流。 

下面是这八种状态的描述,其中每个状态由一个字符标识: 
字符 含义 
>    指针加一 
<    指针减一 
+    指针指向的字节的值加一 
-     指针指向的字节的值减一 
.     输出指针指向的单元内容(ASCII码) 
,     输入内容到指针指向的单元(ASCII码) 
[     如果指针指向的单元值为零,向后跳转到对应的]指令的次一指令处 
]     如果指针指向的单元值不为零,向前跳转到对应的[指令的次一指令处 

(按照更节省时间的简单说法,]也可以说成“向前跳转到对应的[状态”。这两解释是一样的。) 

(第三种同价的说法,[意思是"向后跳转到对应的]",]意思是"向前跳转到对应的[指令的次一指令处,如果指针指向的字节非零。") 

Brainfuck程序可以用下面的替换方法翻译成C语言(假设ptr是char*类型): 
Brainfuck C 
>    ++ptr; 
<    --ptr; 
+    ++*ptr; 
-     --*ptr; 
.     putchar(*ptr); 
,     *ptr =getchar(); 
[     while (*ptr) { 
]     } 

(以上内容源自维基百科:http://zh.wikipedia.org/wiki/Brainfuck)


下面是它的一个解释器: 
-------------------------------- 

#include <stdio.h>
int p, r, q;
char a[5000], f[5000], b, o, *s=f;
void interpret(char *c)
{
    char *d;
    r++;
    while( *c ) {
        //if(strchr("<>;+-,.[]\n",*c))printf("%c",*c);
        switch(o=1,*c++) {
            case ‘<‘: p--; break;
            case ‘>‘: p++; break;
            case ‘+‘: a[p]++; break;
            case ‘-‘: a[p]--; break;
            case ‘.‘: putchar(a[p]); fflush(stdout); break;
            case ‘,‘: a[p]=getchar();fflush(stdout); break;
            case ‘[‘:
                for( b=1,d=c; b && *c; c++ )
                b+=*c==‘[‘, b-=*c==‘]‘;
                if(!b) {
                    c[-1]=0;
                    while( a[p] )
                    interpret(d);
                    c[-1]=‘]‘;
                    break;
                }
            case ‘]‘:
                puts("UNBALANCED BRACKETS"), exit(0);
            case ‘#‘:
                if(q>2)
                printf("%2d %2d %2d %2d %2d %2d %2d %2d %2d %2d\n%*s\n",
                *a,a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8],a[9],3*p+2,"^");
                break;
            default: o=0;
        }
        if( p<0 || p>100)
            puts("RANGE ERROR"), exit(0);
    }
    r--;
    // chkabort();
}
 
main(int argc,char *argv[])
{
    FILE *z;
 
    q=argc;
 
    if(z=fopen(argv[1],"r")) {
        while( (b=getc(z))>0 )
            *s++=b;
        *s=0;
        interpret(f);
    }
}

-------------------------------- 
代码比较直接,不做解释了。


一个 BF 的 hello world ( 注意,这里成行的减号是起分割线作用的,不是 BF 代码。)
-------------------------------- 
++++++++++[>+++++++>++++++++++>+++>+<<<<-] 
>++.>+.+++++++..+++.>++.<<+++++++++++++++. 
>.+++.------.--------.>+.>. 
-------------------------------- 

解释 
-------------------------------- 
+++ +++ +++ +                    initialize counter (cell #0) to 10 
[                                               use loop to set the next four cells to 70/100/30/10 
> +++ +++ +                         add 7 to cell #1 
> +++ +++ +++ +                add 10 to cell #2 
> +++                                    add 3 to cell #3 
> +                                         add 1 to cell #4 
<<< < -                                 decrement counter (cell #0) 

>++ .                                     print ‘H‘ 
>+.                                         print ‘e‘ 
+++ +++ +.                          print ‘l‘ 
.                                             print ‘l‘ 
+++ .                                     print ‘o‘ 
>++ .                                     print ‘ ‘ 
<<+ +++ +++ +++ +++ ++.  print ‘W‘ 
>.                                               print ‘o‘ 
+++ .                                         print ‘r‘ 
--- --- .                                       print ‘l‘ 
--- --- --.                                    print ‘d‘ 
>+.                                             print ‘!‘ 
>.                                               print ‘\n‘ 
-------------------------------- 

(以上内容来自 coolshell : http://coolshell.cn/articles/1142.html,作者: 陈皓)


在网上又查到了一个代码写得很好的解释器,代码如下: 
-------------------------------- 

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#define TOKENS "><+-.,[]"
#define CODE_SEGMENT_SIZE 30000
#define STACK_SEGMENT_SIZE 1000
#define DATA_SEGMENT_SIZE 30000
typedef void (*Callback)(void);
struct {
  char cs[CODE_SEGMENT_SIZE]; /* Code Segment */
  long ip; /* Instruction Pointer */
 
  char ss[STACK_SEGMENT_SIZE]; /* Stack Segment */
  long sp; /* Stack Pointer */
 
  char ds[DATA_SEGMENT_SIZE]; /* Data Segment */
  long bp; /* Base Pointer */
 
  Callback fn[128];
} vm;
void vm_forward() {
  vm.bp = (vm.bp + 1) % DATA_SEGMENT_SIZE;
}
void vm_backward() {
  vm.bp = (vm.bp + DATA_SEGMENT_SIZE - 1) % DATA_SEGMENT_SIZE;
}
void vm_increment() {
  vm.ds[vm.bp]++;
}
void vm_decrement() {
  vm.ds[vm.bp]--;
}
void vm_input() {
  vm.ds[vm.bp] = getchar();
}
 
void vm_output() {
  putchar(vm.ds[vm.bp]);
}
void vm_while_entry() {
  if (vm.ds[vm.bp]) {
    vm.ss[vm.sp] = vm.ip - 1;
    vm.sp++;
  } else {
    int c = 1;
    for (vm.ip++; vm.cs[vm.ip] && c; vm.ip++) {
      if (vm.cs[vm.ip] == ‘[‘) {
        c++;
      } else if (vm.cs[vm.ip] == ‘]‘) {
        c--;
      }
    }
  }
}
void vm_while_exit() {
  if (vm.ds[vm.bp]) {
    vm.sp--;
    vm.ip = vm.ss[vm.sp];
  }
}
void setup() {
  int c;
  int i;
 
  memset(&vm, 0, sizeof(vm));
  vm.fn[‘>‘] = vm_forward;
  vm.fn[‘<‘] = vm_backward;
  vm.fn[‘+‘] = vm_increment;
  vm.fn[‘-‘] = vm_decrement;
  vm.fn[‘.‘] = vm_output;
  vm.fn[‘,‘] = vm_input;
  vm.fn[‘[‘] = vm_while_entry;
  vm.fn[‘]‘] = vm_while_exit;
 
  for (i = 0; (c = getchar()) != EOF;) {
    if (strchr(TOKENS, c)) {
      vm.cs[i] = c;
      i++;
    }
  }
}
void run() {
  while (vm.cs[vm.ip]) {
    vm.fn[vm.cs[vm.ip]]();
    vm.ip++;
  }
}
 
int main(int argc, char* argv[]) {
  if (argc > 1) {
    freopen(argv[1], "r", stdin);
  }
 
  setup();
  run();
 
  return 0;
}

-------------------------------- 

(以上内容来自 http://blog.csdn.net/redraiment/article/details/7483062,作者:redraiment)

代码清晰易懂,不再解释了。


上面提到的图灵完备之类的概念是计算机科学(CS)中的内容,有兴趣的可以自行参考维基百科介绍,然后再决定是否要进一步的了解。不过,先提个醒,CS 是个很大很引人入胜的领域,小心“沉迷”。

Brainfuck 编程语言