0 前言

一直想知道如何编写一门脚本语言,现在终于有机会实现了。非常感谢 Thorsten Ball 的大作:Writing An Interpreter In Go 帮助我实现了这个想法!

Go 是一门非常不错的语言,但是为了锻炼一下自己,使用 C++ 实现了书中的想法,项目地址:https://github.com/ivanallen/autumn。

可能你比较好奇为啥这个项目叫 Autumn,因为刚好这个项目是在国庆节开始的,正好是秋天,就以当时的季节命名了。

C++ 是一门非常灵活的语言,正好趁这个小项目,我可以天马行空的实现我的各种想法,应用到工程里。

1 特性

  • 基于 C++ 17 语法实现。如果可能的话,我希望我能用上 C++ 20. 仅管目前用到的新特性不是很多,但我希望有些地方,能使用新特性来实现。或许你对新特性更加熟悉。
  • 平台:当然是 Linux 和 Mac 都支持啦!(为什么不支持 Windows ? 求大神提 PR 改造!)
  • 完善的注释。抱歉,我撒谎了,后面我一定会补上!
  • 完善的 Debug 能力。是的,编写 Pratt Parsing 算法是个挑战,理解它如何工作也是一个挑战。你不可能通过 gdb 一行一行去调试。Autumn 项目希望能在 Debug 能力上帮助你理解 Pratt Parsing. 下面是一张截图。

  • 高阶函数的支持

  • 闭包支持

是的,你还可以做的更多!

2 快速开发

  • 第一步当然是 fork & clone 这个项目到你的 Mac 或者 Linux 系统的主机上。
  • GCC8 安装

因为这个项目用到了一些 C++17 的特性,所以你得安装支持 C++17 的编译器,这里直接升级到 GCC8 就行了。

# CentOS
$ yum install readline-devel.x86_64
$ yum install -y devtoolset-8-toolchain
$ scl enable devtoolset-8 bash# Ubuntu
$ sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
$ sudo apt-get update -qq
$ sudo apt-get install -qq g++-8
$ apt-get install lib64readline-dev
$ export CXX="g++-8"
$ export CC="gcc-8"
  • 编译
$ make
  • 进入解释器
$ ./autumn eval

然后你就可以在控制台编写一些命令或函数啦!

3 一些酷炫的例子

3.1 map

let map = fn(arr, f) {let iter = fn(arr, accumulated) {if (len(arr) == 0) {accumulated} else {iter(rest(arr), push(accumulated, f(first(arr))));}};iter(arr, []);
};// 压缩成一行的
let map = fn(arr, f) { let iter = fn(arr, accumulated) { if (len(arr) == 0) { accumulated } else { iter(rest(arr), push(accumulated, f(first(arr)))); }}; iter(arr, []);};
  • 数组元素 double
let a = [1,2,3,4]
let double = fn(x) { x * 2 };
map(a, double)

3.2 filter

let filter = fn(arr, f) {let iter = fn(arr, accumulated) {if (len(arr) == 0) {accumulated} else {let e = if (f(first(arr))) {push(accumulated, first(arr));} else {accumulated}iter(rest(arr), e);}};iter(arr, []);
};// 压缩成一行的
let filter = fn(arr, f) { let iter = fn(arr, accumulated) { if (len(arr) == 0) { accumulated } else { let e = if (f(first(arr))) { push(accumulated, first(arr)); } else { accumulated } iter(rest(arr), e); }}; iter(arr, []);};
  • 找到小于 4 的元素
let a = [1,5,3,6,3,8]
let lessThanFour = fn(x) { x < 4 }
filter(a, lessThanFour)

  • 快速排序
let quickSort = fn(arr) {if (len(arr) == 0) {return arr;} else {let head = first(arr);let smaller = filter(rest(arr), fn(x) { x <= head });let bigger = filter(rest(arr), fn(x) { x > head });return quickSort(smaller) + [head] + quickSort(bigger);}
}// 一行版本
let quickSort = fn(arr) {if (len(arr) == 0) {return arr;} else {let head = first(arr);let smaller = filter(rest(arr), fn(x) { x <= head });let bigger = filter(rest(arr), fn(x) { x > head });return quickSort(smaller) + [head] + quickSort(bigger);}}

4 尚未被支持的

  • if … else if 结构(目前只支持了 if … else)
  • 更多的内建函数 (目前实现了 len 函数等)
  • 能像 Python 那样从文件读取代码执行
  • ……

5 Q&A

  • Q: 为什么不支持循环呢?
  • A: autumn 被定位成函数式编程语言,所以不支持循环,不支持变量。

