一直都知道一个很有趣的语言,Brainfuck,只是一直尚未研究,今天晚上看了一下,竟然不是那么难,而且还撸出来了一个解释器。这是一种极小化的计算机语言,它是由Urban Müller在1993年创建的。
就象它的名字所暗示的,brainfuck程序很难读懂。尽管如此,brainfuck图灵机一样可以完成任何计算任务。虽然brainfuck的计算方式如此与众不同,但它确实能够正确运行。
这种语言基于一个简单的机器模型,除了指令,这个机器还包括:一个以字节为单位、被初始化为零的数组、一个指向该数组的指针(初始时指向数组的第一个字节)、以及用于输入输出的两个字节流。
下面是这八种状态的描述,其中每个状态由一个字符标识:
字符 | 含义 |
---|---|
> |
指针加一 |
< |
指针减一 |
+ |
指针指向的字节的值加一 |
- |
指针指向的字节的值减一 |
. |
输出指针指向的单元内容(ASCII码) |
, |
输入内容到指针指向的单元(ASCII码) |
[ |
如果指针指向的单元值为零,向后跳转到对应的] 指令的次一指令处 |
] |
如果指针指向的单元值不为零,向前跳转到对应的[ 指令的次一指令处 |
举个例子,hello world
[ This program prints "Hello World!" and a newline to the screen, its
length is 106 active command characters [it is not the shortest.]
This loop is a "comment loop", it's a simple way of adding a comment
to a BF program such that you don't have to worry about any command
characters. Any ".", ",", "+", "-", "<" and ">" characters are simply
ignored, the "[" and "]" characters just have to be balanced.
]
+++++ +++ Set Cell #0 to 8
[
>++++ Add 4 to Cell #1; this will always set Cell #1 to 4
[ as the cell will be cleared by the loop
>++ Add 2 to Cell #2
>+++ Add 3 to Cell #3
>+++ Add 3 to Cell #4
>+ Add 1 to Cell #5
<<<<- Decrement the loop counter in Cell #1
] Loop till Cell #1 is zero; number of iterations is 4
>+ Add 1 to Cell #2
>+ Add 1 to Cell #3
>- Subtract 1 from Cell #4
>>+ Add 1 to Cell #6
[<] Move back to the first zero cell you find; this will
be Cell #1 which was cleared by the previous loop
<- Decrement the loop Counter in Cell #0
] Loop till Cell #0 is zero; number of iterations is 8
The result of this is:
Cell No : 0 1 2 3 4 5 6
Contents: 0 0 72 104 88 32 8
Pointer : ^
>>. Cell #2 has value 72 which is 'H'
>---. Subtract 3 from Cell #3 to get 101 which is 'e'
+++++++..+++. Likewise for 'llo' from Cell #3
>>. Cell #5 is 32 for the space
<-. Subtract 1 from Cell #4 for 87 to give a 'W'
<. Cell #3 was set to 'o' from the end of 'Hello'
+++.------.--------. Cell #3 for 'rl' and 'd'
>>+. Add 1 to Cell #5 gives us an exclamation point
>++. And finally a newline from Cell #6
自己看下原理并不难,于是自己撸了一个解释器,话不多说直接上代码,用es6写的。
/**
* Brainfuck Interpreter
* author: yfgeek
* https://github.com/yfgeek
*/
'use strict';
class Interpreter{
constructor(code,input) {
this.code = code.trim().replace(/ /g, "").replace(/(\r\n|\n|\r)/gm,"").split("");
this.input = input || [];
this.pointer = 0;
this.codePointer = 0 ;
this.dataset = [];
this.bracketStack = [];
this.output = [];
}
operation(str){
switch(str){
case '+': {
this.dataset[this.pointer] = this.dataset[this.pointer] || 0;
++this.dataset[this.pointer];
break;
}
case '-': {
this.dataset[this.pointer] = this.dataset[this.pointer] || 0;
--this.dataset[this.pointer];
break;
}
case '<':{
this.pointer = --this.pointer<0 ? 0: this.pointer;
break;
}
case '>': {
this.pointer++;
break;
}
case '.':{
this.output.push(String.fromCharCode(this.dataset[this.pointer]));
break;
}
case ',':{
let c = this.input.shift();
if (typeof c === "string") {
this.dataset[this.pointer] = c.charCodeAt(0);
}
break;
}
case '[': {
this.leftBracket();
break;
}
case ']': {
this.rightBracket();
break;
}
}
};
leftBracket(){
let openBrackets = 1;
if (this.dataset[this.pointer]) {
this.bracketStack.push(this.codePointer);
} else {
while (openBrackets && this.code[++this.codePointer]) {
if (this.code[this.codePointer] === ']') {
openBrackets--;
} else if (this.code[this.codePointer] === '[') {
openBrackets++;
}
}
}
}
rightBracket(){
this.codePointer = this.bracketStack.pop() - 1;
}
run(){
let list = ['+','-','<','>','.',',','[',']'];
do{
let c = this.code[this.codePointer];
if(list.indexOf(c) >= 0) this.operation(c);
}while(++this.codePointer < this.code.length);
return this.output;
}
toString(){
return this.run().join('');
}
}
let code = '++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>.';
let i = new Interpreter(code,[]);
console.log(i.toString());