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. 2022 跳槽涨薪必不可少面试通关宝典 —— css 篇

    生于忧患死于安乐!已经居家隔离 23 天了,解封以后估计就得找工作了,提前准备起来!需要的赶紧收藏起来 一.谈谈你对 BFC 的理解及作用. BFC 是 Block Formatting Contex ...

  2. [STM32F4xx 学习] SPI与nRF24L01+的应用

    前面已经总结过STM32Fxx的特点和传输过程,下面以nRF24L01+ 2.4GHz无线收发器为例,来说明如何使用SPI. 一.nRF24L01+ 2.4GHz无线收发器的介绍 1. 主要特性 全球 ...

  3. web自动化-selenium 入门篇

    selenium安装介绍 selenium是web浏览器的自动化工具 官网:https://www.selenium.dev 构成: WebDriver: 浏览器提供的浏览器api来控制浏览器(模拟用 ...

  4. virtual studio发布到gihub

    问题 我们想要发布代码到github或者微软团队服务时候,往往发现没有本地库,所以难以发布. 解决方案 在解决方右击就可以新建git 文件都会出现小锁说明有了记录 文件夹会对应出现 右上角管理连接也会 ...

  5. java IO 文件复制代码模型

    package com.xjtu.demo; import java.io.*; public class FileCopy { public static void main(String[] ar ...

  6. kubernetes之部署traefik-ingress分为http和https

    1 理解Ingress 简单的说,ingress就是从kubernetes集群外访问集群的入口,将用户的URL请求转发到不同的service上.Ingress相当于nginx.apache等负载均衡方 ...

  7. 洛谷P1002过河卒java100分题解

    题目描述如图: 这道题我以前以回溯的方法做,只能拿到60分 现在才发现是道动态规划题 解题思路: 创建一个(0,0)到终点打小的二维数组表示棋盘 每个坐标的值为此位置到终点的路数 最下方一排和最右方一 ...

  8. SharePoint Online 触发 Outlook 邮件内审批

    前言 我们在做SharePoint Online项目时, 经常会有客户问,我们能否在通知邮件中快速完成审批,而不是需要在邮件中打开系统,然后在系统中审批? 答案肯定是可以的,来!安排! 正文 1.我们 ...

  9. HTML Entry 源码分析

    简介 从 HTML Entry 的诞生原因 -> 原理简述 -> 实际应用 -> 源码分析,带你全方位刨析 HTML Entry 框架. 序言 HTML Entry 这个词大家可能比 ...

  10. String存放位置

    简介 字符串在不同的JDK版本中,存放的位置不同,创建方式不同,存放的位置也不同. 存放位置 JDK1.7以下,无论何种方法创建String对象,位置都位于方法区. JDK1.8及1.8以上,new ...