標籤:

如何寫 Lisp 解釋器?

關於代碼的話我搜到了兩個例子

http://blog.csdn.net/sedgewick/article/details/5928653

http://www.googies.info/articles/lispy.html

但具體說, 寫一個解釋器應該怎樣考慮呢?


function interpret(form, env, ctx){
if(form instanceof Array){
switch(form[0]){
case "lambda": {
var params = form[1];
var body = form[2];
return ctx(function(ctx){ return function() {
var e = Object.create(env);
for(var j = 0; j &< params.length; j++) e[params[j]] = arguments[j]; return interpret(body, e, ctx) }}) }; case "if": { var test = form[1], consequent = form[2], alternate = form[3]; return interpret(form[1], env, function(c){ if(c) return interpret(consequent, env, ctx) else return interpret(alternate, env, ctx) }) }; case "callcc": { return interpret(form[1], env, function(f){ var fctx = function(){ return function(x){ return ctx(x) }}; return f(fctx)(fctx) }) }; case "quote": { return ctx(form[1]) }; default: { return interpretCall(form, env, ctx); }; } } else if(typeof form === "string") { return ctx(env[form]) } else { return ctx(form) } } function interpretCall(form, env, ctx){ return interpret(form[0], env, function(callee){ return interpret$(form.slice(1), env, function(args){ return callee(ctx).apply(null, args) }) }) } function interpret$(form, env, ctx){ if(!form.length) return ctx(null); else return interpret(form[0], env, function(x0){ return interpret$(form.slice(1), env, function(x$){ if(x$) return ctx([x0]) else return ctx([x0].concat(x$)) }) }) } function id(x){ return x } var env0 = { trace: function(ctx){ return function(x) { return ctx(console.log(x)) }}}; interpret(["trace", ["callcc", ["lambda", ["return"], ["return", ["quote", 3]]]]], env0, id);

因為之前有人說我偷懶沒做 call/cc,今天我就做它一回。全文按照 Danvy 他們的抽象解釋模式寫成,顯式傳遞 Continuation。

下面是個混淆版 :)

function $(C,E,K){if(!(C instanceof Array))return K("string"==typeof C?
E[C]:C);switch(C[0]){case"lambda":return K(function(K){return function(
){for(var e=Object.create(E),u=0;u&


如果想完整理解建議閱讀SICP第4章,以及MIT配套的視頻和講義

整體來說,你需要考慮以下幾個方面(你可以對照著看一下你給的第二個鏈接中的文章,我覺得Peter Norvig已經描述的很清楚了):

1,詞法分析器(lexical analyzer),即將程序分解為一個個詞法單位,例如「(+ 5 a)」字元串,分解為["+", 5, "a"]。

2,語法分析器(Parser),就是把上面的結果構造成一顆語法樹,即

"+"

/

5 "a"

3,求值器(Ealuator),通常求值器還需要一個環境參數,然後計算上述語法樹在該環境下的值。例如,假設此時求值環境為{"+": &, "a": 2},在上述語法樹的值為7。

4,列印程序(Printer),就是把上步中得到的值先轉換為字元串,再列印出來,我們的例子比較簡單,結果就是7。


Contents ? Build Your Own Lisp


王垠這篇還是寫的不錯的 ---- 怎樣寫一個解釋器

還有就是sicp的第四章了


只是寫一個簡單解釋器的話:

1. 王垠大神的一篇簡潔易懂的博客

2. 還有下面兩篇用python實現的一個例子:(非常容易上手)

(How to Write a (Lisp) Interpreter (in Python))

(An ((Even Better) Lisp) Interpreter (in Python))

上面的文章都介紹了每個特性的考慮方式,應該比較符合題主需求。


以前很傻很天真地寫過一個,放在了Google Code上面。當時的思路是這樣子的,一開始只是想寫一個程序來從標準輸入讀取廣義表,然後生成內部的鏈表形式的廣義表,再調用一個函數將其以相對美觀的形式輸出來。當我完成了第一步之後,就發現既然可以生成廣義表了,那麼其實剩下的工作,就是解析廣義表並將其作為一個表達式進行求值而已了。沒有任何經驗,光聽別人講的話,肯定是不能理解別人的話的,既然如此,lz倒不如從自己認為是``正確""的地方著手,然後一步步地做出來一個呢。


sicp解釋器注釋版

http://zhuanlan.zhihu.com/p/20740190


Write Yourself a Scheme in 48 Hours


推薦一篇文章:The Root of LISP


推薦閱讀:

一個編程語言能否成功的關鍵之處?
Lisp可以完成哪些其它語言難以實現的功能?最好能夠舉一些例子
函數式語言中如何實現while true?
學習 LISP 有哪些網站或書籍推薦?
如何評價 Racket 這門編程語言?

TAG:解釋器 | Lisp |