首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

如何手写一个简单的解释器

“如果你不知道compiler是怎么工作的,那么你就不会清楚计算机是怎么工作的。如果你不是100%的确定地知道‘你知道compiler是怎么工作的’,那么你肯定不知道它们是怎么工作的。”——Steven Yegge

别着急,试着跟我读完整个教程,最终你会学会怎么写interpreter和compiler的。并且你一定会变得自信,至少我希望如此。为什么要学习这些呢?我给三个理由你听听。

为了写成一个interpreter或者compiler,你必须学习相当多的技术和技巧,而且会综合运用。这些工作会让你更善于使用这些技术,变成一个更好的码农。同时,你得到的是如何开发好一个软件,而不仅仅是interpreter和compiler。

你会真切地想知道计算机内部是怎么工作的。通常人们都认为interpreter和compiler像是魔法,并且你一定不习惯那个魔法。你会想解开魔法的帘子,去弄明白帘子里面是什么,它们是怎么控制这一切的。

或者你希望创造一个你自己的编程语言或者领域语言。如果你想这么做,那你就要为这个语言创建一个interpreter或者compiler。干这个事儿最近很流行,很多新语言层出不穷,比如Elixir、Go、Rust,还有好多。

OK,那什么是interpreter和compiler呢?

Interpreter或者compiler的目标是吧源程序翻译成某些高层语言的形式。听起来好像没有说,是吗?相信我,看完这些文章你会弄明白源程序到底被转化成了什么东西。

看到这里,你可能心生疑问:interpreter和compiler区别在哪儿?看下图吧。compiler是源程序转换成了机器语言,而interpreter不转换。

来,我们动手,写一个Pascal语言的interpreter。为了简单,我们选择用python来写。

下面是一个经典的阶乘运算的Pascal程序。

直接写好一个interpreter不太现实。下面我们用python先写一个开头,加法计算器。够简单吧?

运行一下:

为了让这个简单到不能再简单的interpreter正常工作,不出现异常。你必须保证:

只输入简单的整数数字

只使用加法操作

没有空白字符

当你输入3+5的时候,你的interpreter得到了一个字符串“3+5”。为了让interpreter真真的理解要干什么,它首先就要分解这个“3+5”串,编程一系列的tokens。Token是一个物体,它包含类型和数值。比如,“3”这个字符串,它对应的token的类型就是INTEGER,数值是整数3。

把串拆分为tokens的过程叫词法分析,完成这个过程的工具叫词法分析器,或者扫描器。它把你的一串输入数字转换成了一个长长的token串。

get_next_token是Interpreterpython类的一个方法,他就是词法分析器。每次调用它的时候,你就能得到输入串的下一个token。 仔细看看,输入的字符串是放在变量text中的,text中除了有输入串,还有一个pos代表输入串的索引。pos初始值为0,指向“3”。这个方法首先检查第一个字符是不是数字。如果是数字,方法就增加pos并返回一个整形3的token。

现在,pos指向了text中的‘+’这个字符。下次再调用这个方法,它会检测到当前的符号不是数字,而是加号,于是返回一个PLUS+的token。

类似3的处理,5也会处理好。方法返回整形5这个token。

pos现在来到了EOF,代表输入串处理完毕,于是方法退出。

你可以用下面的交互式python执行方式,来验证一下整个过程:

结果是:token的序列为 INTEGER -> PLUS -> INTEGER。interpreter会知道,它要找的序列是:一个整数加上另一个整数。负责找这个序列的方法是expr。它会验证一下序列是否合法,该找的数字有没有错位。一切正常的情况下,它会成功执行出结果。

expr方法使用 helper 方法来eattoken,从而来来验证一个个的current_token指向的字符。出现异常的话就抛出来。

祝贺你,完成了你的第一个简单的interpreter!

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20190103G1IJDM00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券