lisp是一门简单又强大的语言,其语法极其简单:
(+ 1 2 )
上面的意思 是:+是方法或函数,1 ,2 是参数,fn=1+2,即对1,2进行相加求值,结果是:3
双括号用来提醒解释器开始和结束。
之前在iteye写过一篇文章来简单介绍怎么写lisp的解释器:
http://gyc567.iteye.com/blog/2242960
同时也画了一张草图来说明:
因为lexer(词法分析器)主要工作就是把程序的字符串表达式转化为tokens.(Pair),以下是百科对词法分析的说明:
词法分析是编译过程的第一个阶段,是编译的基础。这个阶段的任务是从左到右一个字符一个字符地读入源程序,即对构成源程序的字符流进行扫描然后根据构词规则识别单词(也称单词符号或符号)。
因为lisp的语法极其简单,词法分析可以认为就是把字符串“(+ 1 2 )”转化为Pair对象,这个Pair 有两个属性:first,rest,first用来记录“+”,rest用来记录另一个Pair,如下图:
Pair1 :
first-->"+"
rest-->Pair2
Pair2:
first-->"1"
rest-->"2"
所以这里主要关注parser,parser主要工作是把Pair对象转化为抽象语法树(AST),并对其他求值返回。
好,现在尝试用BDD的方式来开发实现parser的功能。
先写测试用例:
package com.github.eric.camel import spock.lang.Specification /**
* Created by eric567 on 4/4/2016.
*/
class LispSpockTest extends Specification {
def "Caculate"() {
given:"a instance of Lisp,args: 1 2 "
Lisp lisp=new Lisp()
int arg1=1
int arg2=2
when:"invoke lisp method caculate "
int rt=lisp.caculate(arg1,arg2)
then:"return the result :3"
rt==3 } def "Eval"() {
given:"new Lisp instance,Pair1:fisrt-->+,rest-->Pair2;Pair2:first-->1,rest-->2"
Lisp lisp=new Lisp() ValuePair valuePair2=new ValuePair()
valuePair2.first="1"
valuePair2.rest="2"
ValuePair valuePair1=new ValuePair()
valuePair1.first="+"
valuePair1.rest=valuePair2 when:"eval the Pair1"
Object rt=lisp.eval(valuePair1)
then:"the result should be :3 "
Integer.valueOf(rt)==3 }
}
第一个测试用例用来 测试caculate方法,也这里就是简单的相加功能。代码已经说明一切。
第二个测试用来测试eval求值函数。
好,现在写代码通过这两个测试:
package com.github.eric.camel; /**
* Created by eric567 on 3/8/2016.
*/
public class Lisp {
public int caculate(int i, int i1) {
return i+i1;
} public Object eval(ValuePair valuePair)
{
String fn= (String) valuePair.first;
if(fn!=null&&fn.equals("+"))
{
ValuePair args= (ValuePair) valuePair.rest;
int arg1= Integer.valueOf((String) args.first);
int arg2= Integer.valueOf((String) args.rest);
Integer rt=caculate(arg1,arg2);
return rt;
}
return null;
}
} 而Pair对象的代码很简单:
package com.github.eric.camel; /**
* Created by eric567 on 3/8/2016.
*/ public class ValuePair {
Object first;
Object rest; }
好,再次运行测试用例,应该可以出现绿色线条,祝贺你,你已经实现了一个简单的lisp解释器,you got it .cheeers.