[雜記]BrainFuck語言及編譯器(c++實現)

BrainFuck語言ios

極簡的一種圖靈完備的語言,由Urban Müller在1993年創造,由八個指令組成(以下表)。工做機制與圖靈機很是類似,有一條足夠長的紙帶,初始時紙帶上的每一格都是0,有一個數據讀寫頭指向紙帶的初始位置,讀寫頭的行爲由指令指示。c++

指令 含義
> 指針向右移動一位
< 指針向左移動一位
+ 指針所指位置的值增長1字節
- 指針所指位置的值減小1字節
. 將指針所指位置的值按ASCII表輸出
, 接受1字節的輸入,存儲在當前指針所指位置
[ 當指針當前處的值爲0時,跳轉到對應]以後;不然,順序執行
] 跳轉回對應[處

用經典的Hello World!來舉例說明BrainFuck語言的畫風。ide

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

其中的空格、縮進、換行都不影響程序,只是爲了看起來可讀性更強而已。事實上,上述程序徹底能夠寫成這樣:spa

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

 

編譯器實現(c++)指針

寫了兩個版本,都差很少。第一個直接開始執行,會在從[跳轉到]時向後遍歷,時間稍長;第二個先作一次括號匹配,標記對應的括號位置,內存稍大(事實上,若是括號並很少,能夠用STL的map來動態管理內存)。code

第一個:blog

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 
  5 using namespace std;
  6 #define MaxCodeLen 1000                                     //代碼最大長度
  7 #define MaxTapeLen 3000                                     //紙帶最大長度
  8 
  9 char Code[MaxCodeLen];                                      //代碼
 10 char Tape[MaxTapeLen];                                      //紙帶
 11 int St[MaxCodeLen / 2];                                     //用來匹配括號的棧
 12 int top = 0;                                                //棧頂
 13 
 14 int isLegalInstruction(char ch)
 15 {
 16     int Ret = 0;
 17     switch(ch)
 18     {
 19         case '>' :
 20         case '<' :
 21         case '+' :
 22         case '-' :
 23         case '.' :
 24         case ',' :
 25         case '[' :
 26         case ']' : Ret = 1; break;
 27         case '\n' :
 28         case ' ' :
 29         case '\t' : Ret = 2; break;
 30         default : break;
 31     }
 32     return Ret;
 33 }
 34 
 35 int main()
 36 {
 37     freopen("Pro.txt", "r", stdin);
 38     char ch;
 39     int len = 0;
 40     int cur = 0;
 41     int i, cnt;
 42     char* p = Tape + MaxTapeLen / 2;                        //爲了方便左右移動,讓紙帶從中間開始
 43     while((ch = getchar()) != EOF)
 44     {
 45         //printf("ch = %c\n", ch);
 46         switch(isLegalInstruction(ch))
 47         {
 48             case 0 :
 49                 printf("illegal instruction\n");
 50                 return 0;
 51             case 1 :
 52                 Code[len++] = ch;
 53                 break;
 54             default:
 55                 break;
 56         }
 57     }
 58     //Code[len] = '\0';
 59     //printf("%s\n", Code);
 60     freopen("CON", "r", stdin);
 61     while(cur < len)
 62     {
 63         switch(Code[cur])
 64         {
 65             case '>' :
 66                 p++;
 67                 break;
 68             case '<' :
 69                 p--;
 70                 break;
 71             case '+' :
 72                 (*p)++;
 73                 break;
 74             case '-' :
 75                 (*p)--;
 76                 break;
 77             case '.' :
 78                 printf("%c", *p);
 79                 break;
 80             case ',' :
 81                 *p = getchar();
 82                 break;
 83             case '[' :
 84                 if(*p)
 85                 {
 86                     St[top++] = cur;
 87                 }
 88                 else
 89                 {
 90                     cnt = 0;
 91                     for(i = cur; i < len; i++)
 92                     {
 93                         if(Code[i] == '[')
 94                             cnt++;
 95                         if(Code[i] == ']')
 96                             cnt--;
 97                         if(!cnt)
 98                             break;
 99                     }
100                     if(!cnt)
101                     {
102                         cur = i;
103                     }
104                     else
105                     {
106                         printf("parentheses do not match\n");   //左括號比右括號多
107                         return 0;
108                     }
109                 }
110                 break;
111             case ']' :
112                 cur = St[top - 1] - 1;
113                 top--;
114                 break;
115             default:
116                 break;
117         }
118         cur++;
119         if(top < 0)
120         {
121             printf("parentheses do not match\n");               //右括號比左括號多
122             return 0;
123         }
124     }
125     printf("\n");
126     return 0;
127 }
View Code

第二個:ip

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 
  5 using namespace std;
  6 #define MaxCodeLen 1000                                     //代碼最大長度
  7 #define MaxTapeLen 3000                                     //紙帶最大長度
  8 
  9 char Code[MaxCodeLen];                                      //代碼
 10 char Tape[MaxTapeLen];                                      //紙帶
 11 int St[MaxCodeLen / 2];                                     //用來匹配括號的棧
 12 int top = 0;                                                //棧頂
 13 int Match[MaxCodeLen];                                      //括號匹配
 14 
 15 int isLegalInstruction(char ch)
 16 {
 17     int Ret = 0;
 18     switch(ch)
 19     {
 20         case '>' :
 21         case '<' :
 22         case '+' :
 23         case '-' :
 24         case '.' :
 25         case ',' :
 26         case '[' :
 27         case ']' : Ret = 1; break;
 28         case '\n' :
 29         case ' ' :
 30         case '\t' : Ret = 2; break;
 31         default : break;
 32     }
 33     return Ret;
 34 }
 35 
 36 int main()
 37 {
 38     freopen("Pro.txt", "r", stdin);
 39     char ch;
 40     int len = 0;
 41     int cur, i, cnt;
 42     char* p = Tape + MaxTapeLen / 2;                        //爲了方便左右移動,讓紙帶從中間開始
 43     while((ch = getchar()) != EOF)
 44     {
 45         //printf("ch = %c\n", ch);
 46         switch(isLegalInstruction(ch))
 47         {
 48             case 0 :
 49                 printf("illegal instruction\n");
 50                 return 0;
 51             case 1 :
 52                 Code[len++] = ch;
 53                 break;
 54             default:
 55                 break;
 56         }
 57     }
 58     //Code[len] = '\0';
 59     //printf("%s\n", Code);
 60     for(i = 0; i < len; i++)
 61     {
 62         if(Code[i] == '[')
 63         {
 64             St[top++] = i;
 65         }
 66         else if(Code[i] == ']')
 67         {
 68             if(top <= 0)
 69             {
 70                 printf("parentheses do not match\n");           //右括號比左括號多
 71                 return 0;
 72             }
 73             Match[i] = St[top - 1];
 74             Match[St[top - 1]] = i;
 75             top--;
 76         }
 77     }
 78     if(top > 0)
 79     {
 80         printf("parentheses do not match\n");                   //左括號比右括號多
 81         return 0;
 82     }
 83     freopen("CON", "r", stdin);
 84     cur = 0;
 85     while(cur < len)
 86     {
 87         switch(Code[cur])
 88         {
 89             case '>' :
 90                 p++;
 91                 break;
 92             case '<' :
 93                 p--;
 94                 break;
 95             case '+' :
 96                 (*p)++;
 97                 break;
 98             case '-' :
 99                 (*p)--;
100                 break;
101             case '.' :
102                 printf("%c", *p);
103                 break;
104             case ',' :
105                 *p = getchar();
106                 break;
107             case '[' :
108                 if(!(*p))
109                 {
110                     cur = Match[cur];
111                 }
112                 break;
113             case ']' :
114                 cur = Match[cur] - 1;
115                 break;
116             default:
117                 break;
118         }
119         cur++;
120     }
121     printf("\n");
122     return 0;
123 }
View Code

 

【也許有空了能夠琢磨一下寫個界面hhh】內存

 

參考:https://en.m.wikipedia.org/wiki/Brainfuckget

相關文章
相關標籤/搜索