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 }

第二个:

  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 }

【也许有空了可以琢磨一下写个界面hhh】

参考:https://en.m.wikipedia.org/wiki/Brainfuck

[杂记]BrainFuck语言及编译器(c++实现)的更多相关文章

  1. 你知道第一个C语言C++编译器是如何诞生的吗?

    当今几乎所有的实用的编译器/解释器(以下统称编译器)都是用 C 语言编写的,有一些语言比如 Clojure,Jython 等是基于 JVM 或者说是用 Java 实现的,IronPython 等是基于 ...

  2. Lambda表达式(C语言-gcc编译器)

    前言 先来啰嗦几句,身边的朋友,同事都喜欢在博客上记录自己在学习计算机编程技术路程上的一些问题和心得.就我个人而言,这是个好习惯,特别是在计算机编程领域,技术方向种类繁多,永无止境.所以,我也开始我人 ...

  3. 研究Java语言的编译器和虚拟机源代码

    现在使用Java语言的人很多,但是了解Java语言实现的人非常少.如果要研究Java语言的实现,推荐研究Javac和虚拟机HotSpot的源代码实现,其中Javac相当于Java编译的前端,HotSp ...

  4. 从零开始Go语言-GoLand(编译器)-Windows(平台)

    本文章适合那些想入门Go语言,却又不知道如何搭建自己的第一个HelloWorld的同学. 推荐几个Go语言相关学习网站: C语言中文网: http://c.biancheng.net/golang/ ...

  5. BrainFuck语言生成器

    还要求生成的代码比较快和短. 当然stackexchange上面给出了实现,java的 http://codegolf.stackexchange.com/questions/5418/brainfu ...

  6. 一门能让你五分钟学会的语言-Brainfuck

    看到标题,不出意外的话,你肯定开始骂我了:**标题党,什么编程语言五分钟就能学会? 其实我本来也是不相信的,但是学过了才知道这是真的. 1.Brainfuck 看到这个小标题,不要误会,我没有骂人. ...

  7. 第一个C语言编译器是怎样编写的?

    首先向C语言之父Dennis MacAlistair Ritchie致敬! 当今几乎所有的实用的编译器/解释器(以下统称编译器)都是用C语言编写的,有一些语言比如Clojure,Jython等是基于J ...

  8. 【转】自己动手写SC语言编译器

    自序 编译原理与技术的一整套理论在整个计算机科学领域占有相当重要的地位,学习它对程序设计人员有很大的帮助.我们考究历史会发现那些人人称颂的程序设 计大师都是编译领域的高手,像写出BASIC语言的BIL ...

  9. C语言_来了解一下GCC编译器编译C可执行脚本的过程

    GCC简介    Linux系统下的gcc(GNU C Compiler)是GNU推出的功能强大.性能优越的多平台编译器,是GNU的代表作品之一.gcc是可以在多种硬体平台上编译出可执行程序的超级编译 ...

随机推荐

  1. 带你十天轻松搞定 Go 微服务系列(一)

    本文开始,我们会出一个系列文章跟大家详细展示一个 go-zero 微服务示例,整个系列分十篇文章,目录结构如下: 环境搭建(本文) 服务拆分 用户服务 产品服务 订单服务 支付服务 RPC 服务 Au ...

  2. 使用ansible 批量分发ssh密钥

    先看执行结果 看看ssh.yml怎么写的 看看hosts文件中backup组怎么写的

  3. 【webpack4.0】---webpack的基本使用(一)

    一.初识webpack 1.什么是webpack? WebPack可以看做是模块打包机:它做的事情是,分析你的项目结构,找到JavaScript模块以及其它的一些浏览器不能直接运行的拓展语言(Scss ...

  4. mysql新增用户无法登陆问题解决ERROR 1045 (28000)

    mysql增加新用户无法登陆解决方法 ERROR 1045 (28000): Access denied for user 'appadmin'@'localhost' (using password ...

  5. 学习JAVAWEB第六天

    # 今日内容: 1. JavaScript: 1. ECMAScript: 2. BOM: 3. DOM: 1. 事件 ## DOM简单学习:为了满足案例要求 * 功能:控制html文档的内容 * 获 ...

  6. 计算机网络再次整理————tcp例子第二前奏[四]

    前言 前文我们介绍了网络协议的各层,同时也介绍了一下我们在编写代码时候的服务端的accept.bind.listen.connect.send做了什么. 可以说是从宏观的角度,或者代码开发的角度来说的 ...

  7. AT2400 [ARC072B] Alice&Brown

    通过打表后可以发现,当初始石头数 \(|X - Y| \le 1\) 时先手必败否则先手必胜. 我们考虑使用归纳证明这个结论,显然 \((1, 0), (1, 1)\) 时是成立的. 基于观察,我们可 ...

  8. C3P0数据库连接池数据库插入中文乱码问题解决

    问题描述 近期修改一个学生信息管理的JavaWeb项目,其数据库连接池使用了C3P0.在实际测试时,发现在学生信息模块添加中文学生信息会在数据库(MySQL)出现中文乱码问题. 如图所示: 问题分析 ...

  9. Scala中的运算符

    Scala和Java中的运算符用法基本一致. 一.区别 1."=="和"equals"的用法 Java: String str1 = "abc&quo ...

  10. 06.python语法入门--与用户交互、运算符

    与用户交互 输入 input    # python2与python3的区别        '''python3'''    # 将获取到的用户输入赋值给变量名res    res = input(' ...