TeX 總是插入巨集 \par 嗎?

TeX 總是插入巨集 \par 嗎?

當輸入處理器在一行中遇到兩個類別代碼為 5 的字元(換句話說,空白行)時,它會插入巨集\par

\vbox{Abc.}結束時,TeX 結束當前段落,但不是透過插入\par巨集來結束。看起來 TeX 正在插入\par原語。我是否正確理解 TeX 在這種情況下所做的事情? TeX 插入的其他地方怎麼樣\par?什麼時候是宏\par,什麼時候是原語?

\catcode`@=11
\let\@@par\par
\def\par{\typeout{Macro!}\@@par}

Abc.

\vbox{Abc.\tracingall}

答案1

TeX 程式中恰好有 7 個地方 TeX 在內部執行段落構建器,即將水平列表(如果有正在構建的列表)轉換為段落。有時候是這樣的不是透過將\par令牌插入輸入流但透過執行過程結束格拉夫在 TeX 程式的模組 §1096 中實作。

如果 TeX 不處於水平模式,則該程序不執行任何操作;如果處於水平模式但清單為空(TeX 會忽略空段),則該程序或多或少不執行任何操作,並執行該過程越線否則(並且可以實現添加 parfillskip 懲罰等所有魔力)。

這七個地方分別是

  • 在內部垂直結構的末端,例如一個\vbox但也\noalign\vcenter或對齊單元格的右大括號
  • 當原始的par_end被感知(最初在宏觀層面上作為令牌的含義\par
  • 輸出例程 (OR) 結束後立即(因此,在 OR 中開始的任何水平列表都不會繼續使用廚房中的材料,而是單獨形成一個段落)

在這些情況下,都不會\par插入令牌(可能需要重新定義);相反,結束格拉夫程式已執行!

\par僅在處於水平模式並且遇到與水平模式不相容的原語(例如\vskip, \hrule, ... TeX 代碼中的完整列表為 §1094)時才插入標記。當然,在標記化過程中,TeX 將兩個行尾字元替換為\par(即,使空白行等同於\par)。

答案2

根據教材,行尾規則如下

如果 TeX 看到行尾字元(類別 5),它會丟棄可能保留在目前行上的任何其他資訊。那如果 TeX 處於狀態(換行),行尾字元轉換為控制序列標記\par(段落結束);如果 TeX 處於狀態中號(中行),行尾字元被轉換為類別 10(空格)的字元 32 ( ) 的標記;如果 TeX 處於狀態S(跳過空格),行尾字元被簡單地刪除。

這裡,需要注意的是 TeX 插入的是\par標記,而不是\par原語。這意味著\par在所有情況下都必須對其進行定義。 Knuth 在討論強制水平模式的命令時說明了這一點:

< 的出現垂直命令> 在受限水平模式下是禁止的,但在常規水平模式下它會導致 TeX 將標記插入\par到輸入中;讀取並展開此 \par標記後,TeX 將看到 <垂直命令> 再次標記。 (\par將使用 控制序列的當前含義;\par可能不再代表 TeX 的\par原語。)

現在,似乎沒有任何地方提到內部垂直模式結束時發生的情況。顯然,上述規則不允許插入標記,\par因為沒有需要處理的行尾標記。 (如果最後一個材料和盒子末尾\par之間有一個空行,那麼您確實會得到一個插入。)\vbox

\par讀取追蹤輸出,在框的末尾沒有提及原語,但發貨確實顯示

....\penalty 10000
....\glue(\parfillskip) 0.0 plus 1.0fil

當然,顯然已經建立了一個段落。所以我的結論是,內部垂直模式的末尾隱式插入一個\par基元,從而插入通常的段落結尾材料,然後運行段落生成器。

答案3

\parTeX 將 of 的「原始意義」放在 a 的末尾是有原因的\vbox:考慮以下愚蠢的輸入

\vbox{\let\par\empty a}

當 TeX 找到 時},它會備份它,透過插入「原始\par」來終止水平模式,然後重新讀取}關閉內部垂直模式的 。

\par我們可以模擬如果 TeX在重讀}by之前插入當前含義會發生什麼

\vbox{\let\par\empty a\vskip0pt}

因為\vskip插入一個(當前)\par並且 TeX 重新讀取\vskip.結果就是無限循環!

(發現於一個1993年的討論comp.text.tex.)

相關內容