php 实现 lisp解释器,Lisp 解释器的实现

解释器是一种复杂有用的工具,用到了很多技能。

由于 Lisp 简单优雅的设计,让 Lisp 解释器的设计成为一种每个程序员都有能力尝试的挑战。

没有复杂的形式化语法。解释器的每一个部分都向程序员开放,代码和数据结构的统一,读取期,编译期和运行期的分离,让这门语言的扩展能力无以伦比,达到了理论上能想象的任何程度。

读取期

只有几个字符的读取会产生不同的状态。括号,空格,单引号,双引号,反引号,井号,分号,反斜杠,逗号,冒号。

( 左括号标志一个列表的开始,) 右括号标志一个列表的结束。

(setq var 10)

空格分离两个不同的语言单位,可以是字符串,也可以数字,符号,keyword 等

(if nil 1 0)

单引号是 (quote xx) 的缩写,算是一个语法上的简写。

'(1 2 3) == (quote 1 2 3) == (list 1 2 3)

双引号开始一个字符串,也结束一个字符串。

(print "hello world!")

反引号是另外一种 (quote xx) 的缩写,其中的一些符号会有特别的意义,例如逗号代表一个列表模板中的变量插入,,@(逗号加小老鼠)代表对一个内插列表的展开。

`(print ,var ,@list 10)

井号(或问号)通常开始一个字符,或一个特别的数据结构,例如多维数组或一个函数的解引用。

#\a #2(1 2 3)

冒号开始一个关键字,这个关键字类似 Ruby 的符号,是一种自身求值的字符串表示方法而已,用于做函数参数的键指示,是一种在数据结构上快速的字符串实现。

(defun (:from x :end y) (print '(x y))

反斜杠通常对后面的字符串进行转义,代表一些特别的字符,

分号是注释的开始标记,到每行的结束,除了 Scheme,没有多行注释的起始标记,需要每行都进行注释标记。

;; This is comments

还有一些符号,是在进入一个状态后才会有效。

最多的就是字符串,进入字符串模式后,有格式化标记,%(emacs lisp), ~ (common lisp). 还有转义标记 \ 来表示不能打印或显示的字符。在 Common Lisp 中,井号之后的反斜杠代表一个字符的开始。还有关于正则表达式一些特别字符的标记,和字符串是不同的。在不同的上下文中。正则表达式和字符串是不同的类型,虽然语法相同,都是用双引号界定的。

(format t "%times" time)

进入符号定义后,允许的字符是很多的,通常用一些字符做后缀来表示一些特定的命名规则,例如叹号结尾表示有副作用,问号结尾表示返回一个真假值。

(symbol? var) => t

(set! var 10)

读取到的数据结构可以是嵌套的。所有的数据类型都是动态的,用一个符号表示。

只有一种或两种数据结构,就是列表或向量,也可以抽象成一个序列。

同时建立了好几个数据结构,来维护生成的代表代码的树形数据结构。

数字表,所有的数字,都用一个数字 ID 来表示一个数字。

关键字表,这个表是全局共享的,键和值内容相同。

符号表,每个符号都用 name 映射一个字符串名字,用 value 映射一个值,这个值可能是一个数据结构, plist 映射一个属性表,是一个嵌套的查询表,也是用字符串做键,用一个对象或原子类型做值。函数也可能是一个单独的键来定义,也可能定义在 value 中。

保存局部变量的一个符号表列表,不同深度的列表,有不同的局部符号表。

编译期:

扫描数据结构中每个列表的第一个符号,判断是否是一个用 defmacro 定义的宏,如果是,就按照定义的规则,将这个列表进行转换,并替换掉原来的数据结构。这个扫描是反复进行的,直到找不到符合条件的宏的定义。

运行期

递归的,深度优先的对列表或符号进行解释,自身求值的返回自身,列表结构就把第一个符号当成函数名称,后面的当成参数,进行运算。返回计算的值或是一个数据结构。

在读取期,一些实现允许对读取的规则进行动态定义,改变一些字符的含义,是读取期的读取期。

在编译期和运行期,宏或函数都可能会返回值或返回一个数据结构,而这个数据结构,就会替换掉原来的表达式,成为新的将要计算的表达式。尤其编译期的这种扩展,可以任意改变数据结构,在文法上对代码进行扩展,实现一定范围甚至是全局的代码变更和重写,将抽象实现到代码的形式上,实现文法和算法的多重转换。

许多自称是 Lisp 方言的语言,在这点上,由于太多分化的语法,很难将代码表现成一种和数据统一的数据结构,从而实现对代码的重写成为泡影。所以,在语法上追求的各种不同的形式,将会让解析后的数据结构丧失重写代码的能力,算是一个平衡吧。

Lisp 虽然在很多表现形式上笨拙,难看,但他的这种扩展性让他有能力担当任何形式的抽象语言的进化和表示。成为永不过时的语言。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值