C++ 编写一个解释器

本项目基于C++17实现了一门名为Autumn的脚本语言,支持高阶函数、闭包及PrattParsing算法,可在Linux和Mac上运行。提供了map、filter、快速排序等实用示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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 被定位成函数式编程语言,所以不支持循环,不支持变量。
In this book we will create a programming language together. We'll start with 0 lines of code and end up with a fully working interpreter for the Monkey* programming language. Step by step. From tokens to output. All code shown and included. Fully tested. Buy this book to learn - How to build an interpreter for a C-like programming language from scratch - What a lexer, a parser and an Abstract Syntax Tree (AST) are and how to build your own - What closures are and how and why they work - What the Pratt parsing technique and a recursive descent parser is - What others talk about when they talk about built-in data structures - What REPL stands for and how to build one Why this book This is the book I wanted to have a year ago. This is the book I couldn't find. I wrote this book for you and me. So why should you buy it? What's different about it, compared to other interpreter or compiler literature? - Working code is the focus. Code is not just found in the appendix. Code is the main focus of this book. - It's small! It has around 200 pages of which a great deal are readable, syntax-highlighted, working code. - The code presented in the book is easy to understand, easy to extend, easy to maintain. - No 3rd party libraries! You're not left wondering: "But how does tool X do that?" We won't use a tool X. We only use the Go standard library and write everything ourselves. - Tests! The interpreter we build in the book is fully tested! Sometimes in TDD style, sometimes with the tests written after. You can easily run the tests to experiment with the interpreter and make changes. This book is for you if you... - learn by building, love to look under the hood - love programming and to program for the sake of learning and joy! - are interested in how your favorite, interpreted programming language works - never took a compiler course in college - want to get started with interpreters or compilers… - ... but don't want to work through a theory-heavy, 800 pages, 4 pounds co
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值