如何使用 Python 编写一个 Lisp 解释器
http://www.googies.info/articles/lispy.html
感觉是个不错的学习项目,没太看懂怎么用,python 不够熟悉。
补充:
代码来自谷歌的高人,Peter Norvig。 自顶向下地解释了 lisp 解释器。解释器分两部分,parse 和 run。 代码不长,但有些复杂,不是一下子能看懂。
代码分三部分:env, eval, parse, 比较复杂的是前两个部分,盒中盒的结构。
看了一下这个 似乎没实现什么复杂的功能。 反正先了解
对应这个例子里面,从 repl 开始 raw_input 得到用户输入类似 ruby 的 gets parse 里处理 tokenize 方法返回的 tokens,int 类型的转为 int,其他的都归为 symbol(字符串表示) read_from 这里就是 atom 直接返回,list 返回数组 最后交给 eval,数组第一个参数就是 if define lambda 这些 分情况处理就好了 还有个 Env 环境,这里用了个 dict 存变量赋值
rsec 是个 ruby 实现的 parser combinator library 是这么说来着吧(其实没用过)
嗯... 我的 rsec 自带了例子,84 行 (含空行和注释) ruby 实现的 scheme 解释器... https://github.com/luikore/rsec/blob/master/examples/scheme.rb
就是能跑 hello world 和处理 curry 的程度,很多基本函数都没加
parser generator 含义广泛,一种是静态的例如 bison 和 antlr, 编译生成源文件并且只用生成一次。另一种是动态的,例如 boost::spirit, 在运行时生成 parser. treetop 可以当静态的用也可以当动态的用。
parser combinator 是一种 parser generator, 区别是用组合的方式,而不是专门的语法定义... 像 haskell 的 parsec 就是 parser combinator.
代码来自谷歌的高人,Peter Norvig。 自顶向下地解释了 lisp 解释器。解释器分两部分,parse 和 run。 代码不长,但有些复杂,不是一下子能看懂。
antlr 接受的是 CFG 的子集,而 packrat parser 接受的是 PEG CFG 和 PEG 的区别是,CFG 的选择支是无序的,PEG 的选择支是有序的。
packrat 可以无限 lookahead. LL, LR, GLR 都只支持定长 lookahead, LL(3) 就表示最多 lookahead 3 个 token. 不过这个长度在 antlr 里是可以配置/检测的,所以叫 LL(*).
缩进敏感语法可以用 lexer 插入伪 token: indent
和 dedent
来解决。python 语法里的缩进就是这么预处理后交给 antlr 的。手写语法有一些好处,例如可以加入特殊的规则,优化性能,可以更自由的自定义错误报告之类的。官方 java 的语法就是手写的。但是对比较复杂的语法来说手写还是容易出错的,ruby 和 python 就没用手写法。
LL, LR, GLR 里面的第一个 L 都是废话 (left to right), 最后一个字母区别了 Leftmost derivation 和 Rightmost derivation.
LL 和 packrat parser 都不支持 left recursion (称作 ambiguity ignored, 也有一些实现改写了算法加入有限支持的).
LR 可以辨认的语法范围比 LL 大,支持 left recursion. GLR (generalized LR) 通过平行构造多个语法树,最终可以多消除一些歧义 (称作 ambiguity embraced). lookahead LR 的缩略写法是 LALR, 和 LL(k) 的写法略有区别。