我期望(见下面的背景材料)有以下 Plain TeX 手稿
a^^Mb\bye
相当于
a
b\bye
因此排版如下:
AB
相反,pdftex 在编译过程中暂停,并将以下内容写入控制台:
entering extended mode
(./test29.tex)
*
为什么?
背景材料
TeXbook(第 20 次印刷,Addison-Wesley 1991)描述了它的含义^^
以及它是如何被处理的,如下所示。
在第45页:
TEX 有一种标准方法来引用 ASCII 的不可见字符:代码 0 可以输入为三个字符的序列
^^@
,代码 1 可以输入^^A
,依此类推,直到代码 31,即^^_
(参见附录 C)。如果后面的字符^^
有 64 到 127 之间的内部代码,TEX 会从代码中减去 64;如果代码在 0 到 63 之间,TEX 会加上 64。因此可以输入代码 127^^?
[...]^^
符号甚至可以用作控制字中的字母。[...]
还有一个特殊约定,其中
^^
后面跟着两个“小写十六进制数字”,0
即9
-a
。f
根据此约定,所有 256 个字符都以统一的方式获得,从^^00
到^^ff
。字符 127 是^^7f
。
^^
除了特殊应用外,大多数代码并不重要。但特别值得注意的是,它是代码 13,即 TEX 通常放在输入文件每行右端的^^M
ASCII 。<return>
第 46-47 页:
如果 TEX 在任何状态下看到上标字符 (类别 7),并且该字符后跟另一个相同的字符,并且这两个相等的字符后跟一个代码 c < 128 的字符,则删除它们并在代码 c 上加 64 或减 64。(因此,
^^A
被替换为代码为 1 的单个字符,等等,如前所述。)但是,如果两个上标字符后紧跟两个小写十六进制数字 0123456789abcdef,则四个字符的序列被替换为具有指定十六进制代码的单个字符。[...] 替换完成后,TEX 重新开始,就好像新字符一直存在一样。
答案1
你忘记了 TeX 可以在线。通过插入^^M
输入行的一部分,其余部分将被忽略:TeX(在宏级别)永远不会看到,因此会B\bye
在“等待更多输入”提示处停止。添加\tracingall
并可能\bye
在换行符上停留一秒钟即可看到这一点。
答案2
TeXbook 第 47 页,第二个双重危险段落:
如果 TeX 遇到行尾字符(类别 5),它会丢弃当前行中可能保留的任何其他信息。然后如果 TeX 处于状态否(新行),行尾字符转换为控制序列标记'平价'(段落结束);如果 TeX 处于状态米(中间行),行尾字符被转换为类别 10(空格)的字符 32(“⍽”)的标记;并且如果 TeX 处于状态年代(跳过空格),行尾字符被删除。
类别代码 5 字符通常在读取阶段插入,即 TeX 吸收记录(一行输入)时,但最后任何类别代码5的字符遵循上述规则。
该^^
约定允许您明确输入类别代码 5 的字符,这会使 TeX 应用所述规则。也会^^0d
做同样的事情。
和平价我表示 TeXbook 盒子里的东西,也就是具有该名称的控制序列标记,与原始的 不同\par
。
TeX 不会“进入扩展模式”:日志文件中显示的注释位于任何输入之前,您可以从左括号中推断出关注注释。它只是告诉您已包含 e-TeX 扩展(实际上它们已在格式创建过程中包含)。
星号表示“交互模式”,提示需要更多输入,因为 TeX 已结束读取您在命令行中指定的文件,这可以从文件名后面的括号中推断出来。如果您调用pdftex -interaction=nonstopmode test29.tex
控制台,则将显示
entering extended mode
(./test29.tex)
! Emergency stop.
<*> test29
其中<*>
传达的信息是相同的:TeX 需要输入,并且处于非停止模式,因此它会停止。
答案3
在解释你的两个例子中发生的情况之前,我尝试描述 TeX 如何处理 .tex 文件的一些方面:
在 Donald Knuth 的 TeXbook 中,TeX 被比作一个有眼睛和消化道的生物:
- 眼睛 ⇆ 2. 嘴 ⇆ 3. 食道 ⇆ 4. 胃及后续消化器官
眼睛“查看”.tex 文件的整行并对其进行预处理:
- 每个字符都转换为 TeX 的内部字符表示方案(ASCII 或 unicode)。
- 该行最右端的所有空格字符均被删除。
- 在行的右端附加一个字符,其编码点在 TeX 内部字符表示方案中的编号等于整数参数 的值
\endlinechar
。 的值\endlinechar
通常为 13,表示⟨回车符⟩。
眼睛将得到的整个字符序列一次性传递到嘴里。仅当嘴巴请求字符时,眼睛才会这样做。
嘴巴与眼睛和食道相连。当食道请求一个标记时,嘴巴就会产生一个标记并将其传送到食道。在产生标记的过程中,嘴巴会使用/“咀嚼”其中的一些字符。
当嘴巴空了并且需要字符时,它会再次向眼睛请求一个字符序列。然后眼睛查看 .tex 文件的下一行并对其进行预处理,并将整个生成的字符序列一次性传送到嘴巴。嘴巴变空的一种可能性是,嘴巴遇到了行尾字符,即当前类别代码为 5 的字符:然后嘴巴丢弃/扔掉那些源自被 TeX 的眼睛视为最后一行/预处理的行并且还未用于创建标记的字符。
TeXbook中提到了这种可能性:
如果 TeX 看到行尾字符(类别 5),它会丢弃当前行上可能保留的任何其他信息。然后,如果 TeX 处于状态 N(新行),则行尾字符将转换为控制序列标记“par”(段落结束);如果 TeX 处于状态 M(行中),则行尾字符将转换为类别 10(空格)的字符 32(“⍽”)的标记;如果 TeX 处于状态 S(跳过空格),则行尾字符将被删除。
眼睛所做的与 TeX 的“token”概念无关。眼睛所做的与 .tex 输入文件的字符有关。下一个消化站,即嘴巴,是 TeX 的“token”概念开始发挥作用的第一个站。您需要区分 .tex 输入文件的“字符”和“字符 token”。 进一步存在于 .tex 文件中,其行由 TeX 的眼睛“查看”并预处理。只要 .tex 文件存在,进一步,即字符,就会存在。作为 TeX 眼睛预处理的结果,在 TeX 运行时,转换为 TeX 内部字符表示方案的进一步副本存在于 TeX 的嘴巴中。后者,即字符 token,是根据 TeX 的阅读装置给出的规则和 catcodes 和 等参数值在 TeX 的嘴巴中创建的数据结构
\endlinechar
。它们由字符代码和类别等属性组成,并且仅在 TeX 运行时存在。除了不同类型的字符标记之外,嘴巴还会产生控制序列标记,即这些“反斜杠”,例如\section
或\LaTeX
。还要注意短语“catcode”和“category”之间的细微差别。使用短语“catcode”时,我倾向于指 TeX 的嘴在创建标记时遵循的一组规则。您可以通过
\catcode
-assignments 更改规则,例如,在\catcode`\A=11\relax
TeX 的嘴遇到字符后,A
将产生类别 11(字母)的字符标记,即。使用短语“category”时,我倾向于指字符标记的相应属性。即,字符标记的类别为 11(字母)。此类别是固定不变的。它是固定的,不会再改变。它是 11,因为在 TeX 的嘴标记相应的字符时,字符的 catcode是 11。A11
A11
A
A
食道会膨胀可膨胀的代币。当胃部向食道请求代币而食道本身的代币用完时,食道就会向嘴部请求代币。通过食道或因膨胀而产生的代币最终会进入请求它们的胃部。
然后,胃和随后的消化器官使用这些标记作为指令来执行任务、改变模式(水平/垂直/数学)、构建框、线条、段落、页面、创建消息和输出文件等。
了解了这些知识后,我们来看一下这句话:
a^^Mb\bye
TeX 的眼睛看着那行并根据上面描述的规则对其进行预处理。预处理产生以下字符(还不是标记!!!):
a^^Mb\bye⟨carriage‑return character⟩
这些字符被传递到 TeX 的嘴里,在那里根据需要一个接一个地产生标记:
a
有 catcode 11(字母),因此 TeX 的嘴巴产生了一个明确的字符 -令牌 a11
并将其送入 TeX 的“食道”进行进一步处理。同时 TeX 的读取装置切换到状态 M(中线)。(食道是可扩展标记被扩展的地方。食道工作产生的标记根据需要被送入胃和其他消化器官,并构建框和页面,执行任务,创建输出文件和消息等。)
当处理时,TeX 需要更多的标记。a11
TeX 嘴里剩下的字符(还不是标记)源自 TeX 眼睛对单行代码的预处理,它们是:
^^Mb\bye⟨carriage‑return character⟩
TeX 的嘴巴接受a 的^^M
-notation序列^^
⟨回车符⟩。 这⟨回车符⟩通常有 catcode 5(行尾)。
TeXbook 关于 catcode 5 的字符的说明:
如果 TeX 看到行尾字符(类别 5),它会丢弃当前行上可能保留的任何其他信息。然后,如果 TeX 处于状态 N(新行),则行尾字符将转换为控制序列标记“par”(段落结束);如果 TeX 处于状态 M(行中),则行尾字符将转换为类别 10(空格)的字符 32(“⍽”)的标记;如果 TeX 处于状态 S(跳过空格),则行尾字符将被删除。
因此,TeX 嘴里剩余的字符(还不是标记)源自 TeX 眼睛对单行的预处理,它们被丢弃,并且由于 TeX 的读取装置处于状态 M(中行),因此显式空格标记(字符代码 32,类别 10(空格))被送入 TeX 的食道。当显式空格标记被送入 TeX 的食道时,读取装置切换到状态 S(跳过空格)。由于“当前行的剩余部分”被丢弃,切换到状态 S(跳过空格)并不重要:TeX 将不得不开始处理另一行输入 - 因此读取装置将切换到状态 N(新行)。
因此,它被 TeX 的嘴巴扔掉了,而不是被处理/而不是被转换成可以进一步处理的标记。b\bye⟨carriage‑return character⟩
现在有以下情况:
当工作尚未完成且没有其他 .tex 输入文件可供读取时,TeX 的眼睛无法在 .tex 输入文件中找到任何输入行。
由于没有待处理的字符可能源自预处理另一个 .tex 输入文件的一行(当一行包含 -directive
\input
或类似内容后跟其他内容时可能是这种情况),因此 TeX 的口是空的。
因此 TeX 的眼睛看着控制台:换句话说:TeX 切换到交互模式,以便用户可以通过键盘输入更多行输入,例如完成工作的命令,或输入其他 .tex 文件的命令,等等。因此,一开始读取器就切换到状态 N(新行)。
让我们看看这两行
a
b\bye
第一行是预处理的。你得到的是字符序列(还不是标记!)
a⟨carriage‑return character⟩
现在开始对这些字符进行标记:
a
有 catcode 11(字母),因此 TeX 生成一个显式字符 -令牌 a11
并将其送入 TeX 的“喉咙”进行进一步处理。同时 TeX 的读取器切换到状态 M(中线)。
该行的其余字符为:
⟨carriage‑return character⟩
这⟨回车符⟩通常有 catcode 5(行尾)。
TeXbook 关于 catcode 5 的字符的说明:
如果 TeX 看到行尾字符(类别 5),它会丢弃当前行上可能保留的任何其他信息。然后,如果 TeX 处于状态 N(新行),则行尾字符将转换为控制序列标记“par”(段落结束);如果 TeX 处于状态 M(行中),则行尾字符将转换为类别 10(空格)的字符 32(“⍽”)的标记;如果 TeX 处于状态 S(跳过空格),则行尾字符将被删除。
因此,该行的剩余字符(在本例中只有⟨回车符⟩) 被丢弃,而由于 TeX 的读取装置处于状态 M(中线),因此显式空格标记(字符代码 32,类别 10(空格))被送入 TeX 的喉咙。然后读取装置切换到状态 S(跳过空白)。
作业尚未完成,也未到达文件末尾。
因此第二行经过了预处理。你得到的是字符序列(还不是标记!)
b\bye⟨carriage‑return character⟩
阅读器切换到状态 N(新行)。
b
具有 catcode 11(字母),因此 TeX 生成一个显式字符令牌 b11
并将其送入 TeX 的“喉咙”进行进一步处理。同时 TeX 的读取器切换到状态 M(中线)。
剩余的字符序列(还不是标记!)是:
\bye⟨carriage‑return character⟩
由于反斜杠的 catcode 为 0(转义),因此表示要收集控制序列标记,并且后面的b
catcode 被分配为 11(字母),因此 TeX 开始收集字符,直到到达 catcode 不是 11(字母)的字符或到达行的最后一个字符。收集到的字符被用作控制字标记的名称,然后将其发送到 TeX 的管道进行进一步处理。
因此,控制字标记\bye
被送入 TeX 的喉咙进行进一步处理,而字符序列⟨carriage‑return character⟩
仍留在 TeX 的嘴里。
在对控制字标记进行标记后,读取设备切换到状态 S(跳过空白)。
标记的处理\bye
导致作业结束。因此,⟨carriage‑return character⟩
TeX 口中的剩余部分不会被处理。