編譯:
dp@dp:~ % gcc bfi.c -o bfi
bfi.c: In function 'interpret':
bfi.c:35: warning: incompatible implicit declaration of built-in function 'exit'
bfi.c:40: warning: incompatible implicit declaration of built-in function 'exit'
dp@dp:~ %
下面的hello.b輸出經典的hello,world:
+++++++++[<++++++++>-]<.>+++++++[<++++>-]<+.+++++++..+++.[-]>++++++++[<++++>-]
<.#>+++++++++++[<+++++>-]<.>++++++++[<+++>-]<.+++.------.--------.[-]>++++++++[
<++++>-]<+.[-]++++++++++.
用剛生成的bf語言解釋器運行它:
dp@dp:~ % ./bfi hello.b
Hello World!
prime.b完成指定整數內質數的計算:
===================================================================
======================== OUTPUT STRING ============================
===================================================================
++++++++[<++++++++>-]<++++++++++++++++.[-]
++++++++++[<++++++++++>-]<++++++++++++++.[-]
++++++++++[<++++++++++>-]<+++++.[-]
++++++++++[<++++++++++>-]<+++++++++.[-]
++++++++++[<++++++++++>-]<+.[-]
++++++++++[<++++++++++>-]<+++++++++++++++.[-]
+++++[<+++++>-]<+++++++.[-]
++++++++++[<++++++++++>-]<+++++++++++++++++.[-]
++++++++++[<++++++++++>-]<++++++++++++.[-]
+++++[<+++++>-]<+++++++.[-]
++++++++++[<++++++++++>-]<++++++++++++++++.[-]
++++++++++[<++++++++++>-]<+++++++++++.[-]
+++++++[<+++++++>-]<+++++++++.[-]
+++++[<+++++>-]<+++++++.[-]
===================================================================
======================== INPUT NUMBER ============================
===================================================================
+ cont=1
[
- cont=0
>,
======SUB10======
----------
[ not 10
<+> cont=1
=====SUB38======
----------
----------
----------
--------
>
=====MUL10=======
[>+>+<<-]>>[<<+>>-]< dup
>>>+++++++++
[
<<<
[>+>+<<-]>>[<<+>>-]< dup
[<<+>>-]
>>-
]
<<<[-]<
======RMOVE1======
<
[>+<-]
]
<
]
>[<<+>>-]<<
===================================================================
======================= PROCESS NUMBER ===========================
===================================================================
==== ==== ==== ====
numd numu teid teiu
==== ==== ==== ====
+<-
[
>+
======DUP======
[>+>+<<-]>>[<<+>>-]<
>+<--
>>>>>>>>+<<<<<<<< isprime=1
[
>+
<-
=====DUP3=====
<[>>>+>+<<<<-]>>>>[<<<<+>>>>-]<<<
=====DUP2=====
>[>>+>+<<<-]>>>[<<<+>>>-]<<< <
>>>
====DIVIDES=======
[>+>+<<-]>>[<<+>>-]< DUP i=div
<<
[
>>>>>+ bool=1
<<<
[>+>+<<-]>>[<<+>>-]< DUP
[>>[-]<<-] IF i THEN bool=0
>>
[ IF i=0
<<<<
[>+>+<<-]>>[<<+>>-]< i=div
>>>
- bool=0
]
<<<
- DEC i
<<
-
]
+>>[<<[-]>>-]<<
>[-]< CLR div
=====END DIVIDES====
[>>>>>>[-]<<<<<<-] if divides then isprime=0
<<
>>[-]>[-]<<<
]
>>>>>>>>
[
-
<<<<<<<[-]<<
[>>+>+<<<-]>>>[<<<+>>>-]<<<
>>
===================================================================
======================== OUTPUT NUMBER ===========================
===================================================================
[>+<-]>
[
======DUP======
[>+>+<<-]>>[<<+>>-]<
======MOD10====
>+++++++++<
[
>>>+<< bool= 1
[>+>[-]<<-] bool= ten==0
>[<+>-] ten = tmp
>[<<++++++++++>>-] if ten=0 ten=10
<<- dec ten
<- dec num
]
+++++++++ num=9
>[<->-]< dec num by ten
=======RROT======
[>+<-]
< [>+<-]
< [>+<-]
>>>[<<<+>>>-]
<
=======DIV10========
>+++++++++<
[
>>>+<< bool= 1
[>+>[-]<<-] bool= ten==0
>[<+>-] ten = tmp
>[<<++++++++++>>>+<-] if ten=0 ten=10 inc div
<<- dec ten
<- dec num
]
>>>>[<<<<+>>>>-]<<<< copy div to num
>[-]< clear ten
=======INC1=========
<+>
]
<
[
=======MOVER=========
[>+<-]
=======ADD48========
+++++++[<+++++++>-]<->
=======PUTC=======
<.[-]>
======MOVEL2========
>[<<+>>-]<
<-
]
>++++[<++++++++>-]<.[-]
===================================================================
=========================== END FOR ===============================
===================================================================
>>>>>>>
]
<<<<<<<<
>[-]<
[-]
<<-
]
======LF========
++++++++++.[-]
用剛編譯生成的bf語言解釋器運行它:
dp@dp:~ % ./bfi prime.b
Primes up to: 20
2 3 5 7 11 13 17 19
BF解釋器分析:
1、main函數以只讀方式打開BF語言的源代碼文件,然後,將BF源文件按字節逐個拷入數組f中,並在最後加上字符串的結束標誌0,最後,以數組f爲參數,調用interpret函數解釋執行BF語言源代碼。
if((z=fopen(argv[1],"r"))) {
while( (b=getc(z))>0 )
*s++=b;
*s=0;
interpret(f);
}
2、BF語言的解釋器以數組爲數據中心進行計算,在它的計算模型中,需要一個指向數組的指針,通過這個指針的移動以及對指針指向內容的操作完成所有的計算。因此,程序在開頭處聲明瞭解釋器的核心:數組a與f,數據a存放BF指令所操作的數據,數組f存放BF語言代碼文件,同時聲明指針變量s指向f數組的第一個元素。
char a[5000], f[5000], b, o, *s=f;
3、interpret函數解析
這個函數是實現BF語言解釋執行的關鍵。interpret函數接受數組指針c(指存放向BF語言源代碼的數組),然後通過while語句逐個字符提取BF源代碼(因爲BF源代碼中每個字符就是一條指令),通過swith...case...語句塊判斷BF指令(<、>、+、-、.、,、[、]),執行BF指令。
這些指令分爲非跳轉指令與跳轉指令:
(1)非跳轉指令完成了除循環外的其它功能。比如移動指針(指針指變量p,比如代碼中的“ p--”以及“p++”)、對數組(數組指變量a,比如代碼中的“a[p]++”以及“a[p]--”)的操作、輸出(代碼中的“putchar(a[p]); fflush(stdout); break;”)和輸入(代碼中的“case ','”標示的語句塊)。
void interpret(char *c)
{
char *d; int tmp;
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 ',':
tmp=getchar();
if (tmp == EOF) a[p]=0;
else a[p]=tmp;
................
.................
}
r--;
}
(2)跳轉指令完成了循環功能。在循環指令的解釋執行過程中,使用了遞歸機制完成了BF語言的“[”與”]” 指令的解釋,“[”標示着一段循環的開始,而“]”標示着一段循環的結束,這意味着循環可以嵌套,可以由多個“[”與”]” 指令組成多層循環。
[
如果指針指向的單元值爲零,向後跳轉到對應的]指令的次一指令處
]
如果指針指向的單元值不爲零,向前跳轉到對應的[指令的次一指令處
因爲可能存在多種循環,所以必須找到本次循環開始的“[”對應的“]”處,循環的條件通過指針指向的單元值來決定,只要指針指向的內容爲0,則循環結束,否則循環繼續。
通過下面這段語句,完成對應“[”的“]”的查找,尋找的過程中,更新下一步要執行的BF指令指針(for循環語句中的“c++”):
for( b=1,d=c; b && *c; c++ )
b+=c=='[', b-=c==']';
找到循環的結束處後,對指針指向的單元值( 下面代碼中的“a[p]”)進行判斷,只要單元值不爲0,則遞歸調用interpret函數進行下一條指令的解釋:
while( a[p] )
interpret(d);
爲防止循環的符號不對應,比如說,最後多了循環結束標誌”]”,則出現了異常,程序非正常退出,如下面代碼所示:
case ']':
puts("UNBALANCED BRACKETS"), exit(0);
對這2個指令的解釋的全部代碼如下:
void interpret(char *c)
{
char *d; int tmp;
r++;
while( *c ) {
............
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);
.................................