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

如何使用 JavaScript 实现一门编程语言(1):前言

英文: Mihai Bazon 译文:阿安

annn.me/implement-a-programming-language/

这是一系列关于 如何实现编程语言 的教程。如果你曾经写过一个解释器或编译器,那么这里可能没有什么新东西。但是,如果您使用正则表达式来“解析” 任何看起来像编程语言的东西,那么请至少阅读解析部分。让我们写出更少的错误代码!

目标受众是普通的 JavaScript / NodeJS 程序员。

我们要学什么?

什么是解析器,以及如何编写解析器。

如何编写解释器。

为什么它们很重要。

编写一个编译器。

如何将代码转换为延续传递样式。

一些基本的优化技术。

在两者之间,我会争论为什么 Lisp 是一种优秀的编程语言。 但是,我们将要使用的语言不是 Lisp。它有一个更丰富的语法(每个人都知道的经典中缀符号),除宏之外,它的功能与 Scheme相当。

可悲的是,宏是 Lisp 的最终堡垒,其他语言无法克服(除非它们被称为 Lisp 方言)。

首先,让我们想想我们的要实现的编程语言应该是什么样子。

我们应该想清楚自己想要实现的目标。把语法的严格描述放在一起是一个好主意,但是我会在本教程中使语法更加简单,下面的示例就是我们要实现 “λ” 语言:

#thisisacomment

println("Hello World!");

println(2+3*4);

#functions are introducedwith`lambda`or`λ`

fib=lambda(n)ifn

println(fib(15));

print-range=λ(a,b)#`λ`issynonymto`lambda`

ifa

print(a);

print(", ");

print-range(a+1,b);

}elseprintln("");#newline

};

print-range(1,5);

请注意,标识符名称可以包含负号字符(print-range)。这是个人品味的问题:我总是在操作符旁边放置空格,我不喜欢太多的 camelCaseNames,而且我觉得短划线比下划线更好。编写自己的语言的好处是,你可以随心所欲地做到这一点。:)

输出是:

HelloWorld!

14

610

1,2,3,4,5

该语言看起来有点像 JavaScript,但它不同。首先,没有声明,只有表达式。表达式返回一个值,可以用来代替任何其他表达式。分号需要在“序列”中分隔表达式。花括号创建这样一个序列,它本身就是一个表达式。它的值是最后一个表达式返回的值。以下是一个有效的程序:

a={

fib(10);#has noside-effects,butit'scomputed anyway

fib(15)#the last semicolon can bemissing

};

print(a);#prints610

函数被引入其中一个关键字 lambda 或 λ(它们是同义词)。在关键字之后,必须有一个(可能为空的)用逗号分隔的变量名列表(可能为空),就像在 JavaScript 中一样 —— 这些是参数名称。函数体是一个单一的表达式,但它可以是一个包裹在{ … }中的序列。

没有 return 语句 – 在函数返回最后一个表达式给出的返回值。

没有 var。要引入新变量,可以使用 JSer 称之为 “立即执行函数” 的方式。就像在 JavaScript 中一样,使用 a lambda,声明变量作为参数。变量具有函数作用域范围,函数是闭包。

甚至 if 本身就是一种表达。在 JavaScript 中,您可以使用三元运算符获得该效果:

a=foo()?bar():baz();// JavaScript

a=iffoo()thenbar()elsebaz();#λanguage

当分支以一个花括号开始时, then 关键字是可选,你可以在 print-range 上面看到,否则它是必需的。

当替代分支存在时,else 关键字是必须的。再次,then 的 else 的分支主题为一个单一的表达式,但也可以花括号 “{}” 包含多个通过 “;” 分隔的表达式。

当 else 分支不存在并且 if 条件结果为 false,if 表达式的结果是 false。因此,false 是一个关键词,它表示我们的语言中唯一的 falsy 值:

if foo() then print("OK");

当 foo() 的结果不是 false 是,这点程序将会打印 “OK”。还有一个用于表示”真”的关键字 true,不是所非 false(当使用 JavaScript中 === 运算符的时候)的值都被理解成 true (其中包括数字 0 和空字符串 “”)。

还要注意,使用括号包裹 if 条件没有意义。不过,虽然它们是多余的,你添加它们也没有错误。

整个程序被解析,就好像它被嵌入大括号中一样,因此,除了最后一个表达式,您需要在每个表达式后面放置一个分号。

好了,这是就我们的小 λ 语言。它不一定是很完善的的。它的语法看起来很可爱,但也有陷阱。它有很多缺失的功能,如对象或数组; 我们并不关注这些缺失,因为对我们的旅程并不重要。只要你掌握了这个教程的所有内容,你可以轻松实现这些缺失的功能。

在下一节中, 我们将为这个语言编写一个解析器 。

觉得本文对你有帮助?请分享给更多人

关注「前端大全」,提升前端技能

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

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券