
Wenn der Eingabeprozessor auf zwei Zeichen mit dem Kategoriecode 5 hintereinander stößt (also auf eine leere Zeile), fügt er das \par
Makro ein.
Wenn \vbox{Abc.}
„ends“ erscheint, beendet TeX den aktuellen Absatz, aber nicht durch Einfügen des \par
Makros. Es scheint, dass TeX stattdessen das Primitiv einfügt \par
. Verstehe ich richtig, was TeX in diesem Fall macht? Was ist mit anderen Stellen, an denen TeX „einfügt“ \par
? Wann ist es das Makro \par
und wann das Primitiv?
\catcode`@=11
\let\@@par\par
\def\par{\typeout{Macro!}\@@par}
Abc.
\vbox{Abc.\tracingall}
Antwort1
Es gibt genau 7 Stellen im TeX-Programm, an denen TeX intern den Absatzgenerator ausführt, d. h. eine horizontale Liste (falls eine erstellt wird) in einen Absatz umwandelt. Dies geschiehtnichtdurch Einfügen eines \par
Tokens in den Eingabestrom, sondern durch Ausführen der Prozedurend_grafimplementiert im Modul §1096 im TeX-Programm.
Diese Prozedur tut nichts, wenn TeX nicht im horizontalen Modus ist, mehr oder weniger nichts, wenn sie im horizontalen Modus ist, aber eine leere Liste hat (Null-Absätze werden von TeX ignoriert) und führt die Prozedur ausZeilenumbruchandernfalls (und dieses erledigt die ganze Magie beim Hinzufügen von Parfillskip-Strafen usw.).
Die sieben Orte sind
- am Ende der internen vertikalen Strukturen wie die schließende Klammer eines
\vbox
aber auch\noalign
oder\vcenter
oder eine Ausrichtungszelle - wenn das Primitivepar_endewahrgenommen wird (was auf der Makroebene zunächst als Bedeutung des Tokens vorliegt
\par
) - unmittelbar nachdem eine Ausgaberoutine (OR) beendet wurde (daher wird jede in der OR begonnene horizontale Liste nicht mit Material aus der Druckfahne fortgesetzt, sondern bildet einen eigenen Absatz)
In keinem dieser Fälle wird ein \par
Token eingefügt (das möglicherweise neu definiert werden muss); stattdessen wird dasend_grafProzedur wird ausgeführt!
\par
Token werden nur im horizontalen Modus eingefügt und es werden Grundelemente gefunden, die mit dem horizontalen Modus nicht kompatibel sind (wie \vskip
, \hrule
, ... die vollständige Liste ist §1094 im TeX-Code). Und natürlich im Tokenisierungsprozess, wenn TeX zwei Endzeilenzeichen durch ersetzt \par
(d. h. leere Zeilen werden gleichwertig mit \par
).
Antwort2
EntsprechendDas TeXbooklautet die Regel für Zeilenenden wie folgt
Wenn TeX ein Zeilenendezeichen (Kategorie 5) erkennt, verwirft es alle anderen Informationen, die in der aktuellen Zeile verbleiben könnten. Wenn TeX sich dann im ZustandN(neue Zeile), wird das Zeilenendezeichen in das Kontrollsequenz-Token
\par
(Absatzende) umgewandelt; wenn TeX sich im ZustandM(Zeilenmitte) wird das Zeilenendezeichen in ein Token für Zeichen 32 ( ) der Kategorie 10 (Leerzeichen) umgewandelt; und wenn TeX sich im ZustandS(Leerzeichen überspringen), das Zeilenendezeichen wird einfach gelöscht.
Dabei ist zu beachten, dass TeX das \par
Token einfügt und nicht das \par
Primitiv. Das heißt, dass dieses \par
unter allen Umständen definiert werden muss. Knuth veranschaulicht diesen Punkt, wenn er Befehle erläutert, die den horizontalen Modus erzwingen:
Das Erscheinen eines <vertikaler Befehl
\par
> ist im eingeschränkten horizontalen Modus verboten, aber im normalen horizontalen Modus führt es dazu, dass TeX das Token in die Eingabe einfügt ; nach dem Lesen und Erweitern dieses\par
Tokens sieht TeX das <vertikaler Befehl> Token erneut. (Die aktuelle Bedeutung der Steuersequenz\par
wird verwendet;\par
steht möglicherweise nicht mehr für das TeX-\par
Primitiv.)
Was nun nirgends erwähnt zu sein scheint, ist, was am Ende des internen vertikalen Modus passiert. Offensichtlich erlauben die obigen Regeln nicht das Einfügen eines \par
Tokens, da es keine Zeilenende-Markierungen gibt, mit denen man umgehen muss. (Sie erhalten ein Einfügen, wenn sich zwischen dem letzten Material und dem Ende der Box \par
eine leere Zeile befindet .)\vbox
Beim Lesen der Trace-Ausgabe wird das \par
Primitiv am Ende der Box nicht erwähnt, aber der Shipout zeigt
....\penalty 10000
....\glue(\parfillskip) 0.0 plus 1.0fil
und natürlich ist eindeutig ein Absatz aufgebaut. Meine Schlussfolgerung ist also, dass das Ende des internen vertikalen Modus implizit ein \par
Primitiv einfügt und somit das übliche Material am Ende des Absatzes einfügt und dann den Absatzgenerator ausführt.
Antwort3
Es gibt einen Grund, warum TeX die „ursprüngliche Bedeutung“ von \par
an das Ende eines setzt \vbox
: Betrachten Sie die folgende alberne Eingabe
\vbox{\let\par\empty a}
Wenn TeX findet }
, sichert es es, beendet den horizontalen Modus durch Einfügen des „Originals \par
“ und liest dann das erneut, }
wodurch der interne vertikale Modus geschlossen wird.
Wir können nachahmen, was passieren würde, wenn TeX die aktuelle Bedeutung von \par
vor dem erneuten Lesen }
von einfügen würde.
\vbox{\let\par\empty a\vskip0pt}
weil \vskip
ein (aktuelles) eingefügt wird \par
und TeX es erneut liest \vskip
. Das Ergebnis ist eine Endlosschleife!
(Gefunden in einem1993 Diskussion übercomp.text.tex
.)