简单易懂的程序语言入门小册子(8):基于文本替换的解释器,小结
关于语法
我们现在用的这种充满括号和前缀表达式的语法叫做“S表达式”。 S表达式看似奇怪,其实是一种简约风格的语法。 S表达式的表达式一般是这么设计的: 首先第一个词表示这个表达式的类别(如if表达式还是let表达式), 然后后面依次列出这个表达式的所有元素, 最后用一对括号把整个表达式括起来。 比如if表达式有三个元素条件表达式和两个分支表达式,所以if表达式是(ifLMN); 加法则是一个加号后面跟上要相加的表达式:(+MN)。
与其说S表达式语法简单,不如说S表达式几乎没有语法。 S表达式的代码已经是一棵抽象语法树。 它的一个很明显的好处是解释器几乎不用做语法分析。 关于语法分析,编译原理课程已是阐之未尽,我也没什么可说的。 我想说的都是一些语义方面的内容,所以我希望尽量避免语法分析。 减掉一些东西意味着减少许多麻烦(位移归约冲突够玩一阵子了)。 语法分析有时候会出现一些意想不到的bug。 比如《UNIX痛恨者手册》里有个例子,假设p是C语言的一个指向浮点数的指针。 现在要计算*p的倒数,于是有这么一小段代码:
1 | 1 / * p |
嗯?
S表达式一直被诟病括号多。 其实许多人(这些人应该都没学过Lisp)不喜欢S表达式的原因不在于括号多,而是因为S表达式与C语言(或者JAVA、Python)“不够像”。
See you later, alligator
为了引用方便,应该给我们正在实现的这门语言起个名字,就叫Alligator吧。
Alligator的语法: M,N,L=X|b|λX.M|(fixX1X2M)|(+MN)|(−MN)|(iszeroM)|(MN)
值: V=X|b|λX.M
宏: (ifLMN)=(((LλX.M)λX.N)0)其中X∉FV(M),X∉FV(N)(letXNM)=(λX.MN)(letrecX1X2NM)=(λX1.M(fixX1X2N))
Alligator采用call-by-value的调用方式,它的求值过程如下(continuation passing): ⟨X,κ⟩v→v⟨X,κ⟩c⟨b,κ⟩v→v⟨b,κ⟩c⟨λX.M,κ⟩v→v⟨λX.M,κ⟩c⟨(fixX1X2M),κ⟩v→v⟨λX2.M[X1←(fixX1X2M)],κ⟩c⟨(onM1M2...Mn),κ⟩v→v⟨M1,⟨opd,κ,on,(M2...Mn),()⟩⟩v⟨V,⟨opd,κ,on,(Mi+1...Mn),(V1...Vi−1)⟩⟩c→c⟨Mi+1,⟨opd,κ,on,(...Mn),(V1...Vi−1V)⟩⟩v⟨V,⟨opd,κ,on,(),(V1...Vn−1)⟩⟩c→c⟨V′,κ⟩c其中V′=on(V1,...,Vn−1,V)⟨(MN),κ⟩v→v⟨M,⟨arg,κ,N⟩⟩v⟨V,⟨arg,κ,N⟩⟩c→c⟨N,⟨fun,κ,V⟩⟩v⟨V,⟨fun,κ,λX.L⟩⟩c→c⟨L[X←V],κ⟩v
===我是穿越的分割线================================================
由于写解释器太欢乐了,所以我不知不觉就把Alligator写到这个系列大约三分之二的进度。下面链接是Alligator解释器的代码:
https://github.com/sKabYY/Alligator
这个Alligator包含多参数函数、互递归、赋值、垃圾回收、letcc与cc、异常处理等新功能。
testcases.rkt是测试用的例子。运行alligator.rkt文件会测试testcases.rkt里的例子。
1 | racket alligator.rkt |
alligator-cps.rkt对Alligator做了CPS变换和一些简单的CPS代码优化。一个很有意思的地方是做完CPS变换后,一些语句如异常处理就消失了。CPS代码优化写得比较乱,做了beta展开、eta归约和常数折叠三个优化。是处于试验阶段的代码,都是拍脑袋就写的,估计bug比较多。运行alligator-cps.rkt文件会测试testcases.rkt里的例子。
1 | racket alligator-cps.rkt |
输出比较多,可能需要重定向到文件再看。
长路漫漫
本来只想打发郁闷的时间而随便写写。现在发现写文章不仅能改善心情,对加深理解也有好处。我把后面想写的内容列下了,以激励自己。
- 基于文本替换的解释器。
- 环境。引入环境,CEK,作用域(静态,动态),SECD,无名变量,加入多参数。
- 状态。显式引用,隐式引用,垃圾回收,按需传值,按引用传值。
- Continuation。letcc与cc,异常处理,多线程。
- CPS变换,CPS代码优化?
- 类型系统……(待定)
- 面向对象……(待定)
程序语言这领域我才刚跨过半条腿,如有谬误,欢迎斧正。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人