C++ 编写一个解释器相关推荐

  1. 用 C 语言编写一个简单的垃圾回收器

    人们似乎认为编写垃圾回收机制是很难的,是一种只有少数智者和Hans Boehm(et al)才能理解的高深魔法.我认为编写垃圾回收最难的地方就是内存分配,这和阅读K&R所写的malloc样例难 ...

  2. 每日一课 | 如何用Python编写一个Lisp解释器

    作者 | Peter Norvig 译者 | Tianyu 编辑 | Freesia 出品 | Python大本营(ID: pythonnews) 今日知识点  前言 || 展示如何实现一个计算机语言 ...

  3. 如何用Python编写一个Lisp解释器

    作者 | Peter Norvig 译者 | Tianyu 编辑 | Freesia 来源 | Python大本营(ID: pythonnews) 这篇文章有两个目的:一是展示如何实现一个计算机语言的 ...

  4. 从编译原理看一个解释器的实现

    『设计模式』中有一个模式可以解释特定的语法规则,它就是解释器模式(Interpreter Pattern).不同于常见的策略模式或者是工厂模式,解释器模式在.NET或者JDK中并不常见,而且在业务上也 ...

  5. 【译】使用 Python 编写虚拟机解释器

    2019独角兽企业重金招聘Python工程师标准>>> #[译]如何使用 Python 创建一个虚拟机解释器? 原文地址:Making a simple VM interpreter ...

  6. python hello world程序编写_用Python编写一个简单程序

    按照软件行业传统习惯,当你学习一种新的编程语言如Python时,首先编写一个"Hello World! "程序. 请执行以下步骤,以创造你的"Hello World!&q ...

  7. python源文件改写编写一个程序读取一个python源程序文件_学PYTHON第三节:编译和解释...

    计算机执行源程序的两种方式:编译和解释 首先,了解一下静态语言,动态语言,目标代码,源代码. 动态类型语言(又称为脚本语言或扩建语言):在运行期进行类型检查的语言,也就是在编写代码的时候可以不指定变量 ...

  8. linux系统写一个脚本,编写一个简单的linuxshell脚本

    shell脚本和windows平台上的bat批处理是一样的,简化用户处理重复动作的操作,shell脚本由shell命令组成.下面是学习啦小编收集整理的编写一个简单的linuxshell脚本,希望对大家 ...

  9. 如何用FFmpeg编写一个简单播放器详细步骤介绍

    如何用FFmpeg编写一个简单播放器详细步骤介绍(转载) FFMPEG是一个很好的库,可以用来创建视频应用或者生成特定的工具.FFMPEG几乎为你把所有的繁重工作都做了,比如解码.编码.复用和解复用. ...

  10. 用 Javascript 编写λ演算解释器

    本文讲的是用 Javascript 编写λ演算解释器, 最近,我在推特上对λ演算非常着迷,它是如此简单和强大. 当然我之前听说过λ演算,但是直到我读了这本书 Types and Programming ...

最新文章

  1. Windows2008防火墙封ip
  2. Linux常用命令笔记---故障排除
  3. 推荐一个wpfsliverlight的图表控件
  4. linkedhashmap遍历_Java集合:浅谈LinkedHashMap、LinkedHashSet源码及LRU算法实现
  5. 环回测试能够提供什么信息_VIAVI | 全面对比“真双向分析”与“环回测试”,结果一目了然!...
  6. Eclipse单行和多行注释快捷键以及撤销注释
  7. 苹果回应大数据杀熟:罪在开发者,和苹果没关系!
  8. mysql 截取json字符串_mysql如何截取一个json字符串?
  9. 【洛谷P2872】道路建设(最小生成树prim/kruskal)
  10. 镜像文件下载及VM部署win xp 保姆级教程
  11. Djangobook
  12. 车架号OCR识别算法
  13. Pr cc 2019 v13.0 添加字幕文本不显示,输入字符后无选中框解决方案
  14. ulp(unit in the last place)是什么意思
  15. 智能时尚:人工智能在时尚服装行业的应用综述 | 580+参考文献
  16. 网站中木马病毒了怎么办
  17. 长安大学转计算机专业,长安大学本科学生转换专业管理办法
  18. scratch设计跑酷游戏_我如何使用Scratch设计游戏
  19. 用无线网卡做wifi热点共享网络的方法
  20. PyCharm 中的 ___jb_bak___ 和 ___jb_old___ 文件的处理方法

热门文章

  1. 鸿蒙pc系统镜像,鸿蒙系统有pc版么_鸿蒙系统有pc版安装方法
  2. linux下装go环境
  3. 课堂派微信端重设计建议
  4. java pdf打印解决方案,将pdf转为图片进行打印
  5. 攻防世界misc 如来十三掌
  6. nodejs 运行后报错 Error: Couldn‘t find preset “es2015“ relative to directory
  7. 密码学RSA解密之Pollard_rho分解
  8. linux mysql统计次数_按条件计数 - MySQL统计函数记录_数据库技术_Linux公社-Linux系统门户网站...
  9. Qt获取IE地址栏内容
  10. RabbitMQ-基础(二)