> For the complete documentation index, see [llms.txt](https://overleaf-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://overleaf-pro.ayaka.space/latex/zh-tw/shen-ru-wen-zhang/21-how-does-expandafter-work-tex-uses-temporary-token-lists.md).

# \expandafter 如何運作：TeX 使用暫時詞元清單

[第 1 部分](/latex/zh-tw/shen-ru-wen-zhang/19-how-does-expandafter-work-an-introduction-to-tex-tokens.md) [第 2 部分](/latex/zh-tw/shen-ru-wen-zhang/22-how-does-expandafter-work-the-meaning-of-expansion.md) [第 3 部分](/latex/zh-tw/shen-ru-wen-zhang/21-how-does-expandafter-work-tex-uses-temporary-token-lists.md) [第 4 部分](/latex/zh-tw/shen-ru-wen-zhang/20-how-does-expandafter-work-from-basic-principles-to-exploring-tex-s-source-code.md) [第 5 部分](/latex/zh-tw/shen-ru-wen-zhang/17-how-does-expandafter-work-a-detailed-macro-case-study.md) [第 6 部分](/latex/zh-tw/shen-ru-wen-zhang/18-how-does-expandafter-work-a-detailed-study-of-consecutive-expandafter-commands.md)

## 展開與內部詞元清單

到目前為止，我們已經探討了詞元、詞元清單，以及 TeX 的展開概念背後的核心原理。在本節中，我們將使用 TeX 的原語 `\jobname` 來介紹展開處理的一個重要面向：TeX 對於 *暫存詞元清單*——這是 *基本的* 的一個面向，說明 `\expandafter` 的運作方式，稍後在本系列文章中我們會看到。

`\jobname` 是一個可展開的 TeX 原語，其展開會產生一串字元詞元，這些詞元代表主要輸入 `.tex` 檔案的名稱。例如，假設我們有以下文字，作為 `.tex` 名為 `mycode.tex`:

```
    我的檔名是 \jobname .tex %請注意 \jobname 後面的空格
```

這將排版出

```
    我的檔名是 mycode.tex
```

當我們使用 `\jobname` 這個指令時，所產生的排版字元並不是從你的實體 `.tex` 檔案中讀取的，那它們是從哪裡來的：TeX 會把那些詞元儲存／讀取在哪裡？對使用者而言是看不見的（也就是在 TeX 內部深處）， `\jobname` 會建立一個暫時詞元清單，該清單由代表檔名的一串字元詞元所構成。一旦 `\jobname` 已建立該詞元清單，TeX 就會暫時把「視線」從目前的輸入來源（這裡是我們的 `.tex` 檔案）移開，改為從那個暫時詞元清單讀取詞元（字元詞元）。當 TeX 需要下一個輸入詞元時，它會從該內部清單讀取下一個詞元，並持續如此，直到到達清單尾端；此時 TeX 會恢復從先前的輸入來源讀取詞元，在這裡也就是從我們的 `.tex` 輸入檔案中讀取。

如下圖所示，TeX 會在以下位置恢復讀取 `.tex` 輸入檔案，也就是在處理完 `\jobname`之後停下的精確位置——也就是已讀取空白字元，但尚未讀取「.」字元之前。句點（.）實際上正等待從 TeX 的輸入緩衝區中被讀取——那是 TeX 記憶體中一小塊用來保存從 `.tex` 檔案讀入的一行文字的區域——TeX 會逐行讀取並處理你的 `.tex` 檔案，它不會把整個檔案讀入記憶體。

在研究下圖時，請從底部往上閱讀，以追蹤處理流程。

![TeX 如何展開 \jobname](/files/26c02a8fba87d5e11e01a90c13fdc7941b9abf8a)

回到我們對展開的討論，可以觀察到 `\jobname` 的展開導致了 `\jobname` 指令（詞元）被 *移除* 從輸入中 *被取代* 並以來自展開的詞元取代：生成用來保存 `.tex` 檔案中。

可展開的命令（例如 `\jobname`）並不是唯一會「偷偷地」建立並使用詞元清單來達成效果的 TeX 原語。例如，命令 `\uppercase` 以及 `\lowercase` 都會建立內部詞元清單來變更其引數的大小寫。一旦完成大小寫變更工作，TeX 就會切換成從那些命令所產生的詞元清單讀取字元詞元。詞元清單是 TeX 唯一的「詞元資料儲存」機制——除了把資料寫到實體磁碟檔案之外。

### 詞元的來源：TeX 是個高超的雜耍高手

當 TeX 處理一般文件時，它必須管理 *許多* 個詞元來源：來自眾多實體磁碟檔案的輸入，以及在處理過程中建立的無數內部詞元清單。在本節中，我們將非常簡短地探討 TeX 如何設法「同時拋接」這些輸入來源。

假設我們想要一個簡單的巨集，能排版出我們的 `.tex` 檔案：

```
    \def\myfile{我的檔名是 \jobname .tex}
```

之後，在我們的 `.tex` 檔案中的某個時刻，我們呼叫巨集 `\myfile`：暫時地，TeX 會從透過你文字（`.tex`）檔案中的文字來建立／讀取詞元，切換為從 `\myfile` 儲存在其記憶體中的定義（詞元清單）來讀取詞元。當 TeX 執行 `\myfile` 這個巨集（處理其詞元）時，它會偵測到一個代表 `\jobname` 指令的詞元，其展開又會建立另一個暫時詞元清單，TeX 必須從中讀取詞元。即使在這個簡單情境中，TeX 也必須管理三個輸入來源：

1. 加上 `.tex` 包含該 `\myfile` 巨集的文字檔；
2. 儲存著以下定義的詞元清單： `\myfile` 巨集的文字檔；
3. 由 `\jobname` 命令在 `\myfile` 巨集中建立的詞元清單。

當 TeX 處理文件時，它會不斷在輸入來源之間切換：實體檔案與詞元清單，那麼 TeX 如何追蹤這一切？答案是，在內部，TeX 引擎會維護一個所謂的 [輸入堆疊](https://en.wikipedia.org/wiki/Stack_\(abstract_data_type\)) 它充當某種「記憶」，讓 TeX 在切換輸入來源時，仍能記得自己剛才在做什麼（正從哪裡讀取）。

不深入細節來說，TeX 引擎內部的程式碼會使用一個名為 `curinput` （current input），它除了其他用途之外，還會告訴 TeX 目前是從實體檔案還是從詞元清單讀取。 `curinput` 也會指示 TeX 下一個詞元應從哪個位置取得（在目前詞元清單或其文字緩衝區中）。如果 TeX 正在從詞元清單讀取 `curinput` 還會記錄正在處理的是哪一種詞元清單——例如，儲存為巨集的詞元清單，或那些詞元是否來自其他來源。

在需要時， `curinput` 變數會被改為指向新的輸入來源，而 TeX 目前的「輸入狀態」（來源與位置）會被儲存在輸入堆疊中，以便 TeX 日後能回到那個精確位置（在一個 `.tex` 檔案中的位置，或詞元清單中的下一個詞元）。一旦新的輸入來源耗盡（例如，詞元清單中不再有更多詞元，或已到達檔案末尾），它就會從堆疊中彈出，而 `curinput` 會更新，以確保 TeX 恢復從先前的來源取得詞元。

## 更深入探究（選讀）

以下各節為喜歡細節的讀者提供額外的背景資訊。

### 真正的詞元清單

以下圖示是使用 Overleaf 為 Knuth 的 TeX 自訂編譯版所生成，該版本可存取 TeX 的內部資料與資料結構。這張詞元清單的示意圖建立在前面所示的簡化版本之上，並包含額外資料，例如顯示由 `\jobname` 其類別代碼為 12，而不是一般的 11。在這張圖中，「node」只是 TeX 用來指稱一個記憶體儲存單元的名稱。

![TeX 詞元清單內部](/files/3c766854a062d6dc89dd70ef9c6843c534773d4c)

### TeX 如何讀取並處理 \jobname

另外，為求完整，這裡提供一個 TeX 在偵測到時的「思考過程」概覽 `\jobname` 在我們的輸入中 `.tex` 檔案。在這張圖中，我們可以看到 TeX 如何偵測到跳脫字元（`\\` 其類別代碼為 0），處理字元序列 `jobname`，產生一個詞元，並查找該 `\jobname` 指令的含義，而 TeX 會發現其命令代碼 > 100，表示它是一個可展開命令。

![TeX 如何掃描並處理 \jobname](/files/1f102d2820cd30d672426d35bbbb1f3326d6e438)

[第 1 部分](/latex/zh-tw/shen-ru-wen-zhang/19-how-does-expandafter-work-an-introduction-to-tex-tokens.md) [第 2 部分](/latex/zh-tw/shen-ru-wen-zhang/22-how-does-expandafter-work-the-meaning-of-expansion.md) [第 3 部分](/latex/zh-tw/shen-ru-wen-zhang/21-how-does-expandafter-work-tex-uses-temporary-token-lists.md) [第 4 部分](/latex/zh-tw/shen-ru-wen-zhang/20-how-does-expandafter-work-from-basic-principles-to-exploring-tex-s-source-code.md) [第 5 部分](/latex/zh-tw/shen-ru-wen-zhang/17-how-does-expandafter-work-a-detailed-macro-case-study.md) [第 6 部分](/latex/zh-tw/shen-ru-wen-zhang/18-how-does-expandafter-work-a-detailed-study-of-consecutive-expandafter-commands.md)


---

# 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://overleaf-pro.ayaka.space/latex/zh-tw/shen-ru-wen-zhang/21-how-does-expandafter-work-tex-uses-temporary-token-lists.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.
