【技术宅的自我修养】BrainFuck 解释器——C实现版
作者:郭嘉
作为一个技术宅的休闲活动就是研究一项非常冷门的技术,或者非主流奇葩的语言。首先,请允许我向大家介绍一下什么是BrainFuck,正如同它的名字一样,使用它和阅读它的代码就像是强♂奸你的大脑一样。下面我将用C语言为你展示如何实现BrainFuck语言解释器。 BrainFuck只有8条指令:指令 | 含义 | 等价的C代码 |
> | 指针加一 | ++ptr; |
< | 指针减一 | --ptr; |
+ | 指针指向的字节的值加一 | ++*ptr; |
- | 指针指向的字节的值减一 | --*ptr; |
. | 输出指针指向的单元内容 | putchar(*ptr); |
, | 输入内容到指针指向的单元 | *ptr = getchar(); |
[ | 如果指针指向的单元值为零,向后跳转到对应的]指令的次一指令处 | while (*ptr) { |
] | 如果指针指向的单元值不为零,向前跳转到对应的[指令的次一指令处 | } |
[mw_shl_code=c,true]#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 = 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; } [/mw_shl_code] 下面我们来看看它的Hellow World程序: [mw_shl_code=c,true]brainfuc$ cat helloword.bf ++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>. brainfuc$ ./bf helloword.bf Hello World! brainfuc$[/mw_shl_code]