编程便笺:代码的图形(二)
在上一篇 编程便笺:代码的图形(一) 一文中描述了如何用C++直接把结构语义图形化,在继续这个话题以前,我们先暂时放一放,做些准备工作。本文先来描述一下控制语义或者说是规则语义的图形化。
像上一篇文章所说,结构很大的程度上是体现地是几何的概念,也就是图形的概念。而控制语义的图形化离不开图灵机,对于这一点,有以下一些理由:
1、图灵机从表面上看,直接体现地是匹配控制的概念,控制是图灵机的核心;
2、图灵机的语言比一般语言更接近于图形,体现图形的特色,对于编程来说,大部分的时候是形式比实质更重要,换句话说,对于程序员来说,语义的表现比语义的实现更有感受。我们平时指的语言计算能力,应该是指一种语言用于描述解决方案的能力,而解决方案是针对于某一方面的应用,这里指的计算能力是指完成一件事的繁简程度。而对于实际的代数计算,只要是图灵等价,相应的计算能力是一致的,这个时候计算能力是指完成一件事。
3、图灵机的执行是顺序的,但图灵机的语言是非顺序的,有利于扩展和调整。
4、图灵机的控制能力比较强,但计算能力比较弱(至少不会用图灵机去写计算吧?),而计算语义一般是不需要图形化的。对于计算语义可以用函数式的方式来弥补。
关于图灵机的编程,在 以图灵的方式编程一文中有所简单的介绍,正宗的写法可以参考计算理论和计算复杂性的书籍。另外在 编程便笺:Iterator 一文中,探讨了图灵机与迭代器的关系。
在下面,与上一文章不同,我们不首先用c++构造图灵机的实例,这个任务留给后续的文章,在这里,我们首先描述出编程所需要的图灵机式样。
另外说明一点,以下的程序都不会是纯正的图灵程序,纯正的图灵程序的阅读是对记忆力的考验,不想跳楼的就不要去坚持。秉持程序员的宗旨,以简单实用为出发点,根据需要做必要的调整,没有门派、没有宗教、也没有生态牵扯。
好了,现在让我们开始图灵机的图形之旅。
作为第一步,我们先来扩展图灵机的基本操作,这些操作会在后续的文件里用到,所以先在这里列出来,根据需要我们定义以下一些操作:
1) → 右移
2) ← 左移
3) +# 设置标记
4) -# 清楚标记
5) →# 右移到标记
6) ←# 左移到标记
7) ↘(t,x) 入栈
8) ↗(t) 出栈
9) +(t,x) 插入项
10) -(t,x) 删除项
11) <=(t,x) 替换项
12) #ident 命名
13) ∨ 起点
14) ∧ 限界
15) ↑indent 取值
16) ∪ 保存环境
17) ∩ 弹出环境
18) - 不处理
19) Ω ->Ω <-Ω 折弯,进入折弯,退出折弯
你可能已经发现,上面的操作远多于书上写的,那是因为我们不能把自己的手脚先绑起来。
在操作时,我们假定有两条基本图灵条带,输入条带和输出条带。输入条带基本不去修改它,修改只发生在输出条带上,为安全起见,输出条带也作了一些限制,在条带上设定了一个界限,被调用的图灵机只可直接界限以上的数据。当输入输出条带合用时,限定只能做入栈操作。
设置标记和命名是为了方便查找和取值,也便于定义循环的起限。
折弯操作其实是把条带中的两点连接起来,理解这一点,->Ω <-Ω的含义应该也就清楚了。
上面的许多操作以及自定义操作,我们在后续的文章中用到,现在只用 → ,←, - 这些操作,一些要用到的自定义操作也简化了,下面的内容主要是把原始的图灵语言转化成一种直观的,我们能比较接受的方式。然后比较一下与平时编码的异同。
以下是词法分析中+ - /的处理, 从中可以看出经典turing语言的式样。C++宏并没有真实处理turing动作,只是把turing代码打印输出。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <stdio.h> #include <stdlib.h> #include <tchar.h> #define ← << #define → >> #define M(s0,s1,m,d) printf("(%s %s %s %s)\r\n",#s0,#s1,#m,#d) #define T(x) printf("Turing %s:\r\n",#x) #define M1(s0) printf("%s\r\n",#s0) #define m(...) 1 #define M2(...) 1 #define R(...) 1 #define wait printf("\r\n");printf("Press any key to exit!"); getchar();exit(1); int _tmain(int argc, _TCHAR* argv[]) { //process + M(s0,+, s+,→); M(s+,=, s0,→); //+= M(s+,+, s0,→); //++ M(s+,≠,s0,←); //+ //process - M(s0,+, s-,→); M(s-,=, s0,→); //-= M(s-,+, s0,→); //-- M(s-,≠,s0,←); //- //process div M(s0, /, sd,→); //line comment M(sd, /, sml,→); M(sml,\n, s0,→); M(sml,≠, s0,→); //block comment M(sd, *, smb,→); M(smb,[*/], s0,→); M(smb,≠, s0,→); //div M(sd,≠, s0,→); //div wait; }
现在摘录出一段来分析一下:
//process + M(s0,+, s+,→); M(s+,=, s0,→); //+= M(s+,+, s0,→); //++ M(s+,≠,s0,←); //+
这是词法分析器在处理+的情形,从中可以看出turing代码是规则形的,处理过程是匹配、动作、状态改变,然后继续。与普通程序不一样,代码顺序是没有关系的,这一点对于实现代码的组合和扩展是非常有利的。
在上面我们定义了一些状态,其实状态和匹配决定着turing机的执行进程。这些状态如果在描述一个流程,应该是需要的,但在代码中,往往是不需要的,甚至有害,这一点可以在上面处理注释部分体现出来。复杂的代码中,状态很难带有辨析性质,即使带有辨析性质,也需要从头开始在脑中构建出整个处理图形。多了几个嵌套的if语句,我们已经不乐意了,这而不跳.....
对于turing代码,要变得使用,不改造看来是不行的了。改造归改造,turing代码一些优越的地方我们仍需保持,特别是对规则处理的适用性和代码顺序的无关性这两点,无论如何是要保留的。这两点对于其他语言来说是一个弱项,这里的弱,还是是指表达能力。现在我们已经把原则定好了,下面开始调整。
很多代码段起始都基于状态S0,如非特别情况,S0就不特别标出。另外我们需要去掉中间状态,而中间状态在turing机中意味着顺序和选择关系,顺序关系我们用*表示,选择关系用+。*操作如无异议可以省略,这样做的目的是便于路径计算。process + 调整后的代码如下:
R(r1) ← m(+=,→→) + m(++,→→) + m(+,→);
现在代码看起来就简洁多了,继续简化就有点像上下文文法,但有一点请记住,这是语言而不是数据。上面的R和m本身有一定含义,如要执行,也便于宏操作。下面的代码我们增加了一些,也可以说是一些规则。借用函数式的概念,这些规则我们称之抽象。
//@抽象:定义规则 R(r1) ← m(+=,→→) + m(++,→→) + m(+,→); R(r2) ← m(-=,→→) + m(--,→→) + m(-,→); R(r3) ← m(*=,→→) + m(*,→); R(r4) ← m(/,→) * (m(/,→) * m(≠[\n],→,*) + m(*,→)*m(≠*/,→,*) + m(=,→)+ m()); R(r5) ← m(<=,→→) + m(<<=,→→→)+ m(<<,→→) + m(<,→); R(r6) ← m(>=,→→) + m(>>=,→→→)+ m(>>,→→) + m(>,→); R(r7) ← m(|=,→→) + m(||,→→)+ m(|,→); R(r8) ← m(&=,→→) + m(&&,→→)+ m(&,→); R(r9) ← m([a-zA-Z_],→) + m([a-zA-Z_0-9],→,*); //处理数字 R(r10) ← m([1-9],→) * m(m(. ,→) * m([0-9],→,*) * m(m([eE],→)*(m([+-],→),m())*m([0-9],→,+) + m()),m()); R(r11,s0→sx) ← m(0,→); R(r12,sx→s0) ← m([xX],→)*([0-9A-Fa-f],→,4) + R(r10);
在上面,我们定义了一些turing规则。现在我编写一些组合规则。假设我们有三种语言,分别叫L1、L2、L3,分别采用上面的一些规则,也可以增加自定义的一些规则,下面是示意。
R(L1) ← R(r1)+R(r2)+R(r3); R(L2) ← R(r1)+R(r7)+R(r8)+R(r5); R(L3) ← R(r1)+R(r2)+R(r3)+R(r6)+R(r7);
现在可以应用这些代码来构建turing机,代码如下:
T(sym.L1)← R(L1);
T(sym.L2)← R(L2);
T(sym.L3)← R(L3);
至此,我们完成了turing机构建的示意。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步