[杂记]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 }
第二个:
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++实现)的更多相关文章
- 你知道第一个C语言C++编译器是如何诞生的吗?
当今几乎所有的实用的编译器/解释器(以下统称编译器)都是用 C 语言编写的,有一些语言比如 Clojure,Jython 等是基于 JVM 或者说是用 Java 实现的,IronPython 等是基于 ...
- Lambda表达式(C语言-gcc编译器)
前言 先来啰嗦几句,身边的朋友,同事都喜欢在博客上记录自己在学习计算机编程技术路程上的一些问题和心得.就我个人而言,这是个好习惯,特别是在计算机编程领域,技术方向种类繁多,永无止境.所以,我也开始我人 ...
- 研究Java语言的编译器和虚拟机源代码
现在使用Java语言的人很多,但是了解Java语言实现的人非常少.如果要研究Java语言的实现,推荐研究Javac和虚拟机HotSpot的源代码实现,其中Javac相当于Java编译的前端,HotSp ...
- 从零开始Go语言-GoLand(编译器)-Windows(平台)
本文章适合那些想入门Go语言,却又不知道如何搭建自己的第一个HelloWorld的同学. 推荐几个Go语言相关学习网站: C语言中文网: http://c.biancheng.net/golang/ ...
- BrainFuck语言生成器
还要求生成的代码比较快和短. 当然stackexchange上面给出了实现,java的 http://codegolf.stackexchange.com/questions/5418/brainfu ...
- 一门能让你五分钟学会的语言-Brainfuck
看到标题,不出意外的话,你肯定开始骂我了:**标题党,什么编程语言五分钟就能学会? 其实我本来也是不相信的,但是学过了才知道这是真的. 1.Brainfuck 看到这个小标题,不要误会,我没有骂人. ...
- 第一个C语言编译器是怎样编写的?
首先向C语言之父Dennis MacAlistair Ritchie致敬! 当今几乎所有的实用的编译器/解释器(以下统称编译器)都是用C语言编写的,有一些语言比如Clojure,Jython等是基于J ...
- 【转】自己动手写SC语言编译器
自序 编译原理与技术的一整套理论在整个计算机科学领域占有相当重要的地位,学习它对程序设计人员有很大的帮助.我们考究历史会发现那些人人称颂的程序设 计大师都是编译领域的高手,像写出BASIC语言的BIL ...
- C语言_来了解一下GCC编译器编译C可执行脚本的过程
GCC简介 Linux系统下的gcc(GNU C Compiler)是GNU推出的功能强大.性能优越的多平台编译器,是GNU的代表作品之一.gcc是可以在多种硬体平台上编译出可执行程序的超级编译 ...
随机推荐
- JQuery选择器的使用和分类
jQuery选择器 id选择器格式 $("#box") //获取标签里的id是box的标签 类选择器格式 $(".a") //获取标签里的类名是a的标签 标签选 ...
- Solon Web 开发,六、过滤器、处理、拦截器
Solon Web 开发 一.开始 二.开发知识准备 三.打包与运行 四.请求上下文 五.数据访问.事务与缓存应用 六.过滤器.处理.拦截器 七.视图模板与Mvc注解 八.校验.及定制与扩展 九.跨域 ...
- 【解决了一个小问题】go.mod文件中引用另一个库,总会自动拉取新版本
我的项目依赖某个旧的公共库: require ( git.xxx.com/myprj/mylib v0.0.43 ) 可以编译的时候,系统总会自动加上这样的路径: require ( git.xxx. ...
- ARTS Week 22
Algorithm 本周的 LeetCode 题目为 297. 二叉树的序列化与反序列化 序列化是将一个数据结构或者对象转换为连续的比特位的操作,进而可以将转换后的数据存储在一个文件或者内存中,同时也 ...
- 集合框架-工具类-JDK5.0特性-ForEach循环
1 package cn.itcast.p4.news.demo; 2 3 import java.util.ArrayList; 4 import java.util.HashMap; 5 impo ...
- GoLang设计模式20 - 组合模式
定义 组合模式是一种结构型设计模式. 当我们想把一组对象当做一个整体来处理时就可以考虑使用组合模式. 组合模式被视为是接口型设计模式是因为它将一组对象组装为一个树状结构.这个树状结构中的每个独立组件都 ...
- cp 不提示按y
yes|cp index.html.j2 yml -rf \cp index.html.j2 yml/ 两个效果是一样的
- 检测当前编译器支持c++版本
if (__cplusplus > 201703L) std::cout << "C++2a\n"; else if (__cplusplus == 201703 ...
- ApacheCN Angular 译文集 20211114 更新
Angular 专家级编程 零.前言 一.架构概述和在 Angular 中构建简单应用 二.将 AngularJS 应用迁移到 Angular 应用 三.使用 Angular CLI 生成具有最佳实践 ...
- uniapp自定义顶部搜索框兼容微信小程序
zhuanzai: uniapp自定义顶部搜索框兼容微信小程序 自定义组件 navbarvue (胶囊底部高度 - 状态栏的高度) + (胶囊顶部高度 - 状态栏内的高度) = 导航栏的高度 < ...