
當輸入處理器在一行中遇到兩個類別代碼為 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
\par
TeX 將 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
.)