这是用于正在编写的书“Crafting Interpreters”的存储库。它包含本书的 Markdown 文本、两个解释器的完整实现,以及将两者编织在一起形成最终站点的构建系统。
如果您发现错误或有建议,请在此处提出问题。谢谢你!
在网上写一本书并在完成之前将其发布出去的绝对最好的事情之一就是像你这样的人很友善地给我反馈,指出错别字,并发现其他错误或不清楚的文字。
如果您愿意这样做,那就太好了!您可以在存储库上提交错误,或者如果您愿意的话可以发送拉取请求。如果您想发送拉取请求,但又不想将构建系统设置为重新生成 HTML,请不要担心。当我把它拉进去时我会这样做。
另一种参与方式是分享您自己的 Lox 实现。移植到其他语言特别有用,因为并非每个读者都喜欢 Java 和 C。请随意将您的 Lox 移植或实现添加到 wiki:
我是一种非常健忘、容易出错的哺乳动物,所以我尽可能地实现自动化。
我在 OS X 机器上进行开发,但任何 POSIX 系统也应该可以工作。通过一些额外的努力,您应该也能够在 Windows 上运行它,尽管我帮不了您太多。
大部分工作都是由 make 精心策划的。构建脚本、测试运行器和其他实用程序都是用 Dart 编写的。安装 Dart 的说明在这里。安装 Dart 并在路径上后,运行:
$ make get
这将下载构建和测试脚本使用的所有包。
为了编译这两个解释器,您的路径上还需要一个 C 编译器以及javac
。
一旦你完成了设置,请尝试:
$ make
如果一切正常,将会生成本书的站点并编译两个解释器 clox 和 jlox。您可以直接从存储库的根目录运行任一解释器:
$ ./clox
$ ./jlox
使用手写的静态站点生成器将 Markdown 和源代码片段编织到最终的 HTML 中,该生成器最初是我第一本书的一个小型 Python 脚本,后来以某种方式成长为接近真实程序的东西。
生成的 HTML 提交到site/
下的存储库中。它是由 Markdown 散文(位于book/
中)和从java/
和c/
中的 Java 和 C 实现编织而成的代码片段组合而成。 (源代码中所有那些看起来很有趣的注释都是它如何知道哪个片段去哪里的。)
完成所有魔法的脚本是tool/bin/build.dart
。您可以直接运行它,或者运行:
$ make book
这会批量生成整个站点。如果您正在逐步开发它,您将需要运行开发服务器:
$ make serve
这会在以site/
目录为根的本地主机上运行一个小型 HTTP 服务器。每当您请求页面时,它都会重新生成源已更改的所有文件,包括 Markdown 文件、解释器源文件、模板和资产。只需让它继续运行,在本地编辑文件,然后刷新浏览器即可查看更改。
您可以像这样构建每个解释器:
$ make clox
$ make jlox
这构建了每个解释器的最终版本,因为它出现在书中该部分的末尾。
您还可以在每章末尾看到口译员的样子。 (我用它来确保它们即使在本书的中间也能正常工作。)这是由脚本tool/bin/split_chapters.dart
驱动的,该脚本对代码片段使用相同的注释标记来确定哪些代码块是出现在每一章中。它只需要每章末尾看到的代码片段,并在gen/
中生成源代码的新副本,这是每章代码的一个目录。 (这些也是查看源代码的更简单方法,因为它们删除了所有分散注意力的标记注释。)
然后,每个都可以单独构建。跑步:
$ make c_chapters
在build/
目录中,您将获得每个章节的可执行文件,例如chap14_chunks
等。同样:
$ make java_chapters
这会将 Java 代码编译为每章子目录中build/gen/
中的类文件。
我有一个完整的 Lox 测试套件,我用它来确保书中的解释器做他们应该做的事情。测试用例位于test/
中。 Dart 程序tool/bin/test.dart
是一个测试运行程序,它在 Lox 解释器上运行每个测试文件,解析结果,并验证测试是否执行了预期的操作。
您可以针对多种解释器运行测试:
$ make test # The final versions of clox and jlox.
$ make test_clox # The final version of clox.
$ make test_jlox # The final version of jlox.
$ make test_c # Every chapter's version of clox.
$ make test_java # Every chapter's version of jlox.
$ make test_all # All of the above.
欢迎您使用测试套件和测试运行器来测试您自己的 Lox 实现。测试运行器位于tool/bin/test.dart
,可以使用--interpreter
为自定义解释器可执行文件提供运行。例如,如果您在my_code/boblox
有一个解释器可执行文件,您可以像这样测试它:
$ dart tool/bin/test.dart clox --interpreter my_code/boblox
您仍然需要告诉它要运行哪一套测试,因为这决定了测试期望。如果您的解释器的行为应类似于 jlox,请使用“jlox”作为套件名称。如果它的行为类似于 clox,请使用“clox”。如果您的解释器只完成了书中某一章的结尾,您可以使用该章作为套件,例如“chap10_functions”。有关所有章节的名称,请参阅 Makefile。
如果您的解释器需要传递其他命令行参数来使用,请使用--arguments
将它们传递给测试运行器,它将转发给您的解释器。
asset/
– 用于生成站点的 Sass 文件和 jinja2 模板。book/
- 每章文本的 Markdown 文件。build/
- 中间文件和其他构建输出(站点本身除外)位于此处。不致力于 Git。c/
– clox 的源代码,用 C 编写的解释器。如果您喜欢的话,还包含一个 XCode 项目。gen/
– 由GenerateAst.java 生成的Java 源文件位于此处。没有承诺。java/
– jlox 的源代码,用 Java 编写的解释器。note/
– 各种研究、笔记、TODO 和其他杂项。note/answers
– 挑战的示例答案。没有作弊!site/
– 最终生成的站点。该目录的内容直接镜像 craftinginterpreters.com。这里的大部分内容都是由 build.py 生成的,但字体、图像和 JS 只存在于这里。一切都已提交,甚至生成的内容也是如此。test/
– Lox 实现的测试用例。tool/
– 包含构建、测试和其他脚本的 Dart 包。