[杂记]BrainFuck语言及编译器(c++实现)

BrainFuck语言

极简的一种图灵完备的语言,由Urban Müller在1993年创造,由八个指令组成(如下表)。工作机制与图灵机非常相似,有一条足够长的纸带,初始时纸带上的每一格都是0,有一个数据读写头指向纸带的初始位置,读写头的行为由指令指示。

指令 含义
> 指针向右移动一位
< 指针向左移动一位
+ 指针所指位置的值增加1字节
- 指针所指位置的值减少1字节
. 将指针所指位置的值按ASCII表输出
, 接受1字节的输入,存储在当前指针所指位置
[ 当指针当前处的值为0时,跳转到对应]之后;否则,顺序执行
] 跳转回对应[处

用经典的Hello World!来举例说明BrainFuck语言的画风。

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

其中的空格、缩进、换行都不影响程序,只是为了看起来可读性更强而已。事实上,上述程序完全可以写成这样:

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

 

编译器实现(c++)

写了两个版本,都差不多。第一个直接开始执行,会在从[跳转到]时向后遍历,时间稍长;第二个先做一次括号匹配,标记对应的括号位置,内存稍大(事实上,如果括号并不多,可以用STL的map来动态管理内存)。

第一个:

  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

第二个:

  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/Brainfuck

posted @ 2018-05-02 10:34  zyy是一只超级大沙茶  阅读(6078)  评论(0编辑  收藏  举报