> For the complete documentation index, see [llms.txt](https://ayakaleaf-pro.ayaka.space/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://ayakaleaf-pro.ayaka.space/latex/zh-cn/shen-du-wen-zhang/01-a-new-series-of-articles-tex-tokens-and-related-concepts-but-why-and-how.md).

# 一组关于 TeX Token 及相关概念的新文章——但为什么（以及如何）？

这篇导言文章旨在解释为什么写了这个系列、我希望达到什么目标，并提供一些背景信息，介绍通过观察 TeX 引擎内部工作原理来探究 TeX 记号所使用的技术。该文章页也旨在汇总本系列所有文章的链接，并将在每篇新文章发布时更新这些链接。

### 文章链接

每篇文章都会包含一组指向本系列其他文章的链接。

* [什么是“TeX 记号”？](/latex/zh-cn/shen-du-wen-zhang/53-what-is-a-tex-token.md)
* [什么是“TeX 记号列表”？](/latex/zh-cn/shen-du-wen-zhang/54-what-is-a-tex-token-list.md)

## 本系列文章的背景

写这个系列文章的动机，源于我阅读有关 TeX 的资料，这些资料通过“记号”这一概念，以及 TeX 的“记号化过程”、“记号列表”和相关概念，如“宏展开”和“可展开命令”，来解释 TeX 的许多行为。每当我看到以“TeX 记号”为表述的 TeX 相关解释时，同样的问题总会浮现在脑海：究竟什么是 *是* 一个 TeX 记号？我需要弄清楚。

第一篇文章的范围和内容， [什么是“TeX 记号”？](/latex/zh-cn/shen-du-wen-zhang/53-what-is-a-tex-token.md)从本质上说，正如程序员可能会说的那样，非常“贴近底层”，毫无疑问，“TeX 记号”可以被归类为一个相当深奥的话题：那么为什么还要费这个劲呢？归根结底，你会得出一个看法——或者，或许是一种信念——其他人也可能一直在同一个话题上感到困惑，而且写一两篇文章来填补一些空白是有必要的。我的目标是提供一些有用的背景说明，它们可以与您可能正在阅读的其他材料相互补充，并且希望能更好地帮助理解您在学习 TeX、探索宏和编程时出现的一些关键概念。

显然，在博客文章的范围内，我们只能浅尝辄止——试图解释所有重要主题或深入最晦涩的领域，实际上并不现实。出于必要，我会略过大量细节，并在过度简化与把类比推到极限之间谨慎拿捏分寸。

“写你自己希望读到的文章”是一个有用的指南，而我在撰写本系列时也一直努力践行这一点。

## 既然已经提出了这个问题，那么接下来怎么办？

眼前的挑战很明确：如何了解 TeX 记号，因为这些细节（记号、记号化等）深藏于 TeX 引擎的软件代码之中——其实并不需要你去操心，当然，除非你确实对这些细节感兴趣。

探索并回答这些问题的一种方法，是尝试阅读 TeX 的原始源代码， [`tex.web`](https://www.ctan.org/tex-archive/systems/knuth/dist/tex)——通过运行 [WEAVE](http://tug.org/texinfohtml/web2c.html#weave-invocation) 来提取 TeX 文档——或者购买这本书的副本 [《Computers & Typesetting, Volume B: TeX: The Program》](https://www.amazon.co.uk/Computers-Typesetting-TEX-Program-v/dp/0201134373)。我买了一本印刷版！当然，把 TeX 的源代码以书籍形式出版出来非常有帮助，而且书中也确实处处都有很有用的解释。不过，Knuth 的 TeX 是用 Pascal 编写的，而 Pascal 源代码自然是用 Knuth 的文学编程方法来记录的——把代码分成小块、小口径地呈现。很容易体会到，Knuth 的这种文档编写方式对于像 TeX 这样复杂的软件确实大有裨益，但读这本书确实需要大量交叉引用和来回翻页。

虽然这本书很有帮助，但仅靠它对我来说还不足以更好地理解 TeX 在创建“记号”时究竟发生了什么——这正是我特别感兴趣的话题。要真正弄清楚，只有一种办法：构建 TeX 程序，在一个小型 TeX 文件上执行它，并且在 TeX 扫描和读取输入时，字面意义上地观察代码的执行。关于从源代码构建 TeX 的细节有些深奥——需要把 Pascal 转换为 C——不过下一节有一个简短说明，并附有一个个人博客文章链接，其中会更详细地介绍。

与 XeTeX 和 LuaTeX 不同——后两者可以处理 UTF-8 格式文本并支持 Unicode 文本编码——Knuth 的 TeX 是一个 8 位引擎，这意味着它假定输入字符的范围是 0 到 255。虽然这是一个重要区别，但它并不会 *实质上* 影响我们对 TeX 记号的讨论，因为我们讨论的是所有 TeX 引擎共有的主题和原则：它们正是该软件的核心。

## 如何研究 TeX 记号？

理清从输入文本到 TeX 记号的路径，对我来说是一段相当漫长的旅程——我得坦白，在这一路上，不同程度的困惑几乎一直如影随形：TeX 实在是一款非常复杂的软件。

多年来（大约从 2009 年起），我一直例行从源代码编译最新版本的 LuaTeX——得益于 LuaTeX 源代码的分发方式极其出色，这一过程相当直接。基于这段经验，我开始对如何从源代码构建 Knuth 原始的 TeX 产生兴趣—— *非常* 不同的命题，因为 TeX 是使用 Knuth 的文学编程方法编写的。这个在 Windows 上进行的 TeX 个人构建工程使用的是开源编译器和工具集，且是在 TeX Live 发行版之外完成的，是一个独立项目。它还需要构建用于转换 `tex.web` 为一个 C 程序的工具链，然后该程序可以被编译并在调试器中运行，以查看 TeX 在处理输入字符时实际做了什么。

之所以使用 Knuth 原始的 TeX，而不是 pdfTeX、XeTeX 或 LuaTeX，是因为我需要一个最接近书籍《TeX: The Program》印刷源代码的 TeX 版本。该书最初出版于 1986 年，尽管 TeX 自那时以来已经经历了一些更新，但 TeX 的最新版本（3.14159265，发布于 2014 年 1 月）与书中所包含的源代码当然已经足够接近。

体现 Knuth 的文学编程方法，TeX 的源代码以一种名为 WEB 的文本格式分发：它是 TeX 文档和 Pascal 源代码的混合体。基本思路是使用两个名为 TANGLE 和 WEAVE 的工具，它们处理 WEB 文件，以提取 TeX 文档或 Pascal 源代码：

* [TANGLE](http://tug.org/texinfohtml/web2c.html#tangle-invocation) 从 WEB 文件中提取 Pascal 源代码
* [WEAVE](http://tug.org/texinfohtml/web2c.html#weave-invocation) 从 WEB 文件中提取 TeX 文档

不过，在提取 Pascal 源代码之前，你必须先预处理 Knuth 的 `tex.web` 文件，以应用若干修改，从而通过一种称为 Web2C 的过程将 TeX 的 Pascal 代码转换为 C 代码。这一步预处理被称为 *应用变更文件*.

Knuth 的原始代码文件（tex.web）绝不能以任何方式直接修改；相反，你需要使用所谓的变更文件（扩展名 `.ch`）来应用修改，这些文件包含你希望施加到主 `.web` 文件上的更改——例如 `tex.web`。变更文件会与 Knuth 的原始源代码合并——借助一个额外的实用程序 TIE——从而生成一个文件，比如 `mytex.web` ，然后你用 TANGLE 处理它，把 Pascal 代码提取到 `mytex.pas`。一旦你拥有了合适的 Pascal 源文件，就可以执行 Web2C 过程的最后步骤，将其转换为一个 C 源代码文件，进而编译成可执行的 TeX 程序。如果你想了解相当曲折的 Web2C 转换过程，这位作者的 [个人博客网站](http://www.readytext.co.uk/?p=2529).

最终得到的是一个 TeX 程序，你可以借助免费且优秀的 [Eclipse IDE for C/C++](http://www.eclipse.org/home/index.php) 逐步单步跟踪 TeX 的源代码（C 代码），并观察它在扫描输入时发生了什么。这绝对不是最有趣的消遣，因为 C 代码是机器生成的，而且在某些地方极难跟踪（TeX 的源代码大量使用了 GOTO 和全局变量）。《TeX: The Program》这本书在帮助梳理 C 源代码方面仍然极具价值，尽管书中以排版精美的 Pascal 代码形式包含了 TeX 的源代码。

为了把讨论收个尾，这里有一张示例截图，显示 TeX 通过 Eclipse IDE 运行，执行在函数 `getnext()`处暂停——该函数是 TeX 生成记号过程的核心。

![通过 Eclipse IDE 运行 TeX 的截图](/files/a011bf84cbade04b78844bf1bf942a916e4e6b20)

使用开源 Eclipse IDE for C/C++ 逐步执行 TeX 的 C 源代码。

## 结论与致谢

撰写第一篇文章并为本系列未来的博文整理思路，确实非常耗时。我非常感谢 Overleaf 的 John Hammersley 和 Mary Anne Baynes 对这一系列构想的支持，以及允许我花时间进行额外背景研究。我的希望是，这个系列文章能够成功识别并回应普遍关切的话题，并证明对读者有价值。


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://ayakaleaf-pro.ayaka.space/latex/zh-cn/shen-du-wen-zhang/01-a-new-series-of-articles-tex-tokens-and-related-concepts-but-why-and-how.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
