golang 實現brainfuck 解譯器

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。

brainfuck  是極為簡化esoteric 程式設計語言,或許可以翻作蛋疼程式設計語言,僅有八條指令,如果用這玩意搞項目,應該比彙編編程還蛋疼,不過據說是圖靈完全。它的hello world 是這樣的:

++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.

整個代碼都是由+,-,>, <, . , [, ], , 組成。


Character Meaning

> 增加資料指標 (使其指向當前右邊記憶體單元).

< 減少資料指標(使其指向當前左邊記憶體單元).

+ 對當前記憶體單元加 1 

-       對當前記憶體單元減 1

. 輸出當記憶體單元

, 接受一個位元組的輸入,將其放到當前資料指標指向的記憶體單元

[ 如果當前資料指標指向的單元,值為非0, 進入迴圈,執行緊靠 [ 後面的指令;否則,向前跳轉到與此 [ 匹配的 ] 之後開始執行

] 如果當前資料指標指向的單元,值為非0,向後跳轉,回到與此 ] 匹配的 [ 後面執行, 否則,正常流程,繼續向下執行


brainfuck 命令  c語言等價操作

(Program Start) char array[infinitely large size] = {0};

char *ptr=array;

> ++ptr;

< --ptr;

+ ++*ptr;

- --*ptr;

. putchar(*ptr);

, *ptr=getchar();

[ while (*ptr) {

] }

package mainimport ("fmt""io/ioutil""os")//表達brainfuck使用的機器模型,連續位元組記憶體塊type tape struct {mem []bytepos int}func TapeNew() *tape {t := new(tape)t.mem = make([]byte, 4096)return t}//.操作, putchar(*ptr)func (t *tape) get() byte { return t.mem[t.pos] }//,操作, *ptr = getchar()func (t *tape) set(val byte) { t.mem[t.pos] = val }//+操作, ++*ptrfunc (t *tape) inc() { t.mem[t.pos]++ }//-操作, --*ptrfunc (t *tape) dec() { t.mem[t.pos]-- }//>操作,  ++ptrfunc (t *tape) forward() {t.pos++if len(t.mem) <= t.pos {t.mem = append(t.mem, 0)}}//<操作,--ptrfunc (t *tape) backward() { t.pos-- }func interpret(prog string, whilemap map[int]int) {pc := 0tape := TapeNew()var tmp bytefor pc < len(prog) {switch prog[pc] {case '>':tape.forward()case '<':tape.backward()case '+':tape.inc()case '-':tape.dec()case '.':c := tape.get()fmt.Printf("%c", c)case ',':fmt.Scanf("%c", &tmp)tape.set(tmp)case '[':if tape.get() == 0 {pc = whilemap[pc]}case ']':if tape.get() != 0 {pc = whilemap[pc]}}pc++}}func parse(prog string) (string, map[int]int) {parsed := make([]byte, 0)pcstack := make([]int, 0)//記錄[,對應的],索引(指令)位置whilemap := make(map[int]int, 128)pc := 0for _, char := range prog {//fmt.Printf("got char: %c\n", char)switch char {case '>', '<', '+', '-', '.', ',', '[', ']':parsed = append(parsed, byte(char))if char == '[' {pcstack = append(pcstack, pc)} else if char == ']' {last := len(pcstack) - 1left := pcstack[last]pcstack = pcstack[:last]right := pcwhilemap[right] = leftwhilemap[left] = right}pc++}}return string(parsed), whilemap}func main() {if len(os.Args) < 2 {fmt.Printf("Usage: %s <brainfuck source file>\n", os.Args[0])os.Exit(1)}c, err := ioutil.ReadFile(os.Args[1])if err != nil {fmt.Printf("read brainfuck file failed!\n")os.Exit(2)}interpret(parse(string(c)))}

hello.b:

++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++../brainfuck  hello.bHello World!add.b:>> +    [- >,>+<     ----- ----- ----- -----    ; checking with ascii 43 ie plus symbol    ----- ----- ----- -----    ---    [    +++++ +++++ +++++ +++++    +++++ +++++ +++++ +++++    +++    < ] >>    ]    ; first input is over and terminated by a 'plus' symbol    <->>>>>+    [- >,>+<    ----- ----- ----- -----   ; checking with ascii 61 ie = symbol    ----- ----- ----- -----    ----- ----- ----- ------    [    +++++ +++++ +++++ +++++    +++++ +++++ +++++ +++++    +++++ +++++ +++++ ++++++    < ] >>    ]        ; second input is over and terminated by an = symbol        ; now the array looks like 0 0 0 49 0 50 0 0 0 0 0 0 0 0 49 0 53 0 0 1 0        ; for an input 12'plus'15=    <<<<    [<+<]                ; filled with 1's in between    + [<+>-<<[>-]>] ; This is a special loop to traverse LEFT through indefinite no of 0s                ; Lets call it left traverse    <<    [<+<]    >[>]<               ; now the array looks like               ; 0 0 1 49 1 50 0 0 0 0 0 0 0 1 49 1 53 0 0 1 for eg:12plus15    [    [->+>   + [>+<->>[<-]<]  ; Right traverse        >>[>]<+ [<]        + [<+>-<<[>-]>]  ; Left traverse        <<-<    ]     + [>+<->>[<-]<]     >> [>] <<-<[<]    + [<+>-<<[>-]>]    <<-<    ]             ; now actual addition took place             ; ie array is 00000000000000 98 0 103 0 0 1    + [>+<->>[<-]<]    >>    [     ----- ----- ----- -----    ----- ----- ----- -----    ----- ---    >>]                ; minus 48 to get the addition correct as we add 2 ascii numbers    >-<         ; well an undesired 1 was there 2 place after 103 right ? just to kill it            ; now the array is 00000 00000 0000 50 0 55            ; now comes the biggest task Carry shifting    <<    [<<]    +++++ +++++ +++++ +++++    +++++ +++++ +++++ +++++    +++++ +++    [>>]        ; we added a 48 before all the digits in case there is an overall carry        ; to make the size n plus 1        ; array : 00000 00000 00 48 0 50 0 55    <<    <<    [    [>>->[>]>+>>>> >>>+<<<< <<<<<[<]><<]    >+[>]>-    [-<<[<]>+[>]>]    >>>>>+>>>    +++++ +++++ +++++ +++++ +++++    +++++ +++++ +++++ +++++ +++++    +++++ +++    <                ; comparison loop:  0   1   0   a      b  0                ;                  (q) (p)    (num)  (58)    [->-[>]<<]  ; comparison loop to check each digit with 58: greater means                 ; we need to minus 10 and add 1 to next significant digit    <[-            ; n greater than or equal to 58 (at p)            <<<< <<<            [<]+            >            ----- ----- ; minus 10 to that digit            <<+         ; plus 1 to next digit            >            [>]            >>>>>>    ]    < [-<            ; n less than 58 (at q)            <<<<<<            [<]+            [>]            >>>>>      ]        ; at (q)        >>>[-]>[-]        <<<<< <<<<<        [<]>        <<    ]        ; Its all over now : something like 0 48 0 52 0 66 ( ie 0 4 18 )        ; will turn into 0 48 0 53 0 56 (ie 0 5 8)    >>    ----- ----- ----- -----    ----- ----- ----- -----    ----- ---            ; here we are just checking first digit is 48 or not            ; its weird to print 0 ahead but it is defenitely needed            ; if it is 49 ie 1    [    +++++ +++++ +++++ +++++    +++++ +++++ +++++ +++++    +++++ +++    .    [-]    ]    >>    [.>>]    +++++ +++++    .           ; to print nextline : ascii 10

./brainfuck add.b

1234+0001=

1235

fib.b:

>++++++++++>+>+[

    [+++++[>++++++++<-]>.<++++++[>--------<-]+<<<]>.>>[

        [-]<[>+<-]>>[<<+>+>-]<[>+<-[>+<-[>+<-[>+<-[>+<-[>+<-

            [>+<-[>+<-[>+<-[>[-]>+>+<<<-[>+<-]]]]]]]]]]]+>>>

    ]<<<

]

./brainfuck  fib.b

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.