这是一系列关于 如何实现编程语言 的教程。如果你曾经写过一个解释器或编译器,那么这里可能没有什么新东西。但是,如果您使用正则表达式来“解析” 任何看起来像编程语言的东西,那么请至少阅读解析部分。让我们写出更少的错误代码!
目标受众是普通的 JavaScript / NodeJS 程序员。
我们要学什么?
- 什么是解析器,以及如何编写解析器。
- 如何编写解释器。
- 为什么它们很重要。
- 编写一个编译器。
- 如何将代码转换为延续传递样式。
- 一些基本的优化技术。
在两者之间,我会争论为什么 Lisp 是一种优秀的编程语言。 但是,我们将要使用的语言不是 Lisp。它有一个更丰富的语法(每个人都知道的经典中缀符号),除宏之外,它的功能与 Scheme相当。
可悲的是,宏是 Lisp 的最终堡垒,其他语言无法克服(除非它们被称为 Lisp 方言)。
首先,让我们想想我们的要实现的编程语言应该是什么样子。
我们应该想清楚自己想要实现的目标。把语法的严格描述放在一起是一个好主意,但是我会在本教程中使语法更加简单,下面的示例就是我们要实现 “λ” 语言:
# this is a comment
println("Hello World!");
println(2 + 3 * 4);
# functions are introduced with `lambda` or `λ`
fib = lambda (n) if n < 2 then n else fib(n - 1) + fib(n - 2);
println(fib(15));
print-range = λ(a, b) # `λ` is synonym to `lambda`
if a <= b then { # `then` here is optional as you can see below
print(a);
if a + 1 <= b {
print(", ");
print-range(a + 1, b);
} else println(""); # newline
};
print-range(1, 5);
请注意,标识符名称可以包含负号字符(print-range)。这是个人品味的问题:我总是在操作符旁边放置空格,我不喜欢太多的 camelCaseNames,而且我觉得短划线比下划线更好。编写自己的语言的好处是,你可以随心所欲地做到这一点。:)
输出是:
Hello World!
14
610
1, 2, 3, 4, 5
Read More