郭嘉 发表于 2015-7-25 12:46:00

【技术宅的自我修养】BrainFuck 解释器——C实现版

作为一个技术宅的休闲活动就是研究一项非常冷门的技术,或者非主流奇葩的语言。首先,请允许我向大家介绍一下什么是BrainFuck,正如同它的名字一样,使用它和阅读它的代码就像是强♂奸你的大脑一样。下面我将用C语言为你展示如何实现BrainFuck语言解释器。
BrainFuck只有8条指令:

指令 含义 等价的C代码
> 指针加一 ++ptr;
< 指针减一 --ptr;
+ 指针指向的字节的值加一 ++*ptr;
- 指针指向的字节的值减一 --*ptr;
. 输出指针指向的单元内容 putchar(*ptr);
, 输入内容到指针指向的单元 *ptr = getchar();
[ 如果指针指向的单元值为零,向后跳转到对应的]指令的次一指令处 while (*ptr) {
] 如果指针指向的单元值不为零,向前跳转到对应的[指令的次一指令处 }
#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 */
long ip;                      /* Instruction Pointer */

char ss;/* Stack Segment */
long sp;                      /* Stack Pointer */

char ds;   /* Data Segment */
long bp;                      /* Base Pointer */

Callback fn;
} 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++;
}

void vm_decrement() {
vm.ds--;
}

void vm_input() {
vm.ds = getchar();
}

void vm_output() {
putchar(vm.ds);
}

void vm_while_entry() {
if (vm.ds) {
    vm.ss = vm.ip - 1;
    vm.sp++;
} else {
    int c = 1;
    for (vm.ip++; vm.cs && c; vm.ip++) {
      if (vm.cs == '[') {
      c++;
      } else if (vm.cs == ']') {
      c--;
      }
    }
}
}

void vm_while_exit() {
if (vm.ds) {
    vm.sp--;
    vm.ip = vm.ss;
}
}

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 = c;
      i++;
    }
}
}

void run() {
while (vm.cs) {
    vm.fn]();
    vm.ip++;
}
}

int main(int argc, char* argv[]) {
if (argc > 1) {
    freopen(argv, "r", stdin);
}

setup();
run();

return 0;
}

下面我们来看看它的Hellow World程序:
brainfuc$ cat helloword.bf
++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>.
brainfuc$ ./bf helloword.bf
Hello World!
brainfuc$
页: [1]
查看完整版本: 【技术宅的自我修养】BrainFuck 解释器——C实现版