[编译原理]用BDD方式开发lisp解释器(编译器)|开发语言java|Groovy|Spock

lisp是一门简单又强大的语言,其语法极其简单:

(+ 1 2 )

上面的意思 是:+是方法或函数,1 ,2 是参数,fn=1+2,即对1,2进行相加求值,结果是:3

双括号用来提醒解释器开始和结束。

之前在iteye写过一篇文章来简单介绍怎么写lisp的解释器:

http://gyc567.iteye.com/blog/2242960

同时也画了一张草图来说明:

image

因为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的功能。

先写测试用例:

<pre>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

}

} </pre>

第一个测试用例用来 测试caculate方法,也这里就是简单的相加功能。代码已经说明一切。

第二个测试用来测试eval求值函数。

好,现在写代码通过这两个测试:

<pre>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对象的代码很简单: </pre>

<pre>package com.github.eric.camel;

/**

  • Created by eric567 on 3/8/2016.

    */

    public class ValuePair {

    Object first;

    Object rest;

    } </pre>

<pre> 好,再次运行测试用例,应该可以出现绿色线条,祝贺你,你已经实现了一个简单的lisp解释器,you got it .cheeers. </pre>

本人精通java高并发,DDD,微服务等技术实践,以及python,golang技术栈。 本人姓名郭莹城,坐标深圳,前IBM架构师、咨询师、敏捷开发技术教练,前IBM区块链研究小组成员、十多年架构设计工作经验,《区块链核心技术与应用》作者之一, 现有成熟团队提供区块链开发相关业务(公链,交易所,钱包,Dapp,智能合约)。 工作微信&QQ:360369487,交易所开发与区块链钱包开发业务,加我注明:博客园+开发,想学习golang和rust的同学,也可以加我微信,备注:博客园+golang或博客园+rust,谢谢!

我来评几句
登录后评论

已发表评论数()

相关站点

热门文章