TeX 将遇到以下代码的错误:
\documentclass{article}
\test
\begin{document}
\end{document}
它将给出如下消息:
! Undefined control sequence.
<recently read> \test
l.2 \test
我知道这个错误只是由于未定义\test
,但这是什么<recently read>
意思呢?
如果\test
在之后移动\begin{document}
,则不存在这样的事情:
! Undefined control sequence.
l.3 \test
另一个例子是
\documentclass{article}
\begin{document}
a_b
\end{document}
对应的消息<inserted text>
现在变成:
! Missing $ inserted.
<inserted text>
$
l.3 a_
b
第三个例子是\par
论证中的:
\documentclass{article}
\begin{document}
\begin{aa
}
\end{document}
这使<to be read again>
:
Runaway argument?
{aa
! Paragraph ended before \begin was complete.
<to be read again>
\par
l.4
<recently read>
那么,,,等<to be read again>
是什么<inserted text>
意思呢?
答案1
它只是上下文的一部分,类似于l.2
第 2 行。
在任何给定时间,TeX 可能正在从文件中的一行、从终端或读取流之一读取,或者从它之前构建并保存的标记列表(例如,通过从文件中读取)读取。
当打印出错误时,TeX 会打印\errorcontextlines
成对的上下文行,类似于当今编程语言显示的堆栈跟踪。对于打印的每一对上下文行,第一部分(第一行)显示正在打印的内容类型(来自文件的一行,或几种标记列表之一),其余部分(部分在第一行,部分在第二行)显示实际内容。例如,就像:
l.3 a_
b
意味着在第 3 行,TeX 已读取到a_
但尚未读取b
(在发生错误时),类似地
<recently read> \test
(必须成对读取行)表示在<recently read>
标记列表类型中,TeX 已读取到\test
并且尚未读取……好吧,没有什么可读取的了。同样,成对的行
<to be read again>
\par
意思是在<to be read again>
token 列表类型中,TeX 最多只读了 ,还没有读\par
。(当然它已经\par
从输入行读取了,这也是为什么首先创建这个标记列表的原因。)
剩下要说的只是这些不同类型的标记列表是什么。在 TeX 程序中,看 第311条它负责循环并打印所有的行对;参见 §312,其中说打印行的位置或标记列表的类型(在打印行或标记列表的实际内容之前);参见 §313,其中打印行的位置(对于某个 n<*>
为 或<insert>
或<read *>
或<read n>
,对于某个 n 为 或l.n
),最后参见 §314,其中打印标记列表的类型:
其中大部分都是不言自明的。其他的,backed_up
是当 TeX 意识到它读取的内容超出了它正在执行的操作所需的内容时,将“额外”的标记放回输入堆栈,以便下次需要标记时读取。这将打印为<to be read again>
或 ,<recently read>
具体取决于其中是否还有任何内容需要读取。还有inserted
当 TeX 本身为了错误恢复而插入一些您未输入的标记时;这将打印为<inserted text>
。
为了完整起见,让我们更详细地看看问题中的每个例子。
如果你输入了
\documentclass{article}
\test
(后面有一个空行\documentclass{article}
)那么您只会得到:
! Undefined control sequence.
l.3 \test
?
第一行是错误消息,接下来的两行是上下文(l.3
位置在哪里,\test
已经读完,没有剩余内容可读),?
是提示。但是当你输入
\documentclass{article}
\test
你得到
! Undefined control sequence.
<recently read> \test
l.2 \test
?
它有一对额外的上下文行:底部是 ,l.2 \test
没有剩余内容(和之前一样),但上面还有一个包含 的标记列表(由备份创建)\test
(并且这个标记列表也已被完全读取)。为什么?答案是,您可以输入类似的内容\documentclass{article}[2018/09/03]
(看看您是否可以找到这方面的文档),因此在读取 之后\documentclass{article}
,TeX(由于 etc 的定义\documentclass
)仍在寻找 ,[
这时它看到了\test
,并且备份因为它看到的不是[
——它将\test
后面的内容放在输入堆栈上以便再次读取,并完成了扩展宏\documentclass{article}
所需的一切。然后它读取\test
(这次是从标记列表中读取),并向您显示错误。
下一个例子:
\documentclass{article}
\begin{document}
a_b
这很简单:TeX 读取a
,然后读取_
,它应该处于数学模式,无法在当前(水平)模式下处理,因此它将其放回_
输入堆栈以再次读取。然后,出于一种错误的帮助欲望,它插入了一个$
(记住,它还没有真的读取并处理_
,因此实际上插入的$
是之后a
和之前_
),并且在处理之前要求您确认$
:
! Missing $ inserted.
<inserted text>
$
<to be read again>
_
l.3 a_
b
?
这里第一行! Missing $ inserted.
是错误信息,接下来的两行
<inserted text>
$
是输入堆栈的顶部(这是类型的标记列表inserted
,其中没有读取任何内容,还有$
待读取),之后是下一对行
<to be read again>
_
显示接下来有一个要读取的备份令牌列表,之后是下一行
l.3 a_
b
显示从输入文件的第 3 行开始,只剩b
下需要读取的内容。遗憾的是,LaTeX 的默认设置导致只显示第一对和最后一对上下文行,这可能会增加混乱。
最后,你的最后一个例子:
\documentclass{article}
\begin{document}
\begin{aa
}
\end{document}
在向您展示未结束的标记列表参数之后{aa
,TeX 会显示错误消息和上下文:
! Paragraph ended before \begin was complete.
<to be read again>
\par
l.4
?
在错误消息之后,第一对行再次显示,之后的空白行aa
(被视为\par
标记)已被放回到输入堆栈中以供下一步读取,但尚未读取,同样,在第 4 行上没有任何内容被读取并且没有任何剩余。
所以你看 TeX 的错误信息结构相当好,只是为了理解这个结构你需要非常好的视力并且即使在手册没有解释清楚的地方也要仔细阅读手册。:-)